diff --git a/.github/actions/cache-query-compilation/action.yml b/.github/actions/cache-query-compilation/action.yml index 2a0358ae63c..0ad0b7da982 100644 --- a/.github/actions/cache-query-compilation/action.yml +++ b/.github/actions/cache-query-compilation/action.yml @@ -9,7 +9,7 @@ inputs: outputs: cache-dir: description: "The directory where the cache was stored" - value: ${{ steps.fill-compilation-dir.outputs.compdir }} + value: ${{ steps.output-compilation-dir.outputs.compdir }} runs: using: composite @@ -27,7 +27,9 @@ runs: if: ${{ github.event_name == 'pull_request' }} uses: actions/cache/restore@v3 with: - path: '**/.cache' + path: | + **/.cache + ~/.codeql/compile-cache key: codeql-compile-${{ inputs.key }}-pr-${{ github.sha }} restore-keys: | codeql-compile-${{ inputs.key }}-${{ github.base_ref }}-${{ env.merge_base }} @@ -37,18 +39,111 @@ runs: if: ${{ github.event_name != 'pull_request' }} uses: actions/cache@v3 with: - path: '**/.cache' + path: | + **/.cache + ~/.codeql/compile-cache key: codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-${{ github.sha }} # just fill on main restore-keys: | # restore the latest cache if the exact cache is unavailable, to speed up compilation. codeql-compile-${{ inputs.key }}-${{ github.ref_name }}- codeql-compile-${{ inputs.key }}-main- - - name: Fill compilation cache directory - id: fill-compilation-dir + - name: Output-compilationdir + id: output-compilation-dir shell: bash run: | - # Move all the existing cache into another folder, so we only preserve the cache for the current queries. - node $GITHUB_WORKSPACE/.github/actions/cache-query-compilation/move-caches.js ${COMBINED_CACHE_DIR} - echo "compdir=${COMBINED_CACHE_DIR}" >> $GITHUB_OUTPUT env: COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir + - name: Fill compilation cache directory + id: fill-compilation-dir + uses: actions/github-script@v6 + env: + COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir + with: + script: | + // # Move all the existing cache into another folder, so we only preserve the cache for the current queries. + // mkdir -p ${COMBINED_CACHE_DIR} + // rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty. + // # copy the contents of the .cache folders into the combined cache folder. + // cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files + // # clean up the .cache folders + // rm -rf **/.cache/* + + const fs = require("fs"); + const path = require("path"); + const os = require("os"); + + // the first argv is the cache folder to create. + const COMBINED_CACHE_DIR = process.env.COMBINED_CACHE_DIR; + + function* walkCaches(dir) { + const files = fs.readdirSync(dir, { withFileTypes: true }); + for (const file of files) { + if (file.isDirectory()) { + const filePath = path.join(dir, file.name); + yield* walkCaches(filePath); + if (file.name === ".cache") { + yield filePath; + } + } + } + } + + async function copyDir(src, dest) { + for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) { + const srcPath = path.join(src, file.name); + const destPath = path.join(dest, file.name); + if (file.isDirectory()) { + if (!fs.existsSync(destPath)) { + fs.mkdirSync(destPath); + } + await copyDir(srcPath, destPath); + } else { + await fs.promises.copyFile(srcPath, destPath); + } + } + } + + async function main() { + const cacheDirs = [...walkCaches(".")]; + + for (const dir of cacheDirs) { + console.log(`Found .cache dir at ${dir}`); + } + + const globalCacheDir = path.join(os.homedir(), ".codeql", "compile-cache"); + if (fs.existsSync(globalCacheDir)) { + console.log("Found global home dir: " + globalCacheDir); + cacheDirs.push(globalCacheDir); + } + + if (cacheDirs.length === 0) { + console.log("No cache dirs found"); + return; + } + + // mkdir -p ${COMBINED_CACHE_DIR} + fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true }); + + // rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty. + await Promise.all( + cacheDirs.map((cacheDir) => + (async function () { + await fs.promises.rm(path.join(cacheDir, "lock"), { force: true }); + await fs.promises.rm(path.join(cacheDir, "size"), { force: true }); + })() + ) + ); + + // # copy the contents of the .cache folders into the combined cache folder. + // cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files + await Promise.all( + cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR)) + ); + + // # clean up the .cache folders + // rm -rf **/.cache/* + await Promise.all( + cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true })) + ); + } + main(); diff --git a/.github/actions/cache-query-compilation/move-caches.js b/.github/actions/cache-query-compilation/move-caches.js deleted file mode 100644 index 67fc503cdc0..00000000000 --- a/.github/actions/cache-query-compilation/move-caches.js +++ /dev/null @@ -1,75 +0,0 @@ -// # Move all the existing cache into another folder, so we only preserve the cache for the current queries. -// mkdir -p ${COMBINED_CACHE_DIR} -// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty. -// # copy the contents of the .cache folders into the combined cache folder. -// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files -// # clean up the .cache folders -// rm -rf **/.cache/* - -const fs = require("fs"); -const path = require("path"); - -// the first argv is the cache folder to create. -const COMBINED_CACHE_DIR = process.argv[2]; - -function* walkCaches(dir) { - const files = fs.readdirSync(dir, { withFileTypes: true }); - for (const file of files) { - if (file.isDirectory()) { - const filePath = path.join(dir, file.name); - yield* walkCaches(filePath); - if (file.name === ".cache") { - yield filePath; - } - } - } -} - -async function copyDir(src, dest) { - for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) { - const srcPath = path.join(src, file.name); - const destPath = path.join(dest, file.name); - if (file.isDirectory()) { - if (!fs.existsSync(destPath)) { - fs.mkdirSync(destPath); - } - await copyDir(srcPath, destPath); - } else { - await fs.promises.copyFile(srcPath, destPath); - } - } -} - -async function main() { - const cacheDirs = [...walkCaches(".")]; - - for (const dir of cacheDirs) { - console.log(`Found .cache dir at ${dir}`); - } - - // mkdir -p ${COMBINED_CACHE_DIR} - fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true }); - - // rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty. - await Promise.all( - cacheDirs.map((cacheDir) => - (async function () { - await fs.promises.rm(path.join(cacheDir, "lock"), { force: true }); - await fs.promises.rm(path.join(cacheDir, "size"), { force: true }); - })() - ) - ); - - // # copy the contents of the .cache folders into the combined cache folder. - // cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files - await Promise.all( - cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR)) - ); - - // # clean up the .cache folders - // rm -rf **/.cache/* - await Promise.all( - cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true })) - ); -} -main(); diff --git a/.github/workflows/compile-queries.yml b/.github/workflows/compile-queries.yml index 96d8e4cc30b..ac63af81ccd 100644 --- a/.github/workflows/compile-queries.yml +++ b/.github/workflows/compile-queries.yml @@ -24,14 +24,14 @@ jobs: with: key: all-queries - name: check formatting - run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 codeql query format --check-only + run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only - name: compile queries - check-only # run with --check-only if running in a PR (github.sha != main) if : ${{ github.event_name == 'pull_request' }} shell: bash - run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" + run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" - name: compile queries - full # do full compile if running on main - this populates the cache if : ${{ github.event_name != 'pull_request' }} shell: bash - run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" + run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" diff --git a/.github/workflows/go-tests-other-os.yml b/.github/workflows/go-tests-other-os.yml index edf6eb63d49..97207f573c0 100644 --- a/.github/workflows/go-tests-other-os.yml +++ b/.github/workflows/go-tests-other-os.yml @@ -12,10 +12,10 @@ jobs: name: Test MacOS runs-on: macos-latest steps: - - name: Set up Go 1.19 + - name: Set up Go 1.20 uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.20.0 id: go - name: Check out code @@ -47,10 +47,10 @@ jobs: name: Test Windows runs-on: windows-latest-xl steps: - - name: Set up Go 1.19 + - name: Set up Go 1.20 uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.20.0 id: go - name: Check out code diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index eceabb0410a..4cf299e5e44 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -20,10 +20,10 @@ jobs: name: Test Linux (Ubuntu) runs-on: ubuntu-latest-xl steps: - - name: Set up Go 1.19 + - name: Set up Go 1.20 uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.20.0 id: go - name: Check out code diff --git a/.github/workflows/ql-for-ql-build.yml b/.github/workflows/ql-for-ql-build.yml index 8b6e7a56946..49d73d60fc5 100644 --- a/.github/workflows/ql-for-ql-build.yml +++ b/.github/workflows/ql-for-ql-build.yml @@ -5,13 +5,6 @@ on: branches: [main] pull_request: branches: [main] - paths: - - "ql/**" - - "**.qll" - - "**.ql" - - "**.dbscheme" - - "**/qlpack.yml" - - ".github/workflows/ql-for-ql-build.yml" env: CARGO_TERM_COLOR: always @@ -22,6 +15,8 @@ jobs: steps: ### Build the queries ### - uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Find codeql id: find-codeql uses: github/codeql-action/init@v2 @@ -34,7 +29,9 @@ jobs: id: cache-extractor uses: actions/cache@v3 with: - path: ql/extractor-pack/ + path: | + ql/extractor-pack/ + ql/target/release/buramu key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }} - name: Cache cargo if: steps.cache-extractor.outputs.cache-hit != 'true' @@ -57,6 +54,7 @@ jobs: key: run-ql-for-ql - name: Make database and analyze run: | + ./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse. ${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB} ${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" env: @@ -65,6 +63,7 @@ jobs: LGTM_INDEX_FILTERS: | exclude:ql/ql/test exclude:*/ql/lib/upgrades/ + exclude:java/ql/integration-tests - name: Upload sarif to code-scanning uses: github/codeql-action/upload-sarif@v2 with: diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index de0f11f0521..806e04e6c68 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -5,6 +5,7 @@ on: paths: - "swift/**" - "misc/bazel/**" + - "misc/codegen/**" - "*.bazel*" - .github/workflows/swift.yml - .github/actions/** @@ -19,6 +20,7 @@ on: paths: - "swift/**" - "misc/bazel/**" + - "misc/codegen/**" - "*.bazel*" - .github/workflows/swift.yml - .github/actions/** diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f35c2c183b..e612a423462 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,5 +53,5 @@ repos: name: Run Swift code generation unit tests files: ^swift/codegen/.*\.py$ language: system - entry: bazel test //swift/codegen/test + entry: bazel test //misc/codegen/test pass_filenames: false diff --git a/CODEOWNERS b/CODEOWNERS index 42fb364418f..8371dd768cd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,10 +2,11 @@ /csharp/ @github/codeql-csharp /go/ @github/codeql-go /java/ @github/codeql-java -/javascript/ @github/codeql-javascript -/python/ @github/codeql-python -/ruby/ @github/codeql-ruby +/javascript/ @github/codeql-dynamic +/python/ @github/codeql-dynamic +/ruby/ @github/codeql-dynamic /swift/ @github/codeql-swift +/misc/codegen/ @github/codeql-swift /java/kotlin-extractor/ @github/codeql-kotlin /java/kotlin-explorer/ @github/codeql-kotlin diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs index def45890c9f..846d8333030 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs @@ -131,6 +131,14 @@ namespace Semmle.Autobuild.Cpp.Tests bool IBuildActions.IsWindows() => IsWindows; + public bool IsMacOs { get; set; } + + bool IBuildActions.IsMacOs() => IsMacOs; + + public bool IsArm { get; set; } + + bool IBuildActions.IsArm() => IsArm; + string IBuildActions.PathCombine(params string[] parts) { return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p))); diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index 387f55a3e2e..319e78ac20b 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +No user-facing changes. + ## 0.5.2 No user-facing changes. diff --git a/cpp/ql/lib/change-notes/released/0.5.3.md b/cpp/ql/lib/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..e97503053f0 --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.5.3.md @@ -0,0 +1,3 @@ +## 0.5.3 + +No user-facing changes. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 239e5ad0055..ee8b5187961 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.5.3-dev +version: 0.5.4-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index 8b2bc6c1be0..f0364b77bab 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +No user-facing changes. + ## 0.5.2 No user-facing changes. diff --git a/cpp/ql/src/change-notes/released/0.5.3.md b/cpp/ql/src/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..e97503053f0 --- /dev/null +++ b/cpp/ql/src/change-notes/released/0.5.3.md @@ -0,0 +1,3 @@ +## 0.5.3 + +No user-facing changes. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index fb977480f05..025587014e6 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.5.3-dev +version: 0.5.4-dev groups: - cpp - queries diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs index df362c2a129..ec7c63a022d 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs @@ -145,6 +145,14 @@ namespace Semmle.Autobuild.CSharp.Tests bool IBuildActions.IsWindows() => IsWindows; + public bool IsMacOs { get; set; } + + bool IBuildActions.IsMacOs() => IsMacOs; + + public bool IsArm { get; set; } + + bool IBuildActions.IsArm() => IsArm; + public string PathCombine(params string[] parts) { return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p))); diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs index 1cf1d6253a5..f3f9ae15da6 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs @@ -7,6 +7,7 @@ using System.Xml; using System.Net.Http; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; +using System.Runtime.InteropServices; namespace Semmle.Autobuild.Shared { @@ -98,6 +99,18 @@ namespace Semmle.Autobuild.Shared /// bool IsWindows(); + /// + /// Gets a value indicating whether we are running on macOS. + /// + /// True if we are running on macOS. + bool IsMacOs(); + + /// + /// Gets a value indicating whether we are running on arm. + /// + /// True if we are running on arm. + bool IsArm(); + /// /// Combine path segments, Path.Combine(). /// @@ -203,6 +216,12 @@ namespace Semmle.Autobuild.Shared bool IBuildActions.IsWindows() => Win32.IsWindows(); + bool IBuildActions.IsMacOs() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + + bool IBuildActions.IsArm() => + RuntimeInformation.ProcessArchitecture == Architecture.Arm64 || + RuntimeInformation.ProcessArchitecture == Architecture.Arm; + string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts); void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents); diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs index 77f2f70f718..56858cc87a2 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs @@ -1,18 +1,36 @@ using Semmle.Util.Logging; +using System; using System.Linq; +using System.Runtime.InteropServices; namespace Semmle.Autobuild.Shared { + internal static class MsBuildCommandExtensions + { + /// + /// Appends a call to msbuild. + /// + /// + /// + /// + public static CommandBuilder MsBuildCommand(this CommandBuilder cmdBuilder, IAutobuilder builder) + { + var isArmMac = builder.Actions.IsMacOs() && builder.Actions.IsArm(); + + // mono doesn't ship with `msbuild` on Arm-based Macs, but we can fall back to + // msbuild that ships with `dotnet` which can be invoked with `dotnet msbuild` + // perhaps we should do this on all platforms? + return isArmMac ? + cmdBuilder.RunCommand("dotnet").Argument("msbuild") : + cmdBuilder.RunCommand("msbuild"); + } + } + /// /// A build rule using msbuild. /// public class MsBuildRule : IBuildRule { - /// - /// The name of the msbuild command. - /// - private const string msBuild = "msbuild"; - public BuildScript Analyse(IAutobuilder builder, bool auto) { if (!builder.ProjectsOrSolutionsToBuild.Any()) @@ -57,7 +75,7 @@ namespace Semmle.Autobuild.Shared Script; var nugetRestore = GetNugetRestoreScript(); var msbuildRestoreCommand = new CommandBuilder(builder.Actions). - RunCommand(msBuild). + MsBuildCommand(builder). Argument("/t:restore"). QuoteArgument(projectOrSolution.FullPath); @@ -95,7 +113,7 @@ namespace Semmle.Autobuild.Shared command.RunCommand("set Platform=&& type NUL", quoteExe: false); } - command.RunCommand(msBuild); + command.MsBuildCommand(builder); command.QuoteArgument(projectOrSolution.FullPath); var target = builder.Options.MsBuildTarget ?? "rebuild"; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs index 7e4a3a95e39..15da81bf5e4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs @@ -65,6 +65,15 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.has_modifiers(target, Modifier.Create(cx, modifier)); } + private static void ExtractFieldModifiers(Context cx, TextWriter trapFile, IEntity key, IFieldSymbol symbol) + { + if (symbol.IsReadOnly) + HasModifier(cx, trapFile, key, Modifiers.Readonly); + + if (symbol.IsRequired) + HasModifier(cx, trapFile, key, Modifiers.Required); + } + private static void ExtractNamedTypeModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol) { if (symbol.Kind != SymbolKind.NamedType) @@ -106,8 +115,11 @@ namespace Semmle.Extraction.CSharp.Entities if (symbol.IsVirtual) HasModifier(cx, trapFile, key, Modifiers.Virtual); - if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly) - HasModifier(cx, trapFile, key, Modifiers.Readonly); + if (symbol is IFieldSymbol field) + ExtractFieldModifiers(cx, trapFile, key, field); + + if (symbol.Kind == SymbolKind.Property && ((IPropertySymbol)symbol).IsRequired) + HasModifier(cx, trapFile, key, Modifiers.Required); if (symbol.IsOverride) HasModifier(cx, trapFile, key, Modifiers.Override); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifiers.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifiers.cs index f535a9c3058..ef38646bc81 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifiers.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifiers.cs @@ -13,6 +13,7 @@ internal static class Modifiers public const string Public = "public"; public const string Readonly = "readonly"; public const string Record = "record"; + public const string Required = "required"; public const string Ref = "ref"; public const string Sealed = "sealed"; public const string Static = "static"; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 6018b9903c1..debb96ca3b6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -77,12 +77,8 @@ namespace Semmle.Extraction.CSharp /// /// Gets the source-level modifiers belonging to this symbol, if any. /// - public static IEnumerable GetSourceLevelModifiers(this ISymbol symbol) - { - var methodModifiers = symbol.GetModifiers(md => md.Modifiers); - var typeModifiers = symbol.GetModifiers(cd => cd.Modifiers); - return methodModifiers.Concat(typeModifiers).Select(m => m.Text); - } + public static IEnumerable GetSourceLevelModifiers(this ISymbol symbol) => + symbol.GetModifiers(md => md.Modifiers).Select(m => m.Text); /// /// Holds if the ID generated for `dependant` will contain a reference to diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 3137a84a435..3d63162ca4d 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.3 + +No user-facing changes. + ## 1.4.2 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.3.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.3.md new file mode 100644 index 00000000000..abf2a0d4dcc --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.3.md @@ -0,0 +1,3 @@ +## 1.4.3 + +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 a76cacdf799..08f88b689fb 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.2 +lastReleaseVersion: 1.4.3 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 4655f3d5939..7aa032fa92d 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.3-dev +version: 1.4.4-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 3137a84a435..3d63162ca4d 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.3 + +No user-facing changes. + ## 1.4.2 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.3.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.3.md new file mode 100644 index 00000000000..abf2a0d4dcc --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.3.md @@ -0,0 +1,3 @@ +## 1.4.3 + +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 a76cacdf799..08f88b689fb 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.2 +lastReleaseVersion: 1.4.3 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 813cb0d50ce..72f0256ef39 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.3-dev +version: 1.4.4-dev groups: - csharp - solorigate diff --git a/csharp/ql/integration-tests/all-platforms/msbuild/Program.cs b/csharp/ql/integration-tests/all-platforms/msbuild/Program.cs new file mode 100644 index 00000000000..66b32336aa3 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/msbuild/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace Test +{ + public class Program + { + public static int Main(string[] args) + { + Console.WriteLine("Hello world!"); + return 0; + } + } +} diff --git a/csharp/ql/integration-tests/all-platforms/msbuild/test.csproj b/csharp/ql/integration-tests/all-platforms/msbuild/test.csproj new file mode 100644 index 00000000000..88ed91975ce --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/msbuild/test.csproj @@ -0,0 +1,7 @@ + + + + Exe + net4.0 + + diff --git a/csharp/ql/integration-tests/all-platforms/msbuild/test.py b/csharp/ql/integration-tests/all-platforms/msbuild/test.py new file mode 100644 index 00000000000..97682d28205 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/msbuild/test.py @@ -0,0 +1,4 @@ +from create_database_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' }) diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index d31bad9b040..7d14d20ddbc 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.5.3 + +### Minor Analysis Improvements + +* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables. + ## 0.5.2 ### Major Analysis Improvements diff --git a/csharp/ql/lib/change-notes/2023-02-07-scoped-modifier.md b/csharp/ql/lib/change-notes/2023-02-07-scoped-modifier.md deleted file mode 100644 index 93460b64184..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-07-scoped-modifier.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables. \ No newline at end of file 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 new file mode 100644 index 00000000000..19d4a7f3f66 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-02-14-checked-operators.md @@ -0,0 +1,4 @@ +--- +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 new file mode 100644 index 00000000000..8a318ca52ec --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md @@ -0,0 +1,4 @@ +--- +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-22-modifierextraction.md b/csharp/ql/lib/change-notes/2023-02-22-modifierextraction.md new file mode 100644 index 00000000000..2078c2a9f1e --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-02-22-modifierextraction.md @@ -0,0 +1,4 @@ +--- +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/released/0.5.3.md b/csharp/ql/lib/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..a4f605335ac --- /dev/null +++ b/csharp/ql/lib/change-notes/released/0.5.3.md @@ -0,0 +1,5 @@ +## 0.5.3 + +### Minor Analysis Improvements + +* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 106d566fefe..3f118d8115f 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.5.3-dev +version: 0.5.4-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp @@ -8,6 +8,7 @@ upgrades: upgrades dependencies: codeql/ssa: ${workspace} codeql/tutorial: ${workspace} + codeql/util: ${workspace} dataExtensions: - ext/*.model.yml - ext/generated/*.model.yml diff --git a/csharp/ql/lib/semmle/code/csharp/Callable.qll b/csharp/ql/lib/semmle/code/csharp/Callable.qll index ea88f814bce..82ffbfa6a06 100644 --- a/csharp/ql/lib/semmle/code/csharp/Callable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Callable.qll @@ -435,8 +435,12 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de * (`BinaryOperator`), or a conversion operator (`ConversionOperator`). */ class Operator extends Callable, Member, Attributable, @operator { - /** Gets the assembly name of this operator. */ - string getAssemblyName() { operators(this, result, _, _, _, _) } + /** + * DEPRECATED: use `getFunctionName()` instead. + * + * Gets the assembly name of this operator. + */ + deprecated string getAssemblyName() { result = this.getFunctionName() } override string getName() { operators(this, _, result, _, _, _) } @@ -445,7 +449,7 @@ class Operator extends Callable, Member, Attributable, @operator { /** * Gets the metadata name of the operator, such as `op_implicit` or `op_RightShift`. */ - string getFunctionName() { none() } + string getFunctionName() { operators(this, result, _, _, _, _) } override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) } @@ -481,10 +485,11 @@ class RecordCloneMethod extends Method, DotNet::RecordCloneCallable { * A user-defined unary operator - an operator taking one operand. * * Either a plus operator (`PlusOperator`), minus operator (`MinusOperator`), - * not operator (`NotOperator`), complement operator (`ComplementOperator`), - * true operator (`TrueOperator`), false operator (`FalseOperator`), - * increment operator (`IncrementOperator`), or decrement operator - * (`DecrementOperator`). + * checked minus operator (`CheckedMinusOperator`), not operator (`NotOperator`), + * complement operator (`ComplementOperator`), true operator (`TrueOperator`), + * false operator (`FalseOperator`), increment operator (`IncrementOperator`), + * checked increment operator (`CheckedIncrementOperator`), decrement operator + * (`DecrementOperator`) or checked decrement operator (`CheckedDecrementOperator`). */ class UnaryOperator extends Operator { UnaryOperator() { @@ -505,8 +510,6 @@ class UnaryOperator extends Operator { class PlusOperator extends UnaryOperator { PlusOperator() { this.getName() = "+" } - override string getFunctionName() { result = "op_UnaryPlus" } - override string getAPrimaryQlClass() { result = "PlusOperator" } } @@ -522,11 +525,24 @@ class PlusOperator extends UnaryOperator { class MinusOperator extends UnaryOperator { MinusOperator() { this.getName() = "-" } - override string getFunctionName() { result = "op_UnaryNegation" } - override string getAPrimaryQlClass() { result = "MinusOperator" } } +/** + * A user-defined checked minus operator (`-`), for example + * + * ```csharp + * public static Widget operator checked -(Widget w) { + * ... + * } + * ``` + */ +class CheckedMinusOperator extends UnaryOperator { + CheckedMinusOperator() { this.getName() = "checked -" } + + override string getAPrimaryQlClass() { result = "CheckedMinusOperator" } +} + /** * A user-defined not operator (`!`), for example * @@ -539,8 +555,6 @@ class MinusOperator extends UnaryOperator { class NotOperator extends UnaryOperator { NotOperator() { this.getName() = "!" } - override string getFunctionName() { result = "op_LogicalNot" } - override string getAPrimaryQlClass() { result = "NotOperator" } } @@ -556,8 +570,6 @@ class NotOperator extends UnaryOperator { class ComplementOperator extends UnaryOperator { ComplementOperator() { this.getName() = "~" } - override string getFunctionName() { result = "op_OnesComplement" } - override string getAPrimaryQlClass() { result = "ComplementOperator" } } @@ -573,11 +585,24 @@ class ComplementOperator extends UnaryOperator { class IncrementOperator extends UnaryOperator { IncrementOperator() { this.getName() = "++" } - override string getFunctionName() { result = "op_Increment" } - override string getAPrimaryQlClass() { result = "IncrementOperator" } } +/** + * A user-defined checked increment operator (`++`), for example + * + * ```csharp + * public static Widget operator checked ++(Widget w) { + * ... + * } + * ``` + */ +class CheckedIncrementOperator extends UnaryOperator { + CheckedIncrementOperator() { this.getName() = "checked ++" } + + override string getAPrimaryQlClass() { result = "CheckedIncrementOperator" } +} + /** * A user-defined decrement operator (`--`), for example * @@ -590,11 +615,24 @@ class IncrementOperator extends UnaryOperator { class DecrementOperator extends UnaryOperator { DecrementOperator() { this.getName() = "--" } - override string getFunctionName() { result = "op_Decrement" } - override string getAPrimaryQlClass() { result = "DecrementOperator" } } +/** + * A user-defined checked decrement operator (`--`), for example + * + * ```csharp + * public static Widget operator checked --(Widget w) { + * ... + * } + * ``` + */ +class CheckedDecrementOperator extends UnaryOperator { + CheckedDecrementOperator() { this.getName() = "checked --" } + + override string getAPrimaryQlClass() { result = "CheckedDecrementOperator" } +} + /** * A user-defined false operator (`false`), for example * @@ -607,8 +645,6 @@ class DecrementOperator extends UnaryOperator { class FalseOperator extends UnaryOperator { FalseOperator() { this.getName() = "false" } - override string getFunctionName() { result = "op_False" } - override string getAPrimaryQlClass() { result = "FalseOperator" } } @@ -624,17 +660,18 @@ class FalseOperator extends UnaryOperator { class TrueOperator extends UnaryOperator { TrueOperator() { this.getName() = "true" } - override string getFunctionName() { result = "op_True" } - override string getAPrimaryQlClass() { result = "TrueOperator" } } /** * A user-defined binary operator. * - * Either an addition operator (`AddOperator`), a subtraction operator - * (`SubOperator`), a multiplication operator (`MulOperator`), a division - * operator (`DivOperator`), a remainder operator (`RemOperator`), an and + * Either an addition operator (`AddOperator`), a checked addition operator + * (`CheckedAddOperator`) a subtraction operator (`SubOperator`), a checked + * substraction operator (`CheckedSubOperator`), a multiplication operator + * (`MulOperator`), a checked multiplication operator (`CheckedMulOperator`), + * a division operator (`DivOperator`), a checked division operator + * (`CheckedDivOperator`), a remainder operator (`RemOperator`), an and * operator (`AndOperator`), an or operator (`OrOperator`), an xor * operator (`XorOperator`), a left shift operator (`LeftShiftOperator`), * a right shift operator (`RightShiftOperator`), an unsigned right shift @@ -659,11 +696,24 @@ class BinaryOperator extends Operator { class AddOperator extends BinaryOperator { AddOperator() { this.getName() = "+" } - override string getFunctionName() { result = "op_Addition" } - override string getAPrimaryQlClass() { result = "AddOperator" } } +/** + * A user-defined checked addition operator (`+`), for example + * + * ```csharp + * public static Widget operator checked +(Widget lhs, Widget rhs) { + * ... + * } + * ``` + */ +class CheckedAddOperator extends BinaryOperator { + CheckedAddOperator() { this.getName() = "checked +" } + + override string getAPrimaryQlClass() { result = "CheckedAddOperator" } +} + /** * A user-defined subtraction operator (`-`), for example * @@ -676,11 +726,24 @@ class AddOperator extends BinaryOperator { class SubOperator extends BinaryOperator { SubOperator() { this.getName() = "-" } - override string getFunctionName() { result = "op_Subtraction" } - override string getAPrimaryQlClass() { result = "SubOperator" } } +/** + * A user-defined checked subtraction operator (`-`), for example + * + * ```csharp + * public static Widget operator checked -(Widget lhs, Widget rhs) { + * ... + * } + * ``` + */ +class CheckedSubOperator extends BinaryOperator { + CheckedSubOperator() { this.getName() = "checked -" } + + override string getAPrimaryQlClass() { result = "CheckedSubOperator" } +} + /** * A user-defined multiplication operator (`*`), for example * @@ -693,11 +756,24 @@ class SubOperator extends BinaryOperator { class MulOperator extends BinaryOperator { MulOperator() { this.getName() = "*" } - override string getFunctionName() { result = "op_Multiply" } - override string getAPrimaryQlClass() { result = "MulOperator" } } +/** + * A user-defined checked multiplication operator (`*`), for example + * + * ```csharp + * public static Widget operator checked *(Widget lhs, Widget rhs) { + * ... + * } + * ``` + */ +class CheckedMulOperator extends BinaryOperator { + CheckedMulOperator() { this.getName() = "checked *" } + + override string getAPrimaryQlClass() { result = "CheckedMulOperator" } +} + /** * A user-defined division operator (`/`), for example * @@ -710,11 +786,24 @@ class MulOperator extends BinaryOperator { class DivOperator extends BinaryOperator { DivOperator() { this.getName() = "/" } - override string getFunctionName() { result = "op_Division" } - override string getAPrimaryQlClass() { result = "DivOperator" } } +/** + * A user-defined checked division operator (`/`), for example + * + * ```csharp + * public static Widget operator checked /(Widget lhs, Widget rhs) { + * ... + * } + * ``` + */ +class CheckedDivOperator extends BinaryOperator { + CheckedDivOperator() { this.getName() = "checked /" } + + override string getAPrimaryQlClass() { result = "CheckedDivOperator" } +} + /** * A user-defined remainder operator (`%`), for example * @@ -727,8 +816,6 @@ class DivOperator extends BinaryOperator { class RemOperator extends BinaryOperator { RemOperator() { this.getName() = "%" } - override string getFunctionName() { result = "op_Modulus" } - override string getAPrimaryQlClass() { result = "RemOperator" } } @@ -744,8 +831,6 @@ class RemOperator extends BinaryOperator { class AndOperator extends BinaryOperator { AndOperator() { this.getName() = "&" } - override string getFunctionName() { result = "op_BitwiseAnd" } - override string getAPrimaryQlClass() { result = "AndOperator" } } @@ -761,8 +846,6 @@ class AndOperator extends BinaryOperator { class OrOperator extends BinaryOperator { OrOperator() { this.getName() = "|" } - override string getFunctionName() { result = "op_BitwiseOr" } - override string getAPrimaryQlClass() { result = "OrOperator" } } @@ -778,8 +861,6 @@ class OrOperator extends BinaryOperator { class XorOperator extends BinaryOperator { XorOperator() { this.getName() = "^" } - override string getFunctionName() { result = "op_ExclusiveOr" } - override string getAPrimaryQlClass() { result = "XorOperator" } } @@ -795,8 +876,6 @@ class XorOperator extends BinaryOperator { class LeftShiftOperator extends BinaryOperator { LeftShiftOperator() { this.getName() = "<<" } - override string getFunctionName() { result = "op_LeftShift" } - override string getAPrimaryQlClass() { result = "LeftShiftOperator" } } @@ -815,8 +894,6 @@ deprecated class LShiftOperator = LeftShiftOperator; class RightShiftOperator extends BinaryOperator { RightShiftOperator() { this.getName() = ">>" } - override string getFunctionName() { result = "op_RightShift" } - override string getAPrimaryQlClass() { result = "RightShiftOperator" } } @@ -835,8 +912,6 @@ deprecated class RShiftOperator = RightShiftOperator; class UnsignedRightShiftOperator extends BinaryOperator { UnsignedRightShiftOperator() { this.getName() = ">>>" } - override string getFunctionName() { result = "op_UnsignedRightShift" } - override string getAPrimaryQlClass() { result = "UnsignedRightShiftOperator" } } @@ -852,8 +927,6 @@ class UnsignedRightShiftOperator extends BinaryOperator { class EQOperator extends BinaryOperator { EQOperator() { this.getName() = "==" } - override string getFunctionName() { result = "op_Equality" } - override string getAPrimaryQlClass() { result = "EQOperator" } } @@ -869,8 +942,6 @@ class EQOperator extends BinaryOperator { class NEOperator extends BinaryOperator { NEOperator() { this.getName() = "!=" } - override string getFunctionName() { result = "op_Inequality" } - override string getAPrimaryQlClass() { result = "NEOperator" } } @@ -886,8 +957,6 @@ class NEOperator extends BinaryOperator { class LTOperator extends BinaryOperator { LTOperator() { this.getName() = "<" } - override string getFunctionName() { result = "op_LessThan" } - override string getAPrimaryQlClass() { result = "LTOperator" } } @@ -903,8 +972,6 @@ class LTOperator extends BinaryOperator { class GTOperator extends BinaryOperator { GTOperator() { this.getName() = ">" } - override string getFunctionName() { result = "op_GreaterThan" } - override string getAPrimaryQlClass() { result = "GTOperator" } } @@ -920,8 +987,6 @@ class GTOperator extends BinaryOperator { class LEOperator extends BinaryOperator { LEOperator() { this.getName() = "<=" } - override string getFunctionName() { result = "op_LessThanOrEqual" } - override string getAPrimaryQlClass() { result = "LEOperator" } } @@ -937,8 +1002,6 @@ class LEOperator extends BinaryOperator { class GEOperator extends BinaryOperator { GEOperator() { this.getName() = ">=" } - override string getFunctionName() { result = "op_GreaterThanOrEqual" } - override string getAPrimaryQlClass() { result = "GEOperator" } } @@ -954,7 +1017,8 @@ class GEOperator extends BinaryOperator { class ConversionOperator extends Operator { ConversionOperator() { this.getName() = "implicit conversion" or - this.getName() = "explicit conversion" + this.getName() = "explicit conversion" or + this.getName() = "checked explicit conversion" } /** Gets the source type of the conversion. */ @@ -976,8 +1040,6 @@ class ConversionOperator extends Operator { class ImplicitConversionOperator extends ConversionOperator { ImplicitConversionOperator() { this.getName() = "implicit conversion" } - override string getFunctionName() { result = "op_Implicit" } - override string getAPrimaryQlClass() { result = "ImplicitConversionOperator" } } @@ -993,11 +1055,24 @@ class ImplicitConversionOperator extends ConversionOperator { class ExplicitConversionOperator extends ConversionOperator { ExplicitConversionOperator() { this.getName() = "explicit conversion" } - override string getFunctionName() { result = "op_Explicit" } - override string getAPrimaryQlClass() { result = "ExplicitConversionOperator" } } +/** + * A user-defined checked explicit conversion operator, for example + * + * ```csharp + * public static explicit operator checked int(BigInteger i) { + * ... + * } + * ``` + */ +class CheckedExplicitConversionOperator extends ConversionOperator { + CheckedExplicitConversionOperator() { this.getName() = "checked explicit conversion" } + + override string getAPrimaryQlClass() { result = "CheckedExplicitConversionOperator" } +} + /** * A local function, defined within the scope of another callable. * For example, `Fac` on lines 2--4 in diff --git a/csharp/ql/lib/semmle/code/csharp/File.qll b/csharp/ql/lib/semmle/code/csharp/File.qll index e4e0d3c6c26..79406aec2f6 100644 --- a/csharp/ql/lib/semmle/code/csharp/File.qll +++ b/csharp/ql/lib/semmle/code/csharp/File.qll @@ -3,184 +3,34 @@ */ private import Comments +private import codeql.util.FileSystem -/** A file or folder. */ -class Container extends @container { - /** - * Gets the absolute, canonical path of this container, using forward slashes - * as path separator. - * - * The path starts with a _root prefix_ followed by zero or more _path - * segments_ separated by forward slashes. - * - * The root prefix is of one of the following forms: - * - * 1. A single forward slash `/` (Unix-style) - * 2. An upper-case drive letter followed by a colon and a forward slash, - * such as `C:/` (Windows-style) - * 3. Two forward slashes, a computer name, and then another forward slash, - * such as `//FileServer/` (UNC-style) - * - * Path segments are never empty (that is, absolute paths never contain two - * contiguous slashes, except as part of a UNC-style root prefix). Also, path - * segments never contain forward slashes, and no path segment is of the - * form `.` (one dot) or `..` (two dots). - * - * Note that an absolute path never ends with a forward slash, except if it is - * a bare root prefix, that is, the path has no path segments. A container - * whose absolute path has no segments is always a `Folder`, not a `File`. - */ - string getAbsolutePath() { none() } +private module Input implements InputSig { + abstract class ContainerBase extends @container { + abstract string getAbsolutePath(); - /** - * Gets a URL representing the location of this container. - * - * For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls). - */ - string getURL() { none() } + ContainerBase getParentContainer() { containerparent(result, this) } - /** - * Gets the relative path of this file or folder from the root folder of the - * analyzed source location. The relative path of the root folder itself is - * the empty string. - * - * This has no result if the container is outside the source root, that is, - * if the root folder is not a reflexive, transitive parent of this container. - */ - string getRelativePath() { - exists(string absPath, string pref | - absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) - | - absPath = pref and result = "" - or - absPath = pref.regexpReplaceAll("/$", "") + "/" + result and - not result.matches("/%") - ) + string toString() { result = this.getAbsolutePath() } } - /** - * Gets the base name of this container including extension, that is, the last - * segment of its absolute path, or the empty string if it has no segments. - * - * Here are some examples of absolute paths and the corresponding base names - * (surrounded with quotes to avoid ambiguity): - * - * - * - * - * - * - * - * - * - *
Absolute pathBase name
"/tmp/tst.cs""tst.cs"
"C:/Program Files (x86)""Program Files (x86)"
"/"""
"C:/"""
"D:/"""
"//FileServer/"""
- */ - string getBaseName() { - result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + class FolderBase extends ContainerBase, @folder { + override string getAbsolutePath() { folders(this, result) } } - /** - * Gets the extension of this container, that is, the suffix of its base name - * after the last dot character, if any. - * - * In particular, - * - * - if the name does not include a dot, there is no extension, so this - * predicate has no result; - * - if the name ends in a dot, the extension is the empty string; - * - if the name contains multiple dots, the extension follows the last dot. - * - * Here are some examples of absolute paths and the corresponding extensions - * (surrounded with quotes to avoid ambiguity): - * - * - * - * - * - * - * - * - *
Absolute pathExtension
"/tmp/tst.cs""cs"
"/tmp/.classpath""classpath"
"/bin/bash"not defined
"/tmp/tst2."""
"/tmp/x.tar.gz""gz"
- */ - string getExtension() { - result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + class FileBase extends ContainerBase, @file { + override string getAbsolutePath() { files(this, result) } } - /** - * Gets the stem of this container, that is, the prefix of its base name up to - * (but not including) the last dot character if there is one, or the entire - * base name if there is not. - * - * Here are some examples of absolute paths and the corresponding stems - * (surrounded with quotes to avoid ambiguity): - * - * - * - * - * - * - * - * - *
Absolute pathStem
"/tmp/tst.cs""tst"
"/tmp/.classpath"""
"/bin/bash""bash"
"/tmp/tst2.""tst2"
"/tmp/x.tar.gz""x.tar"
- */ - string getStem() { - result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } - - /** Gets the parent container of this file or folder, if any. */ - Container getParentContainer() { containerparent(result, this) } - - /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { this = result.getParentContainer() } - - /** Gets a file in this container. */ - File getAFile() { result = this.getAChildContainer() } - - /** Gets the file in this container that has the given `baseName`, if any. */ - File getFile(string baseName) { - result = this.getAFile() and - result.getBaseName() = baseName - } - - /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = this.getAChildContainer() } - - /** Gets the sub-folder in this container that has the given `baseName`, if any. */ - Folder getFolder(string baseName) { - result = this.getAFolder() and - result.getBaseName() = baseName - } - - /** Gets the file or sub-folder in this container that has the given `name`, if any. */ - Container getChildContainer(string name) { - result = this.getAChildContainer() and - result.getBaseName() = name - } - - /** Gets the file in this container that has the given `stem` and `extension`, if any. */ - File getFile(string stem, string extension) { - result = this.getAChildContainer() and - result.getStem() = stem and - result.getExtension() = extension - } - - /** Gets a sub-folder contained in this container. */ - Folder getASubFolder() { result = this.getAChildContainer() } - - /** - * Gets a textual representation of the path of this container. - * - * This is the absolute path of the container. - */ - string toString() { result = this.getAbsolutePath() } + predicate hasSourceLocationPrefix = sourceLocationPrefix/1; } +private module Impl = Make; + +class Container = Impl::Container; + /** A folder. */ -class Folder extends Container, @folder { - override string getAbsolutePath() { folders(this, result) } - - override string getURL() { result = "folder://" + this.getAbsolutePath() } -} +class Folder extends Container, Impl::Folder { } bindingset[flag] private predicate fileHasExtractionFlag(File f, int flag) { @@ -191,9 +41,7 @@ private predicate fileHasExtractionFlag(File f, int flag) { } /** A file. */ -class File extends Container, @file { - override string getAbsolutePath() { files(this, result) } - +class File extends Container, Impl::File { /** Gets the number of lines in this file. */ int getNumberOfLines() { numlines(this, result, _, _) } diff --git a/csharp/ql/lib/semmle/code/csharp/Member.qll b/csharp/ql/lib/semmle/code/csharp/Member.qll index 85225ac44cf..0ce8dc44e3c 100644 --- a/csharp/ql/lib/semmle/code/csharp/Member.qll +++ b/csharp/ql/lib/semmle/code/csharp/Member.qll @@ -90,6 +90,9 @@ class Modifiable extends Declaration, @modifiable { /** Holds if this declaration is `const`. */ predicate isConst() { this.hasModifier("const") } + /** Holds if this declaration has the modifier `required`. */ + predicate isRequired() { this.hasModifier("required") } + /** Holds if this declaration is `unsafe`. */ predicate isUnsafe() { this.hasModifier("unsafe") or @@ -178,6 +181,8 @@ class Member extends DotNet::Member, Modifiable, @member { override predicate isAbstract() { Modifiable.super.isAbstract() } override predicate isStatic() { Modifiable.super.isStatic() } + + override predicate isRequired() { Modifiable.super.isRequired() } } private class TOverridable = @virtualizable or @callable_accessor; diff --git a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll index fea5a1aaeca..8e45a06eaca 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll @@ -80,6 +80,9 @@ class Member extends Declaration, @dotnet_member { /** Holds if this member is `static`. */ predicate isStatic() { none() } + /** Holds if this member is declared `required`. */ + predicate isRequired() { none() } + /** * Holds if this member has name `name` and is defined in type `type` * with namespace `namespace`. diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index c9bdcf20c42..15b14e1e20d 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +No user-facing changes. + ## 0.5.2 No user-facing changes. diff --git a/csharp/ql/src/Telemetry/ExternalApi.qll b/csharp/ql/src/Telemetry/ExternalApi.qll index 94168e6d3fe..9358e9ce8e4 100644 --- a/csharp/ql/src/Telemetry/ExternalApi.qll +++ b/csharp/ql/src/Telemetry/ExternalApi.qll @@ -8,6 +8,7 @@ private import semmle.code.csharp.dataflow.FlowSummary private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon private import semmle.code.csharp.dataflow.internal.DataFlowPrivate private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch +private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate private import semmle.code.csharp.security.dataflow.flowsources.Remote @@ -104,8 +105,17 @@ class ExternalApi extends DotNet::Callable { pragma[nomagic] predicate isSink() { sinkNode(this.getAnInput(), _) } - /** Holds if this API is supported by existing CodeQL libraries, that is, it is either a recognized source or sink or has a flow summary. */ - predicate isSupported() { this.hasSummary() or this.isSource() or this.isSink() } + /** Holds if this API is a known neutral. */ + pragma[nomagic] + predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable } + + /** + * Holds if this API is supported by existing CodeQL libraries, that is, it is either a + * recognized source, sink or neutral or it has a flow summary. + */ + predicate isSupported() { + this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral() + } } /** diff --git a/csharp/ql/src/Telemetry/SupportedExternalApis.ql b/csharp/ql/src/Telemetry/SupportedExternalApis.ql index 7611a367b0a..6d6270fde4e 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalApis.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalApis.ql @@ -8,13 +8,9 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch -private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import ExternalApi -private predicate relevant(ExternalApi api) { - api.isSupported() or - api instanceof FlowSummaryImpl::Public::NeutralCallable -} +private predicate relevant(ExternalApi api) { api.isSupported() } from string info, int usages where Results::restrict(info, usages) diff --git a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql index ee22c960043..99b8eaf74d9 100644 --- a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -7,14 +7,9 @@ */ private import csharp -private import semmle.code.csharp.dispatch.Dispatch -private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import ExternalApi -private predicate relevant(ExternalApi api) { - not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NeutralCallable -} +private predicate relevant(ExternalApi api) { not api.isSupported() } from string info, int usages where Results::restrict(info, usages) diff --git a/csharp/ql/src/change-notes/released/0.5.3.md b/csharp/ql/src/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..e97503053f0 --- /dev/null +++ b/csharp/ql/src/change-notes/released/0.5.3.md @@ -0,0 +1,3 @@ +## 0.5.3 + +No user-facing changes. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql b/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql index ddfaac675f5..56299f82d9c 100644 --- a/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql @@ -9,13 +9,10 @@ */ private import csharp -private import semmle.code.csharp.dispatch.Dispatch -private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import Telemetry.ExternalApi from Call c, ExternalApi api where c.getTarget().getUnboundDeclaration() = api and - not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NeutralCallable + not api.isSupported() select c, "Call to unsupported external API $@.", api, api.toString() diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index b3c48bf29fe..54179503685 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.5.3-dev +version: 0.5.4-dev groups: - csharp - queries diff --git a/csharp/ql/test/library-tests/csharp11/CheckedOperators.cs b/csharp/ql/test/library-tests/csharp11/CheckedOperators.cs new file mode 100644 index 00000000000..a61be485b15 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/CheckedOperators.cs @@ -0,0 +1,56 @@ +namespace CheckedOperators; + +public class Number +{ + public int Value { get; } + + public Number(int n) => this.Value = n; + + public static Number operator checked +(Number n1, Number n2) => + new Number(checked(n1.Value + n2.Value)); + + public static Number operator +(Number n1, Number n2) => + new Number(n1.Value + n2.Value); + + public static Number operator checked -(Number n1, Number n2) => + new Number(checked(n1.Value - n2.Value)); + + public static Number operator -(Number n1, Number n2) => + new Number(n1.Value - n2.Value); + + public static Number operator checked *(Number n1, Number n2) => + new Number(checked(n1.Value * n2.Value)); + + public static Number operator *(Number n1, Number n2) => + new Number(n1.Value * n2.Value); + + public static Number operator checked /(Number n1, Number n2) => + new Number(checked(n1.Value / n2.Value)); + + public static Number operator /(Number n1, Number n2) => + new Number(n1.Value / n2.Value); + + public static Number operator checked -(Number n) => + new Number(checked(-n.Value)); + + public static Number operator -(Number n) => + new Number(-n.Value); + + public static Number operator checked ++(Number n) => + new Number(checked(n.Value + 1)); + + public static Number operator ++(Number n) => + new Number(n.Value + 1); + + public static Number operator checked --(Number n) => + new Number(checked(n.Value - 1)); + + public static Number operator --(Number n) => + new Number(n.Value - 1); + + public static explicit operator short(Number n) => + (short)n.Value; + + public static explicit operator checked short(Number n) => + checked((short)n.Value); +} diff --git a/csharp/ql/test/library-tests/csharp11/PrintAst.expected b/csharp/ql/test/library-tests/csharp11/PrintAst.expected index b03c5b6a9e3..3ef77ba3864 100644 --- a/csharp/ql/test/library-tests/csharp11/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp11/PrintAst.expected @@ -1,3 +1,221 @@ +CheckedOperators.cs: +# 1| [NamespaceDeclaration] namespace ... { ... } +# 3| 1: [Class] Number +# 5| 4: [Property] Value +# 5| -1: [TypeMention] int +# 5| 3: [Getter] get_Value +# 7| 5: [InstanceConstructor] Number +#-----| 2: (Parameters) +# 7| 0: [Parameter] n +# 7| -1: [TypeMention] int +# 7| 4: [AssignExpr] ... = ... +# 7| 0: [PropertyCall] access to property Value +# 7| -1: [ThisAccess] this access +# 7| 1: [ParameterAccess] access to parameter n +# 9| 6: [CheckedAddOperator] checked + +# 9| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 9| 0: [Parameter] n1 +# 9| -1: [TypeMention] Number +# 9| 1: [Parameter] n2 +# 9| -1: [TypeMention] Number +# 10| 4: [ObjectCreation] object creation of type Number +# 10| -1: [TypeMention] Number +# 10| 0: [CheckedExpr] checked (...) +# 10| 0: [AddExpr] ... + ... +# 10| 0: [PropertyCall] access to property Value +# 10| -1: [ParameterAccess] access to parameter n1 +# 10| 1: [PropertyCall] access to property Value +# 10| -1: [ParameterAccess] access to parameter n2 +# 12| 7: [AddOperator] + +# 12| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 12| 0: [Parameter] n1 +# 12| -1: [TypeMention] Number +# 12| 1: [Parameter] n2 +# 12| -1: [TypeMention] Number +# 13| 4: [ObjectCreation] object creation of type Number +# 13| -1: [TypeMention] Number +# 13| 0: [AddExpr] ... + ... +# 13| 0: [PropertyCall] access to property Value +# 13| -1: [ParameterAccess] access to parameter n1 +# 13| 1: [PropertyCall] access to property Value +# 13| -1: [ParameterAccess] access to parameter n2 +# 15| 8: [CheckedSubOperator] checked - +# 15| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 15| 0: [Parameter] n1 +# 15| -1: [TypeMention] Number +# 15| 1: [Parameter] n2 +# 15| -1: [TypeMention] Number +# 16| 4: [ObjectCreation] object creation of type Number +# 16| -1: [TypeMention] Number +# 16| 0: [CheckedExpr] checked (...) +# 16| 0: [SubExpr] ... - ... +# 16| 0: [PropertyCall] access to property Value +# 16| -1: [ParameterAccess] access to parameter n1 +# 16| 1: [PropertyCall] access to property Value +# 16| -1: [ParameterAccess] access to parameter n2 +# 18| 9: [SubOperator] - +# 18| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 18| 0: [Parameter] n1 +# 18| -1: [TypeMention] Number +# 18| 1: [Parameter] n2 +# 18| -1: [TypeMention] Number +# 19| 4: [ObjectCreation] object creation of type Number +# 19| -1: [TypeMention] Number +# 19| 0: [SubExpr] ... - ... +# 19| 0: [PropertyCall] access to property Value +# 19| -1: [ParameterAccess] access to parameter n1 +# 19| 1: [PropertyCall] access to property Value +# 19| -1: [ParameterAccess] access to parameter n2 +# 21| 10: [CheckedMulOperator] checked * +# 21| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 21| 0: [Parameter] n1 +# 21| -1: [TypeMention] Number +# 21| 1: [Parameter] n2 +# 21| -1: [TypeMention] Number +# 22| 4: [ObjectCreation] object creation of type Number +# 22| -1: [TypeMention] Number +# 22| 0: [CheckedExpr] checked (...) +# 22| 0: [MulExpr] ... * ... +# 22| 0: [PropertyCall] access to property Value +# 22| -1: [ParameterAccess] access to parameter n1 +# 22| 1: [PropertyCall] access to property Value +# 22| -1: [ParameterAccess] access to parameter n2 +# 24| 11: [MulOperator] * +# 24| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 24| 0: [Parameter] n1 +# 24| -1: [TypeMention] Number +# 24| 1: [Parameter] n2 +# 24| -1: [TypeMention] Number +# 25| 4: [ObjectCreation] object creation of type Number +# 25| -1: [TypeMention] Number +# 25| 0: [MulExpr] ... * ... +# 25| 0: [PropertyCall] access to property Value +# 25| -1: [ParameterAccess] access to parameter n1 +# 25| 1: [PropertyCall] access to property Value +# 25| -1: [ParameterAccess] access to parameter n2 +# 27| 12: [CheckedDivOperator] checked / +# 27| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 27| 0: [Parameter] n1 +# 27| -1: [TypeMention] Number +# 27| 1: [Parameter] n2 +# 27| -1: [TypeMention] Number +# 28| 4: [ObjectCreation] object creation of type Number +# 28| -1: [TypeMention] Number +# 28| 0: [CheckedExpr] checked (...) +# 28| 0: [DivExpr] ... / ... +# 28| 0: [PropertyCall] access to property Value +# 28| -1: [ParameterAccess] access to parameter n1 +# 28| 1: [PropertyCall] access to property Value +# 28| -1: [ParameterAccess] access to parameter n2 +# 30| 13: [DivOperator] / +# 30| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 30| 0: [Parameter] n1 +# 30| -1: [TypeMention] Number +# 30| 1: [Parameter] n2 +# 30| -1: [TypeMention] Number +# 31| 4: [ObjectCreation] object creation of type Number +# 31| -1: [TypeMention] Number +# 31| 0: [DivExpr] ... / ... +# 31| 0: [PropertyCall] access to property Value +# 31| -1: [ParameterAccess] access to parameter n1 +# 31| 1: [PropertyCall] access to property Value +# 31| -1: [ParameterAccess] access to parameter n2 +# 33| 14: [CheckedMinusOperator] checked - +# 33| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 33| 0: [Parameter] n +# 33| -1: [TypeMention] Number +# 34| 4: [ObjectCreation] object creation of type Number +# 34| -1: [TypeMention] Number +# 34| 0: [CheckedExpr] checked (...) +# 34| 0: [UnaryMinusExpr] -... +# 34| 0: [PropertyCall] access to property Value +# 34| -1: [ParameterAccess] access to parameter n +# 36| 15: [MinusOperator] - +# 36| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 36| 0: [Parameter] n +# 36| -1: [TypeMention] Number +# 37| 4: [ObjectCreation] object creation of type Number +# 37| -1: [TypeMention] Number +# 37| 0: [UnaryMinusExpr] -... +# 37| 0: [PropertyCall] access to property Value +# 37| -1: [ParameterAccess] access to parameter n +# 39| 16: [CheckedIncrementOperator] checked ++ +# 39| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 39| 0: [Parameter] n +# 39| -1: [TypeMention] Number +# 40| 4: [ObjectCreation] object creation of type Number +# 40| -1: [TypeMention] Number +# 40| 0: [CheckedExpr] checked (...) +# 40| 0: [AddExpr] ... + ... +# 40| 0: [PropertyCall] access to property Value +# 40| -1: [ParameterAccess] access to parameter n +# 40| 1: [IntLiteral] 1 +# 42| 17: [IncrementOperator] ++ +# 42| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 42| 0: [Parameter] n +# 42| -1: [TypeMention] Number +# 43| 4: [ObjectCreation] object creation of type Number +# 43| -1: [TypeMention] Number +# 43| 0: [AddExpr] ... + ... +# 43| 0: [PropertyCall] access to property Value +# 43| -1: [ParameterAccess] access to parameter n +# 43| 1: [IntLiteral] 1 +# 45| 18: [CheckedDecrementOperator] checked -- +# 45| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 45| 0: [Parameter] n +# 45| -1: [TypeMention] Number +# 46| 4: [ObjectCreation] object creation of type Number +# 46| -1: [TypeMention] Number +# 46| 0: [CheckedExpr] checked (...) +# 46| 0: [SubExpr] ... - ... +# 46| 0: [PropertyCall] access to property Value +# 46| -1: [ParameterAccess] access to parameter n +# 46| 1: [IntLiteral] 1 +# 48| 19: [DecrementOperator] -- +# 48| -1: [TypeMention] Number +#-----| 2: (Parameters) +# 48| 0: [Parameter] n +# 48| -1: [TypeMention] Number +# 49| 4: [ObjectCreation] object creation of type Number +# 49| -1: [TypeMention] Number +# 49| 0: [SubExpr] ... - ... +# 49| 0: [PropertyCall] access to property Value +# 49| -1: [ParameterAccess] access to parameter n +# 49| 1: [IntLiteral] 1 +# 51| 20: [ExplicitConversionOperator] explicit conversion +# 51| -1: [TypeMention] short +#-----| 2: (Parameters) +# 51| 0: [Parameter] n +# 51| -1: [TypeMention] Number +# 52| 4: [CastExpr] (...) ... +# 52| 0: [TypeAccess] access to type Int16 +# 52| 0: [TypeMention] short +# 52| 1: [PropertyCall] access to property Value +# 52| -1: [ParameterAccess] access to parameter n +# 54| 21: [CheckedExplicitConversionOperator] checked explicit conversion +# 54| -1: [TypeMention] short +#-----| 2: (Parameters) +# 54| 0: [Parameter] n +# 54| -1: [TypeMention] Number +# 55| 4: [CheckedExpr] checked (...) +# 55| 0: [CastExpr] (...) ... +# 55| 0: [TypeAccess] access to type Int16 +# 55| 0: [TypeMention] short +# 55| 1: [PropertyCall] access to property Value +# 55| -1: [ParameterAccess] access to parameter n GenericAttribute.cs: # 3| [GenericAssemblyAttribute] [assembly: MyGeneric(...)] # 3| 0: [TypeMention] MyGenericAttribute @@ -439,6 +657,97 @@ RelaxedShift.cs: # 30| 1: [OperatorCall] call to operator >>> # 30| 0: [LocalVariableAccess] access to local variable n31 # 30| 1: [StringLiteralUtf16] "3" +RequiredMembers.cs: +# 4| [Class] ClassRequiredMembers +# 6| 4: [Field] RequiredField +# 6| -1: [TypeMention] object +# 7| 5: [Property] RequiredProperty +# 7| -1: [TypeMention] string +# 7| 3: [Getter] get_RequiredProperty +# 7| 4: [Setter] set_RequiredProperty +#-----| 2: (Parameters) +# 7| 0: [Parameter] value +# 8| 6: [Property] VirtualProperty +# 8| -1: [TypeMention] object +# 8| 3: [Getter] get_VirtualProperty +# 8| 4: [Setter] set_VirtualProperty +#-----| 2: (Parameters) +# 8| 0: [Parameter] value +# 10| 7: [InstanceConstructor] ClassRequiredMembers +# 10| 4: [BlockStmt] {...} +# 13| 8: [InstanceConstructor] ClassRequiredMembers +#-----| 0: (Attributes) +# 12| 1: [DefaultAttribute] [SetsRequiredMembers(...)] +# 12| 0: [TypeMention] SetsRequiredMembersAttribute +#-----| 2: (Parameters) +# 13| 0: [Parameter] requiredField +# 13| -1: [TypeMention] object +# 13| 1: [Parameter] requiredProperty +# 13| -1: [TypeMention] string +# 14| 4: [BlockStmt] {...} +# 15| 0: [ExprStmt] ...; +# 15| 0: [AssignExpr] ... = ... +# 15| 0: [FieldAccess] access to field RequiredField +# 15| 1: [ParameterAccess] access to parameter requiredField +# 16| 1: [ExprStmt] ...; +# 16| 0: [AssignExpr] ... = ... +# 16| 0: [PropertyCall] access to property RequiredProperty +# 16| 1: [ParameterAccess] access to parameter requiredProperty +# 20| [Class] ClassRequiredMembersSub +#-----| 3: (Base types) +# 20| 0: [TypeMention] ClassRequiredMembers +# 22| 4: [Property] VirtualProperty +# 22| -1: [TypeMention] object +# 22| 3: [Getter] get_VirtualProperty +# 22| 4: [Setter] set_VirtualProperty +#-----| 2: (Parameters) +# 22| 0: [Parameter] value +# 24| 5: [InstanceConstructor] ClassRequiredMembersSub +# 24| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers +# 24| 4: [BlockStmt] {...} +# 27| 6: [InstanceConstructor] ClassRequiredMembersSub +#-----| 0: (Attributes) +# 26| 1: [DefaultAttribute] [SetsRequiredMembers(...)] +# 26| 0: [TypeMention] SetsRequiredMembersAttribute +#-----| 2: (Parameters) +# 27| 0: [Parameter] requiredField +# 27| -1: [TypeMention] object +# 27| 1: [Parameter] requiredProperty +# 27| -1: [TypeMention] string +# 27| 2: [Parameter] virtualProperty +# 27| -1: [TypeMention] object +# 27| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers +# 27| 0: [ParameterAccess] access to parameter requiredField +# 27| 1: [ParameterAccess] access to parameter requiredProperty +# 28| 4: [BlockStmt] {...} +# 29| 0: [ExprStmt] ...; +# 29| 0: [AssignExpr] ... = ... +# 29| 0: [PropertyCall] access to property VirtualProperty +# 29| 1: [ParameterAccess] access to parameter virtualProperty +# 33| [RecordClass] RecordRequiredMembers +# 33| 12: [NEOperator] != +#-----| 2: (Parameters) +# 33| 0: [Parameter] left +# 33| 1: [Parameter] right +# 33| 13: [EQOperator] == +#-----| 2: (Parameters) +# 33| 0: [Parameter] left +# 33| 1: [Parameter] right +# 33| 14: [Property] EqualityContract +# 33| 3: [Getter] get_EqualityContract +# 35| 15: [Property] X +# 35| -1: [TypeMention] object +# 35| 3: [Getter] get_X +# 35| 4: [Setter] set_X +#-----| 2: (Parameters) +# 35| 0: [Parameter] value +# 38| [Struct] StructRequiredMembers +# 40| 5: [Property] Y +# 40| -1: [TypeMention] string +# 40| 3: [Getter] get_Y +# 40| 4: [Setter] set_Y +#-----| 2: (Parameters) +# 40| 0: [Parameter] value Scoped.cs: # 1| [Struct] S1 # 2| [Struct] S2 diff --git a/csharp/ql/test/library-tests/csharp11/RequiredMembers.cs b/csharp/ql/test/library-tests/csharp11/RequiredMembers.cs new file mode 100644 index 00000000000..9bccbd24584 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/RequiredMembers.cs @@ -0,0 +1,42 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +public class ClassRequiredMembers +{ + public required object? RequiredField; + public required string? RequiredProperty { get; init; } + public virtual object? VirtualProperty { get; init; } + + public ClassRequiredMembers() { } + + [SetsRequiredMembers] + public ClassRequiredMembers(object requiredField, string requiredProperty) + { + RequiredField = requiredField; + RequiredProperty = requiredProperty; + } +} + +public class ClassRequiredMembersSub : ClassRequiredMembers +{ + public override required object? VirtualProperty { get; init; } + + public ClassRequiredMembersSub() : base() { } + + [SetsRequiredMembers] + public ClassRequiredMembersSub(object requiredField, string requiredProperty, object virtualProperty) : base(requiredField, requiredProperty) + { + VirtualProperty = virtualProperty; + } +} + +public record RecordRequiredMembers +{ + public required object? X { get; init; } +} + +public struct StructRequiredMembers +{ + public required string? Y { get; init; } +} + diff --git a/csharp/ql/test/library-tests/csharp11/checkedOperators.expected b/csharp/ql/test/library-tests/csharp11/checkedOperators.expected new file mode 100644 index 00000000000..bbd509e36d9 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/checkedOperators.expected @@ -0,0 +1,16 @@ +| CheckedOperators.cs:9:43:9:43 | checked + | op_CheckedAddition | CheckedAddOperator | +| CheckedOperators.cs:12:35:12:35 | + | op_Addition | AddOperator | +| CheckedOperators.cs:15:43:15:43 | checked - | op_CheckedSubtraction | CheckedSubOperator | +| CheckedOperators.cs:18:35:18:35 | - | op_Subtraction | SubOperator | +| CheckedOperators.cs:21:43:21:43 | checked * | op_CheckedMultiply | CheckedMulOperator | +| CheckedOperators.cs:24:35:24:35 | * | op_Multiply | MulOperator | +| CheckedOperators.cs:27:43:27:43 | checked / | op_CheckedDivision | CheckedDivOperator | +| CheckedOperators.cs:30:35:30:35 | / | op_Division | DivOperator | +| CheckedOperators.cs:33:43:33:43 | checked - | op_CheckedUnaryNegation | CheckedMinusOperator | +| CheckedOperators.cs:36:35:36:35 | - | op_UnaryNegation | MinusOperator | +| CheckedOperators.cs:39:43:39:44 | checked ++ | op_CheckedIncrement | CheckedIncrementOperator | +| CheckedOperators.cs:42:35:42:36 | ++ | op_Increment | IncrementOperator | +| CheckedOperators.cs:45:43:45:44 | checked -- | op_CheckedDecrement | CheckedDecrementOperator | +| CheckedOperators.cs:48:35:48:36 | -- | op_Decrement | DecrementOperator | +| CheckedOperators.cs:51:28:51:35 | explicit conversion | op_Explicit | ExplicitConversionOperator | +| CheckedOperators.cs:54:28:54:35 | checked explicit conversion | op_CheckedExplicit | CheckedExplicitConversionOperator | diff --git a/csharp/ql/test/library-tests/csharp11/checkedOperators.ql b/csharp/ql/test/library-tests/csharp11/checkedOperators.ql new file mode 100644 index 00000000000..c7ad15aa625 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/checkedOperators.ql @@ -0,0 +1,5 @@ +import csharp + +from Operator o +where o.getFile().getStem() = "CheckedOperators" +select o, o.getFunctionName(), o.getAPrimaryQlClass() diff --git a/csharp/ql/test/library-tests/csharp11/requiredMembers.expected b/csharp/ql/test/library-tests/csharp11/requiredMembers.expected new file mode 100644 index 00000000000..a54084464de --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/requiredMembers.expected @@ -0,0 +1,5 @@ +| RequiredMembers.cs:6:29:6:41 | RequiredField | ClassRequiredMembers | Field | +| RequiredMembers.cs:7:29:7:44 | RequiredProperty | ClassRequiredMembers | Property | +| RequiredMembers.cs:22:38:22:52 | VirtualProperty | ClassRequiredMembersSub | Property | +| RequiredMembers.cs:35:29:35:29 | X | RecordRequiredMembers | Property | +| RequiredMembers.cs:40:29:40:29 | Y | StructRequiredMembers | Property | diff --git a/csharp/ql/test/library-tests/csharp11/requiredMembers.ql b/csharp/ql/test/library-tests/csharp11/requiredMembers.ql new file mode 100644 index 00000000000..e0be03dd906 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/requiredMembers.ql @@ -0,0 +1,8 @@ +import csharp + +query predicate requiredmembers(Member m, string type, string qlclass) { + m.getFile().getStem() = "RequiredMembers" and + m.isRequired() and + type = m.getDeclaringType().getName() and + qlclass = m.getAPrimaryQlClass() +} diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 213fc0eb4cf..0e52045cbdf 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -238,3 +238,7 @@ | ViableCallable.cs:458:10:458:14 | M5<> | ViableCallable.cs:444:23:444:27 | M2<> | | ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:468:10:468:11 | M2 | | ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:473:17:473:18 | M1 | +| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:487:32:487:32 | + | +| 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 | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index fb0547dffcd..074deaf9dff 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -471,3 +471,7 @@ | ViableCallable.cs:461:9:461:30 | call to method M2 | C17.M2(Func) | | ViableCallable.cs:478:9:478:14 | call to method M1 | C18.M1() | | ViableCallable.cs:481:9:481:14 | call to method M2 | I2.M2() | +| ViableCallable.cs:495:18:495:22 | call to operator + | C19.+(C19, C19) | +| 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) | diff --git a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs index c742789fef3..6345bb3510e 100644 --- a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs +++ b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs @@ -480,4 +480,27 @@ class C18 : I2 // Viable callables: I2.M2() i.M2(); } +} + +class C19 +{ + public static C19 operator +(C19 x, C19 y) => throw null; + public static C19 operator checked +(C19 x, C19 y) => throw null; + public static explicit operator int(C19 x) => throw null; + public static explicit operator checked int(C19 x) => throw null; + + void Run(C19 c) + { + // Viable callables: C19.op_Addition() + var c1 = c + c; + + // Viable callables: C19.op_CheckedAddition() + var c2 = checked(c + c); + + // Viable callables: C19.op_Explicit() + var n1 = (int)c; + + // Viable callables: C19.op_CheckedExplicit() + var n2 = checked((int)c); + } } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dispatch/viableCallable.expected b/csharp/ql/test/library-tests/dispatch/viableCallable.expected index 2de575c5291..d752fb824da 100644 --- a/csharp/ql/test/library-tests/dispatch/viableCallable.expected +++ b/csharp/ql/test/library-tests/dispatch/viableCallable.expected @@ -268,3 +268,7 @@ | ViableCallable.cs:423:9:423:21 | call to method M | M<> | A5 | | ViableCallable.cs:478:9:478:14 | call to method M1 | M1 | C18 | | ViableCallable.cs:481:9:481:14 | call to method M2 | M2 | I2 | +| ViableCallable.cs:495:18:495:22 | call to operator + | + | C19 | +| 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 | diff --git a/csharp/scripts/create-extractor-pack.sh b/csharp/scripts/create-extractor-pack.sh index 2308ed7cd89..dbaf18b40c2 100755 --- a/csharp/scripts/create-extractor-pack.sh +++ b/csharp/scripts/create-extractor-pack.sh @@ -6,7 +6,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then dotnet_platform="linux-x64" elif [[ "$OSTYPE" == "darwin"* ]]; then platform="osx64" - dotnet_platform="osx-x64" + if [[ $(uname -m) == 'arm64' ]]; then + dotnet_platform="osx-arm64" + else + dotnet_platform="osx-x64" + fi else echo "Unknown OS" exit 1 diff --git a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst index ca52df98f73..9150102f212 100644 --- a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst +++ b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst @@ -204,6 +204,7 @@ The completed query will now identify cases where the result of ``strlen`` is st .. code-block:: ql import cpp + import semmle.code.cpp.controlflow.SSA class MallocCall extends FunctionCall { diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index 5f6f5993a32..196bb1a44dd 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -16,8 +16,8 @@ .NET Core up to 3.1 .NET 5, .NET 6","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" - Go (aka Golang), "Go up to 1.19", "Go 1.11 or more recent", ``.go`` - Java,"Java 7 to 19 [4]_","javac (OpenJDK and Oracle JDK), + Go (aka Golang), "Go up to 1.20", "Go 1.11 or more recent", ``.go`` + Java,"Java 7 to 20 [4]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [5]_",``.java`` Kotlin [6]_,"Kotlin 1.5.0 to 1.8.20","kotlinc",``.kt`` @@ -31,7 +31,7 @@ .. [1] C++20 support is currently in beta. Supported for GCC on Linux only. Modules are *not* supported. .. [2] Support for the clang-cl compiler is preliminary. .. [3] Support for the Arm Compiler (armcc) is preliminary. - .. [4] Builds that execute on Java 7 to 19 can be analyzed. The analysis understands Java 19 standard language features. + .. [4] Builds that execute on Java 7 to 20 can be analyzed. The analysis understands Java 20 standard language features. .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. .. [6] Kotlin support is currently in beta. .. [7] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. diff --git a/go/go.mod b/go/go.mod index 48bdb72b158..516bc228330 100644 --- a/go/go.mod +++ b/go/go.mod @@ -1,13 +1,13 @@ module github.com/github/codeql-go -go 1.18 +go 1.20 require ( - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 - golang.org/x/tools v0.1.12 + golang.org/x/mod v0.8.0 + golang.org/x/tools v0.6.0 ) require ( - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/sys v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/go/go.sum b/go/go.sum index 9054efe904e..d92f42b1d05 100644 --- a/go/go.sum +++ b/go/go.sum @@ -6,6 +6,8 @@ golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -19,6 +21,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0v golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -28,6 +32,8 @@ golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 687d1d2ca66..1a5db51a5ee 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.4.3 + +### New Features + +* Go 1.20 is now supported. The extractor now functions as expected when Go 1.20 is installed; the definition of `implementsComparable` has been updated according to Go 1.20's new, more-liberal rules; and taint flow models have been added for relevant, new standard-library functions. + +### Minor Analysis Improvements + +* Support for the Twirp framework has been added. + ## 0.4.2 No user-facing changes. diff --git a/go/ql/lib/change-notes/2023-02-01--add-support-for-twirp-framework.md b/go/ql/lib/change-notes/2023-02-01--add-support-for-twirp-framework.md deleted file mode 100644 index 1bbf2df72cf..00000000000 --- a/go/ql/lib/change-notes/2023-02-01--add-support-for-twirp-framework.md +++ /dev/null @@ -1,2 +0,0 @@ -lgtm,codescanning -* Support for the Twirp framework has been added. diff --git a/go/ql/lib/change-notes/released/0.4.3.md b/go/ql/lib/change-notes/released/0.4.3.md new file mode 100644 index 00000000000..812c902d9bf --- /dev/null +++ b/go/ql/lib/change-notes/released/0.4.3.md @@ -0,0 +1,9 @@ +## 0.4.3 + +### New Features + +* Go 1.20 is now supported. The extractor now functions as expected when Go 1.20 is installed; the definition of `implementsComparable` has been updated according to Go 1.20's new, more-liberal rules; and taint flow models have been added for relevant, new standard-library functions. + +### Minor Analysis Improvements + +* Support for the Twirp framework has been added. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 94c5b17423c..1ec9c4ea5d9 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.2 +lastReleaseVersion: 0.4.3 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 7519fff5a28..6d9f6fb8962 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.4.3-dev +version: 0.4.4-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index 76a0455a20b..ea522b2e11e 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -112,22 +112,10 @@ class Type extends @type { or u instanceof ArrayType and u.(ArrayType).getElementType().implementsComparable() or - exists(InterfaceType uif | uif = u | - not uif instanceof BasicInterfaceType and - if exists(uif.getAnEmbeddedTypeSetLiteral()) - then - // All types in the intersection of all the embedded type set - // literals must implement comparable. - forall(Type intersectionType | - intersectionType = uif.getAnEmbeddedTypeSetLiteral().getATerm().getType() and - forall(TypeSetLiteralType tslit | tslit = uif.getAnEmbeddedTypeSetLiteral() | - intersectionType = tslit.getATerm().getType() - ) - | - intersectionType.implementsComparable() - ) - else uif.isOrEmbedsComparable() - ) + // As of Go 1.20, any interface type satisfies the `comparable` constraint, even though comparison + // may panic at runtime depending on the actual object's concrete type. + // Look at git history here if you need the old definition. + u instanceof InterfaceType ) } diff --git a/go/ql/lib/semmle/go/frameworks/Stdlib.qll b/go/ql/lib/semmle/go/frameworks/Stdlib.qll index db46167d205..232055ca751 100644 --- a/go/ql/lib/semmle/go/frameworks/Stdlib.qll +++ b/go/ql/lib/semmle/go/frameworks/Stdlib.qll @@ -65,6 +65,7 @@ import semmle.go.frameworks.stdlib.Syscall import semmle.go.frameworks.stdlib.TextScanner import semmle.go.frameworks.stdlib.TextTabwriter import semmle.go.frameworks.stdlib.TextTemplate +import semmle.go.frameworks.stdlib.Unsafe /** A `String()` method. */ class StringMethod extends TaintTracking::FunctionModel, Method { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Bytes.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Bytes.qll index c2791b1eaa3..3d8df63f5fa 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Bytes.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Bytes.qll @@ -11,6 +11,15 @@ module Bytes { FunctionOutput outp; FunctionModels() { + hasQualifiedName("bytes", "Clone") and + (inp.isParameter(0) and outp.isResult()) + or + hasQualifiedName("bytes", "Cut") and + (inp.isParameter(0) and outp.isResult([0, 1])) + or + hasQualifiedName("bytes", ["CutPrefix", "CutSuffix"]) and + (inp.isParameter(0) and outp.isResult(0)) + or // signature: func Fields(s []byte) [][]byte hasQualifiedName("bytes", "Fields") and (inp.isParameter(0) and outp.isResult()) diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll index 5225ad97fee..b38584f1e92 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll @@ -22,6 +22,10 @@ module Errors { // signature: func Unwrap(err error) error hasQualifiedName("errors", "Unwrap") and (inp.isParameter(0) and outp.isResult()) + or + // signature: func Join(errs ...error) error + hasQualifiedName("errors", "Join") and + (inp.isParameter(_) and outp.isResult()) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Sync.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Sync.qll index b82e1e59804..fcdb7660441 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Sync.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Sync.qll @@ -11,6 +11,9 @@ module Sync { FunctionOutput outp; MethodModels() { + hasQualifiedName("sync", "Map", "CompareAndSwap") and + (inp.isParameter(2) and outp.isReceiver()) + or // signature: func (*Map) Load(key interface{}) (value interface{}, ok bool) hasQualifiedName("sync", "Map", "Load") and (inp.isReceiver() and outp.isResult(0)) @@ -28,6 +31,13 @@ module Sync { hasQualifiedName("sync", "Map", "Store") and (inp.isParameter(_) and outp.isReceiver()) or + hasQualifiedName("sync", "Map", "Swap") and + ( + inp.isReceiver() and outp.isResult(0) + or + inp.isParameter(_) and outp.isReceiver() + ) + or // signature: func (*Pool) Get() interface{} hasQualifiedName("sync", "Pool", "Get") and (inp.isReceiver() and outp.isResult()) diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll new file mode 100644 index 00000000000..d9b83da9f24 --- /dev/null +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll @@ -0,0 +1,22 @@ +/** + * Provides classes modeling security-relevant aspects of the `unsafe` package. + */ + +import go + +/** Provides models of commonly used functions in the `unsafe` package. */ +module Unsafe { + private class FunctionModels extends TaintTracking::FunctionModel { + FunctionInput inp; + FunctionOutput outp; + + FunctionModels() { + hasQualifiedName("unsafe", ["String", "StringData", "Slice", "SliceData"]) and + (inp.isParameter(0) and outp.isResult()) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } +} diff --git a/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll b/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll index 060832cfffc..1c0b647e91f 100644 --- a/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll +++ b/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll @@ -56,14 +56,14 @@ private predicate isIncorrectIntegerConversion(int sourceBitSize, int sinkBitSiz * integer types, which could cause unexpected values. */ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { - boolean sourceIsSigned; + boolean sinkIsSigned; int sourceBitSize; int sinkBitSize; ConversionWithoutBoundsCheckConfig() { - sourceIsSigned in [true, false] and + sinkIsSigned in [true, false] and isIncorrectIntegerConversion(sourceBitSize, sinkBitSize) and - this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sourceIsSigned + sinkBitSize + this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sinkIsSigned + sinkBitSize } /** Gets the bit size of the source. */ @@ -75,11 +75,6 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { | c.getTarget() = ip and source = c.getResult(0) | - ( - if ip.getResultType(0) instanceof SignedIntegerType - then sourceIsSigned = true - else sourceIsSigned = false - ) and ( apparentBitSize = ip.getTargetBitSize() or @@ -112,10 +107,13 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { predicate isSinkWithBitSize(DataFlow::TypeCastNode sink, int bitSize) { sink.asExpr() instanceof ConversionExpr and exists(IntegerType integerType | sink.getResultType().getUnderlyingType() = integerType | - bitSize = integerType.getSize() - or - not exists(integerType.getSize()) and - bitSize = getIntTypeBitSize(sink.getFile()) + ( + bitSize = integerType.getSize() + or + not exists(integerType.getSize()) and + bitSize = getIntTypeBitSize(sink.getFile()) + ) and + if integerType instanceof SignedIntegerType then sinkIsSigned = true else sinkIsSigned = false ) and not exists(ShrExpr shrExpr | shrExpr.getLeftOperand().getGlobalValueNumber() = @@ -134,7 +132,7 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { if sinkBitSize != 0 then bitSize = sinkBitSize else bitSize = 32 | node = DataFlow::BarrierGuard::getABarrierNodeForGuard(g) and - g.isBoundFor(bitSize, sourceIsSigned) + g.isBoundFor(bitSize, sinkIsSigned) ) } diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index 7271b252996..d7c6b659d23 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.4.3 + +### New Queries + +* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors. + +### Query Metadata Changes + +* The precision of the `go/log-injection` query was decreased from `high` to `medium`, since it may not be able to identify every way in which log data may be sanitized. This also aligns it with the precision of comparable queries for other languages. + ## 0.4.2 No user-facing changes. diff --git a/go/ql/src/change-notes/2023-02-06-unhandled-close-writable-handle.md b/go/ql/src/change-notes/2023-02-06-unhandled-close-writable-handle.md deleted file mode 100644 index a759cd48517..00000000000 --- a/go/ql/src/change-notes/2023-02-06-unhandled-close-writable-handle.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: newQuery ---- -* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors. diff --git a/go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md b/go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md new file mode 100644 index 00000000000..9fb36271a32 --- /dev/null +++ b/go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md @@ -0,0 +1,4 @@ +--- +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]`. diff --git a/go/ql/src/change-notes/2023-02-09-log-injection-precision.md b/go/ql/src/change-notes/released/0.4.3.md similarity index 54% rename from go/ql/src/change-notes/2023-02-09-log-injection-precision.md rename to go/ql/src/change-notes/released/0.4.3.md index 668d06dbfb5..3a1f617387c 100644 --- a/go/ql/src/change-notes/2023-02-09-log-injection-precision.md +++ b/go/ql/src/change-notes/released/0.4.3.md @@ -1,4 +1,9 @@ ---- -category: queryMetadata ---- +## 0.4.3 + +### New Queries + +* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors. + +### Query Metadata Changes + * The precision of the `go/log-injection` query was decreased from `high` to `medium`, since it may not be able to identify every way in which log data may be sanitized. This also aligns it with the precision of comparable queries for other languages. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 94c5b17423c..1ec9c4ea5d9 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.2 +lastReleaseVersion: 0.4.3 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 191e4d8f940..a5a4c5de846 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.4.3-dev +version: 0.4.4-dev groups: - go - queries diff --git a/go/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected b/go/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected index fc69f87cc3f..aa526b3e750 100644 --- a/go/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected +++ b/go/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected @@ -1,7 +1,7 @@ | -:0:0:0:0 | package ; expected main | -| broken2/test1.go:4:2:4:2 | undeclared name: fmt | -| broken2/test1.go:5:2:5:2 | undeclared name: fmt | -| broken2/test1.go:5:14:5:14 | undeclared name: a | +| broken2/test1.go:4:2:4:2 | undefined: fmt | +| broken2/test1.go:5:2:5:2 | undefined: fmt | +| broken2/test1.go:5:14:5:14 | undefined: a | | broken2/test.go:3:1:3:1 | expected 'package', found pac | | broken2/test.go:3:1:3:1 | expected 'package', found pac | | broken2/test.go:3:4:3:4 | expected 'IDENT', found newline | diff --git a/go/ql/test/extractor-tests/diagnostics/Diagnostics.expected b/go/ql/test/extractor-tests/diagnostics/Diagnostics.expected index af155e81213..9d89f8c411b 100644 --- a/go/ql/test/extractor-tests/diagnostics/Diagnostics.expected +++ b/go/ql/test/extractor-tests/diagnostics/Diagnostics.expected @@ -5,8 +5,8 @@ qcompilations | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | go.mod:0:0:0:0 | go.mod | | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | notbroken/test.go:0:0:0:0 | notbroken/test.go | qdiagnostics -| broken2/test1.go:4:2:4:2 | error: undeclared name: fmt | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | -| broken2/test1.go:5:2:5:2 | error: undeclared name: fmt | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | -| broken2/test1.go:5:14:5:14 | error: undeclared name: a | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | +| broken2/test1.go:4:2:4:2 | error: undefined: fmt | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | +| broken2/test1.go:5:2:5:2 | error: undefined: fmt | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | +| broken2/test1.go:5:14:5:14 | error: undefined: a | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken2/test1.go:0:0:0:0 | broken2/test1.go | | broken/test.go:7:1:7:1 | error: expected declaration, found This | compilation in 'diagnostics': go-extractor -mod=vendor -- ./... | broken/test.go:0:0:0:0 | broken/test.go | duplicateerrs diff --git a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected index 661cc77556f..6178ffff530 100644 --- a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected +++ b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected @@ -13,3 +13,4 @@ | TG2 | interface { } | | U | interface { } | | V | interface { int64 \| float64 } | +| bytes | interface { []uint8 \| string } | diff --git a/go/ql/test/library-tests/semmle/go/Types/CONSISTENCY/UnexpectedFrontendErrors.expected b/go/ql/test/library-tests/semmle/go/Types/CONSISTENCY/UnexpectedFrontendErrors.expected index fa64f5084a9..be9b19ab4f1 100644 --- a/go/ql/test/library-tests/semmle/go/Types/CONSISTENCY/UnexpectedFrontendErrors.expected +++ b/go/ql/test/library-tests/semmle/go/Types/CONSISTENCY/UnexpectedFrontendErrors.expected @@ -1 +1 @@ -| unknownFunction.go:9:7:9:7 | undeclared name: unknownFunction | +| unknownFunction.go:9:7:9:7 | undefined: unknownFunction | diff --git a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected index b658da877e7..3f170370284 100644 --- a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected +++ b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected @@ -51,31 +51,31 @@ | interface.go:95:6:95:8 | i18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i18 | | interface.go:101:6:101:8 | i19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i19 | | interface.go:105:6:105:8 | i20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i20 | -| interface.go:110:6:110:19 | testComparable | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable | -| interface.go:111:6:111:20 | testComparable0 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable0 | -| interface.go:112:6:112:20 | testComparable1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable1 | -| interface.go:113:6:113:20 | testComparable2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable2 | -| interface.go:114:6:114:20 | testComparable3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable3 | -| interface.go:115:6:115:20 | testComparable4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable4 | -| interface.go:116:6:116:20 | testComparable5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable5 | -| interface.go:117:6:117:20 | testComparable6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable6 | -| interface.go:118:6:118:20 | testComparable7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable7 | -| interface.go:119:6:119:20 | testComparable8 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable8 | -| interface.go:120:6:120:20 | testComparable9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable9 | -| interface.go:121:6:121:21 | testComparable10 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable10 | -| interface.go:122:6:122:21 | testComparable11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable11 | -| interface.go:123:6:123:21 | testComparable12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable12 | -| interface.go:124:6:124:21 | testComparable13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable13 | -| interface.go:125:6:125:21 | testComparable14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable14 | -| interface.go:126:6:126:21 | testComparable15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable15 | -| interface.go:127:6:127:21 | testComparable16 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable16 | -| interface.go:128:6:128:21 | testComparable17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable17 | -| interface.go:129:6:129:21 | testComparable18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable18 | -| interface.go:130:6:130:21 | testComparable19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable19 | -| interface.go:131:6:131:21 | testComparable20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable20 | -| interface.go:132:6:132:21 | testComparable21 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable21 | -| interface.go:133:6:133:21 | testComparable22 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable22 | -| interface.go:134:6:134:21 | testComparable23 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable23 | +| interface.go:114:6:114:19 | testComparable | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable | +| interface.go:115:6:115:20 | testComparable0 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable0 | +| interface.go:116:6:116:20 | testComparable1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable1 | +| interface.go:117:6:117:20 | testComparable2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable2 | +| interface.go:118:6:118:20 | testComparable3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable3 | +| interface.go:119:6:119:20 | testComparable4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable4 | +| interface.go:120:6:120:20 | testComparable5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable5 | +| interface.go:121:6:121:20 | testComparable6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable6 | +| interface.go:122:6:122:20 | testComparable7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable7 | +| interface.go:123:6:123:20 | testComparable8 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable8 | +| interface.go:124:6:124:20 | testComparable9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable9 | +| interface.go:125:6:125:21 | testComparable10 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable10 | +| interface.go:126:6:126:21 | testComparable11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable11 | +| interface.go:127:6:127:21 | testComparable12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable12 | +| interface.go:128:6:128:21 | testComparable13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable13 | +| interface.go:129:6:129:21 | testComparable14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable14 | +| interface.go:130:6:130:21 | testComparable15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable15 | +| interface.go:131:6:131:21 | testComparable16 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable16 | +| interface.go:132:6:132:21 | testComparable17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable17 | +| interface.go:133:6:133:21 | testComparable18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable18 | +| interface.go:134:6:134:21 | testComparable19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable19 | +| interface.go:135:6:135:21 | testComparable20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable20 | +| interface.go:136:6:136:21 | testComparable21 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable21 | +| interface.go:137:6:137:21 | testComparable22 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable22 | +| interface.go:138:6:138:21 | testComparable23 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable23 | | pkg1/embedding.go:8:6:8:9 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base | | pkg1/embedding.go:19:6:19:13 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | | pkg1/embedding.go:22:6:22:16 | ptrembedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | diff --git a/go/ql/test/library-tests/semmle/go/Types/Types.expected b/go/ql/test/library-tests/semmle/go/Types/Types.expected index 76933af4008..b4a05a8858d 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Types.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Types.expected @@ -51,31 +51,31 @@ | interface.go:95:6:95:8 | i18 | i18 | | interface.go:101:6:101:8 | i19 | i19 | | interface.go:105:6:105:8 | i20 | i20 | -| interface.go:110:6:110:19 | testComparable | testComparable | -| interface.go:111:6:111:20 | testComparable0 | testComparable0 | -| interface.go:112:6:112:20 | testComparable1 | testComparable1 | -| interface.go:113:6:113:20 | testComparable2 | testComparable2 | -| interface.go:114:6:114:20 | testComparable3 | testComparable3 | -| interface.go:115:6:115:20 | testComparable4 | testComparable4 | -| interface.go:116:6:116:20 | testComparable5 | testComparable5 | -| interface.go:117:6:117:20 | testComparable6 | testComparable6 | -| interface.go:118:6:118:20 | testComparable7 | testComparable7 | -| interface.go:119:6:119:20 | testComparable8 | testComparable8 | -| interface.go:120:6:120:20 | testComparable9 | testComparable9 | -| interface.go:121:6:121:21 | testComparable10 | testComparable10 | -| interface.go:122:6:122:21 | testComparable11 | testComparable11 | -| interface.go:123:6:123:21 | testComparable12 | testComparable12 | -| interface.go:124:6:124:21 | testComparable13 | testComparable13 | -| interface.go:125:6:125:21 | testComparable14 | testComparable14 | -| interface.go:126:6:126:21 | testComparable15 | testComparable15 | -| interface.go:127:6:127:21 | testComparable16 | testComparable16 | -| interface.go:128:6:128:21 | testComparable17 | testComparable17 | -| interface.go:129:6:129:21 | testComparable18 | testComparable18 | -| interface.go:130:6:130:21 | testComparable19 | testComparable19 | -| interface.go:131:6:131:21 | testComparable20 | testComparable20 | -| interface.go:132:6:132:21 | testComparable21 | testComparable21 | -| interface.go:133:6:133:21 | testComparable22 | testComparable22 | -| interface.go:134:6:134:21 | testComparable23 | testComparable23 | +| interface.go:114:6:114:19 | testComparable | testComparable | +| interface.go:115:6:115:20 | testComparable0 | testComparable0 | +| interface.go:116:6:116:20 | testComparable1 | testComparable1 | +| interface.go:117:6:117:20 | testComparable2 | testComparable2 | +| interface.go:118:6:118:20 | testComparable3 | testComparable3 | +| interface.go:119:6:119:20 | testComparable4 | testComparable4 | +| interface.go:120:6:120:20 | testComparable5 | testComparable5 | +| interface.go:121:6:121:20 | testComparable6 | testComparable6 | +| interface.go:122:6:122:20 | testComparable7 | testComparable7 | +| interface.go:123:6:123:20 | testComparable8 | testComparable8 | +| interface.go:124:6:124:20 | testComparable9 | testComparable9 | +| interface.go:125:6:125:21 | testComparable10 | testComparable10 | +| interface.go:126:6:126:21 | testComparable11 | testComparable11 | +| interface.go:127:6:127:21 | testComparable12 | testComparable12 | +| interface.go:128:6:128:21 | testComparable13 | testComparable13 | +| interface.go:129:6:129:21 | testComparable14 | testComparable14 | +| interface.go:130:6:130:21 | testComparable15 | testComparable15 | +| interface.go:131:6:131:21 | testComparable16 | testComparable16 | +| interface.go:132:6:132:21 | testComparable17 | testComparable17 | +| interface.go:133:6:133:21 | testComparable18 | testComparable18 | +| interface.go:134:6:134:21 | testComparable19 | testComparable19 | +| interface.go:135:6:135:21 | testComparable20 | testComparable20 | +| interface.go:136:6:136:21 | testComparable21 | testComparable21 | +| interface.go:137:6:137:21 | testComparable22 | testComparable22 | +| interface.go:138:6:138:21 | testComparable23 | testComparable23 | | pkg1/embedding.go:8:6:8:9 | base | base | | pkg1/embedding.go:19:6:19:13 | embedder | embedder | | pkg1/embedding.go:22:6:22:16 | ptrembedder | ptrembedder | diff --git a/go/ql/test/library-tests/semmle/go/Types/interface.go b/go/ql/test/library-tests/semmle/go/Types/interface.go index 40653aaca71..afda7e759a0 100644 --- a/go/ql/test/library-tests/semmle/go/Types/interface.go +++ b/go/ql/test/library-tests/semmle/go/Types/interface.go @@ -107,28 +107,32 @@ type i20 interface { StringB() string } -type testComparable[T comparable] struct{} // $ implementsComparable -type testComparable0[T0 i0] struct{} // $ implementsComparable -type testComparable1[T1 i1] struct{} // $ implementsComparable -type testComparable2[T2 i2] struct{} // $ implementsComparable -type testComparable3[T3 i3] struct{} // $ implementsComparable -type testComparable4[T4 i4] struct{} // $ implementsComparable -type testComparable5[T5 i5] struct{} // does not implement comparable -type testComparable6[T6 i6] struct{} // does not implement comparable -type testComparable7[T7 i7] struct{} // $ implementsComparable -type testComparable8[T8 i8] struct{} // does not implement comparable -type testComparable9[T9 i9] struct{} // does not implement comparable -type testComparable10[T10 i10] struct{} // $ implementsComparable -type testComparable11[T11 i11] struct{} // $ implementsComparable -type testComparable12[T12 i12] struct{} // does not implement comparable -type testComparable13[T13 i13] struct{} // does not implement comparable -type testComparable14[T14 i14] struct{} // $ implementsComparable -type testComparable15[T15 i15] struct{} // $ implementsComparable -type testComparable16[T16 i16] struct{} // does not implement comparable -type testComparable17[T17 i17] struct{} // does not implement comparable -type testComparable18[T18 i18] struct{} // $ implementsComparable -type testComparable19[T19 i19] struct{} // does not implement comparable -type testComparable20[T20 i20] struct{} // $ implementsComparable -type testComparable21[T21 ~[]byte | string] struct{} // does not implement comparable -type testComparable22[T22 any] struct{} // does not implement comparable -type testComparable23[T23 ~[5]byte | string] struct{} // $ implementsComparable +// These used to distinguish strictly-comparable interfaces (i.e. those which will not panic at runtime on attempting a comparison), +// which were required to satisfy the `comparable` type constraint in Go <1.20. Now they all match `comparable` as all interfaces +// are accepted. I mark those which are also strictly comparable for the future in case we want to expose that concept in QL. + +type testComparable[T comparable] struct{} // $ implementsComparable isStrictlyComparable +type testComparable0[T0 i0] struct{} // $ implementsComparable isStrictlyComparable +type testComparable1[T1 i1] struct{} // $ implementsComparable isStrictlyComparable +type testComparable2[T2 i2] struct{} // $ implementsComparable isStrictlyComparable +type testComparable3[T3 i3] struct{} // $ implementsComparable isStrictlyComparable +type testComparable4[T4 i4] struct{} // $ implementsComparable isStrictlyComparable +type testComparable5[T5 i5] struct{} // $ implementsComparable +type testComparable6[T6 i6] struct{} // $ implementsComparable +type testComparable7[T7 i7] struct{} // $ implementsComparable isStrictlyComparable +type testComparable8[T8 i8] struct{} // $ implementsComparable +type testComparable9[T9 i9] struct{} // $ implementsComparable +type testComparable10[T10 i10] struct{} // $ implementsComparable isStrictlyComparable +type testComparable11[T11 i11] struct{} // $ implementsComparable isStrictlyComparable +type testComparable12[T12 i12] struct{} // $ implementsComparable +type testComparable13[T13 i13] struct{} // $ implementsComparable +type testComparable14[T14 i14] struct{} // $ implementsComparable isStrictlyComparable +type testComparable15[T15 i15] struct{} // $ implementsComparable isStrictlyComparable +type testComparable16[T16 i16] struct{} // $ implementsComparable +type testComparable17[T17 i17] struct{} // $ implementsComparable +type testComparable18[T18 i18] struct{} // $ implementsComparable isStrictlyComparable +type testComparable19[T19 i19] struct{} // $ implementsComparable +type testComparable20[T20 i20] struct{} // $ implementsComparable isStrictlyComparable +type testComparable21[T21 ~[]byte | string] struct{} // $ implementsComparable +type testComparable22[T22 any] struct{} // $ implementsComparable +type testComparable23[T23 ~[5]byte | string] struct{} // $ implementsComparable isStrictlyComparable diff --git a/go/ql/test/library-tests/semmle/go/Types/variadicFunctions.go b/go/ql/test/library-tests/semmle/go/Types/variadicFunctions.go index 427adeb9041..4cedb679b04 100644 --- a/go/ql/test/library-tests/semmle/go/Types/variadicFunctions.go +++ b/go/ql/test/library-tests/semmle/go/Types/variadicFunctions.go @@ -7,7 +7,7 @@ func testing() { nonvariadicDeclaredFunction([]int{}) } -func variadicDeclaredFunction(x ...int) int { // $ isVariadic +func variadicDeclaredFunction(x ...int) int { a := make([]int, 0, 10) y := append(x, a...) print(x[0], x[1]) @@ -15,7 +15,7 @@ func variadicDeclaredFunction(x ...int) int { // $ isVariadic fmt.Fprint(nil, nil, nil) variadicFunctionLiteral := func(z ...int) int { return z[1] } // $ isVariadic return variadicFunctionLiteral(y...) -} +} // $ isVariadic func nonvariadicDeclaredFunction(x []int) int { return 0 diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/main.go b/go/ql/test/library-tests/semmle/go/concepts/HTTP/main.go index 12a3929cec6..5bd6dbf185e 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/main.go +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/main.go @@ -59,7 +59,7 @@ func main() { http.HandleFunc("/foo", handler) // $ handler="/foo" - http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { // $ handler="/bar" + http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) - }) + }) // $ handler="/bar" } diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedCalls.expected b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected similarity index 100% rename from python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedCalls.expected rename to go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.expected diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.ql b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.ql new file mode 100644 index 00000000000..e6e99b0e6c2 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/Flows.ql @@ -0,0 +1,58 @@ +import go +import TestUtilities.InlineExpectationsTest + +class DataConfiguration extends DataFlow::Configuration { + DataConfiguration() { this = "data-configuration" } + + override predicate isSource(DataFlow::Node source) { + source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0) + } + + override predicate isSink(DataFlow::Node sink) { + sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) + } +} + +class DataFlowTest extends InlineExpectationsTest { + DataFlowTest() { this = "DataFlowTest" } + + override string getARelevantTag() { result = "dataflow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "dataflow" and + exists(DataFlow::Node sink | any(DataConfiguration c).hasFlow(_, sink) | + element = sink.toString() and + value = "" and + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) + ) + } +} + +class TaintConfiguration extends TaintTracking::Configuration { + TaintConfiguration() { this = "taint-configuration" } + + override predicate isSource(DataFlow::Node source) { + source = any(DataFlow::CallNode c | c.getCalleeName() = "source").getResult(0) + } + + override predicate isSink(DataFlow::Node sink) { + sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) + } +} + +class TaintFlowTest extends InlineExpectationsTest { + TaintFlowTest() { this = "TaintFlowTest" } + + override string getARelevantTag() { result = "taintflow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "taintflow" and + exists(DataFlow::Node sink | any(TaintConfiguration c).hasFlow(_, sink) | + element = sink.toString() and + value = "" and + sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) + ) + } +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/main.go b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/main.go new file mode 100644 index 00000000000..1c83b891680 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/ArrayConversion/main.go @@ -0,0 +1,25 @@ +package main + +func source() string { + return "untrusted data" +} + +func sink(string) { +} + +func sliceToArray(p []string) [1]string { + return [1]string(p) +} + +func main() { + // Test the new slice->array conversion permitted in Go 1.20 + var a [4]string + a[0] = source() + alias := sliceToArray(a[:]) + sink(alias[0]) // $ taintflow + + // Compare with the standard dataflow support for arrays + var b [4]string + b[0] = source() + sink(b[0]) // $ taintflow +} diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Bytes.go b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Bytes.go index a4d3230c009..8e31c32aba4 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Bytes.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Bytes.go @@ -316,6 +316,39 @@ func TaintStepTest_BytesReaderWriteTo_B0I0O0(sourceCQL interface{}) interface{} return intoWriter197 } +func TaintStepTest_Clone(sourceCQL interface{}) interface{} { + fromReader628 := sourceCQL.([]byte) + return bytes.Clone(fromReader628) +} + +func TaintStepTest_Cutleft(sourceCQL interface{}) interface{} { + fromReader628 := sourceCQL.([]byte) + sep := []byte{} + left, _, _ := bytes.Cut(fromReader628, sep) + return left +} + +func TaintStepTest_Cutright(sourceCQL interface{}) interface{} { + fromReader628 := sourceCQL.([]byte) + sep := []byte{} + _, right, _ := bytes.Cut(fromReader628, sep) + return right +} + +func TaintStepTest_CutPrefix(sourceCQL interface{}) interface{} { + fromReader628 := sourceCQL.([]byte) + sep := []byte{} + result, _ := bytes.CutPrefix(fromReader628, sep) + return result +} + +func TaintStepTest_CutSuffix(sourceCQL interface{}) interface{} { + fromReader628 := sourceCQL.([]byte) + sep := []byte{} + result, _ := bytes.CutSuffix(fromReader628, sep) + return result +} + func RunAllTaints_Bytes() { { source := newSource(0) @@ -567,4 +600,29 @@ func RunAllTaints_Bytes() { out := TaintStepTest_BytesReaderWriteTo_B0I0O0(source) sink(49, out) } + { + source := newSource(50) + out := TaintStepTest_Cutleft(source) + sink(50, out) + } + { + source := newSource(51) + out := TaintStepTest_Cutright(source) + sink(51, out) + } + { + source := newSource(52) + out := TaintStepTest_CutPrefix(source) + sink(52, out) + } + { + source := newSource(53) + out := TaintStepTest_CutSuffix(source) + sink(53, out) + } + { + source := newSource(54) + out := TaintStepTest_Clone(source) + sink(54, out) + } } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Errors.go b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Errors.go index 84ea857e58b..324f1e36ae7 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Errors.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Errors.go @@ -23,6 +23,18 @@ func TaintStepTest_ErrorsUnwrap_B0I0O0(sourceCQL interface{}) interface{} { return intoError957 } +func TaintStepTest_ErrorsJoin1(sourceCQL interface{}) interface{} { + fromError784 := sourceCQL.(error) + intoError957 := errors.Join(fromError784, errors.New("")) + return intoError957 +} + +func TaintStepTest_ErrorsJoin2(sourceCQL interface{}) interface{} { + fromError784 := sourceCQL.(error) + intoError957 := errors.Join(errors.New(""), fromError784) + return intoError957 +} + func RunAllTaints_Errors() { { source := newSource(0) @@ -39,4 +51,14 @@ func RunAllTaints_Errors() { out := TaintStepTest_ErrorsUnwrap_B0I0O0(source) sink(2, out) } + { + source := newSource(3) + out := TaintStepTest_ErrorsJoin1(source) + sink(3, out) + } + { + source := newSource(4) + out := TaintStepTest_ErrorsJoin2(source) + sink(4, out) + } } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Sync.go b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Sync.go index 3bc8c2d3dfe..25a0f7d96d0 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Sync.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Sync.go @@ -58,6 +58,30 @@ func TaintStepTest_SyncMapStore_B0I1O0(sourceCQL interface{}) interface{} { return intoMap881 } +func TaintStepTest_SyncMapSwapinkey(sourceCQL interface{}) interface{} { + var m sync.Map + m.Swap(sourceCQL, "value") + return m +} + +func TaintStepTest_SyncMapSwapinvalue(sourceCQL interface{}) interface{} { + var m sync.Map + m.Swap("key", sourceCQL) + return m +} + +func TaintStepTest_SyncMapSwapout(sourceCQL interface{}) interface{} { + m := sourceCQL.(sync.Map) + oldVal, _ := m.Swap("key", "value") + return oldVal +} + +func TaintStepTest_SyncMapCompareAndSwap(sourceCQL interface{}) interface{} { + var m sync.Map + m.CompareAndSwap("key", "compareTo", sourceCQL) + return m +} + func TaintStepTest_SyncPoolGet_B0I0O0(sourceCQL interface{}) interface{} { fromPool186 := sourceCQL.(sync.Pool) intoInterface284 := fromPool186.Get() @@ -122,4 +146,24 @@ func RunAllTaints_Sync() { out := TaintStepTest_SyncPoolPut_B0I0O0(source) sink(9, out) } + { + source := newSource(10) + out := TaintStepTest_SyncMapSwapinkey(source) + sink(10, out) + } + { + source := newSource(11) + out := TaintStepTest_SyncMapSwapinvalue(source) + sink(11, out) + } + { + source := newSource(12) + out := TaintStepTest_SyncMapSwapout(source) + sink(12, out) + } + { + source := newSource(13) + out := TaintStepTest_SyncMapCompareAndSwap(source) + sink(13, out) + } } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Unsafe.go b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Unsafe.go new file mode 100644 index 00000000000..50f7e2281fa --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Unsafe.go @@ -0,0 +1,46 @@ +package main + +import "unsafe" + +func TaintStepTest_UnsafeSlice(sourceCQL interface{}) interface{} { + s := sourceCQL.(*byte) + return unsafe.Slice(s, 1) +} + +func TaintStepTest_UnsafeSliceData(sourceCQL interface{}) interface{} { + s := sourceCQL.([]byte) + return unsafe.SliceData(s) +} + +func TaintStepTest_UnsafeString(sourceCQL interface{}) interface{} { + s := sourceCQL.(*byte) + return unsafe.String(s, 1) +} + +func TaintStepTest_UnsafeStringData(sourceCQL interface{}) interface{} { + s := sourceCQL.(string) + return unsafe.StringData(s) +} + +func RunAllTaints_Unsafe() { + { + source := newSource(0) + out := TaintStepTest_UnsafeSlice(source) + sink(0, out) + } + { + source := newSource(1) + out := TaintStepTest_UnsafeSliceData(source) + sink(1, out) + } + { + source := newSource(2) + out := TaintStepTest_UnsafeString(source) + sink(2, out) + } + { + source := newSource(3) + out := TaintStepTest_UnsafeStringData(source) + sink(3, out) + } +} diff --git a/go/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected b/go/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected index 7c7600b70da..a608f356a30 100644 --- a/go/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected +++ b/go/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected @@ -5,5 +5,5 @@ | bad.go:3:5:3:5 | expected 'IDENT', found newline | | bad.go:5:1:5:1 | expected ';', found wnvwun | | badimport.go:6:2:6:2 | invalid import path (invalid character U+007B '{') | -| badimport.go:6:2:6:2 | invalid import path: "github.com/pkg{}" | +| badimport.go:6:2:6:2 | malformed import path "github.com/pkg{}": invalid char '{' | | type.go:11:9:11:9 | cannot use v (variable of type V) as T value in argument to takesT | diff --git a/go/ql/test/query-tests/Diagnostics/ExtractionErrors.expected b/go/ql/test/query-tests/Diagnostics/ExtractionErrors.expected index 50b08606056..52fc92b4973 100644 --- a/go/ql/test/query-tests/Diagnostics/ExtractionErrors.expected +++ b/go/ql/test/query-tests/Diagnostics/ExtractionErrors.expected @@ -1,5 +1,5 @@ | Extraction failed in query-tests/Diagnostics/badimport.go with error invalid import path (invalid character U+007B '{') | 2 | -| Extraction failed in query-tests/Diagnostics/badimport.go with error invalid import path: "github.com/pkg{}" | 2 | +| Extraction failed in query-tests/Diagnostics/badimport.go with error malformed import path "github.com/pkg{}": invalid char '{' | 2 | | Extraction failed in query-tests/Diagnostics/type.go with error cannot use v (variable of type V) as T value in argument to takesT | 2 | | Extraction failed with error expected ';', found wnvwun | 2 | | Extraction failed with error expected 'IDENT', found newline | 2 | diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/CONSISTENCY/UnexpectedFrontendErrors.expected b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/CONSISTENCY/UnexpectedFrontendErrors.expected index 13fa384da0e..a7a03f17abc 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/CONSISTENCY/UnexpectedFrontendErrors.expected +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/CONSISTENCY/UnexpectedFrontendErrors.expected @@ -1 +1 @@ -| main.go:36:9:36:9 | undeclared name: unknownFunction | +| main.go:36:9:36:9 | undefined: unknownFunction | diff --git a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/CONSISTENCY/UnexpectedFrontendErrors.expected b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/CONSISTENCY/UnexpectedFrontendErrors.expected index f0a094c5bab..7c35a931673 100644 --- a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/CONSISTENCY/UnexpectedFrontendErrors.expected +++ b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/CONSISTENCY/UnexpectedFrontendErrors.expected @@ -1 +1 @@ -| err.go:6:7:6:7 | undeclared name: unknownFunction | +| err.go:6:7:6:7 | undefined: unknownFunction | diff --git a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.go b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.go index 92782b7ad67..d10d1e47a3b 100644 --- a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.go +++ b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.go @@ -264,6 +264,9 @@ func testBoundsChecking(input string) { _ = int16(parsed) } } + if parsed <= math.MaxUint16 { + _ = uint16(parsed) + } } { parsed, err := strconv.ParseUint(input, 10, 32) diff --git a/go/vendor/golang.org/x/mod/modfile/read.go b/go/vendor/golang.org/x/mod/modfile/read.go index 70947ee7794..a503bc2105d 100644 --- a/go/vendor/golang.org/x/mod/modfile/read.go +++ b/go/vendor/golang.org/x/mod/modfile/read.go @@ -494,7 +494,7 @@ func (in *input) endToken(kind tokenKind) { in.token.endPos = in.pos } -// peek returns the kind of the the next token returned by lex. +// peek returns the kind of the next token returned by lex. func (in *input) peek() tokenKind { return in.token.kind } diff --git a/go/vendor/golang.org/x/mod/modfile/rule.go b/go/vendor/golang.org/x/mod/modfile/rule.go index ed2f31aa70e..6bcde8fabe3 100644 --- a/go/vendor/golang.org/x/mod/modfile/rule.go +++ b/go/vendor/golang.org/x/mod/modfile/rule.go @@ -513,6 +513,9 @@ func parseReplace(filename string, line *Line, verb string, args []string, fix V nv := "" if len(args) == arrow+2 { if !IsDirectoryPath(ns) { + if strings.Contains(ns, "@") { + return nil, errorf("replacement module must match format 'path version', not 'path@version'") + } return nil, errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") } if filepath.Separator == '/' && strings.Contains(ns, `\`) { diff --git a/go/vendor/golang.org/x/mod/module/module.go b/go/vendor/golang.org/x/mod/module/module.go index c26d1d29ec3..e9dec6e6148 100644 --- a/go/vendor/golang.org/x/mod/module/module.go +++ b/go/vendor/golang.org/x/mod/module/module.go @@ -96,13 +96,13 @@ package module // Changes to the semantics in this file require approval from rsc. import ( + "errors" "fmt" "path" "sort" "strings" "unicode" "unicode/utf8" - "errors" "golang.org/x/mod/semver" ) @@ -258,7 +258,7 @@ func modPathOK(r rune) bool { return false } -// modPathOK reports whether r can appear in a package import path element. +// importPathOK reports whether r can appear in a package import path element. // // Import paths are intermediate between module paths and file paths: we allow // disallow characters that would be confusing or ambiguous as arguments to diff --git a/go/vendor/golang.org/x/sys/execabs/execabs_go119.go b/go/vendor/golang.org/x/sys/execabs/execabs_go119.go index 1e7a9ada0b0..46c5b525e7b 100644 --- a/go/vendor/golang.org/x/sys/execabs/execabs_go119.go +++ b/go/vendor/golang.org/x/sys/execabs/execabs_go119.go @@ -7,9 +7,11 @@ package execabs -import "strings" +import ( + "errors" + "os/exec" +) func isGo119ErrDot(err error) bool { - // TODO: return errors.Is(err, exec.ErrDot) - return strings.Contains(err.Error(), "current directory") + return errors.Is(err, exec.ErrDot) } diff --git a/go/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/go/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go index 2ed25a75024..165ede0f8f3 100644 --- a/go/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ b/go/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -27,10 +27,9 @@ import ( "go/token" "go/types" "io" - "io/ioutil" "os/exec" - "golang.org/x/tools/go/internal/gcimporter" + "golang.org/x/tools/internal/gcimporter" ) // Find returns the name of an object (.o) or archive (.a) file @@ -85,9 +84,26 @@ func NewReader(r io.Reader) (io.Reader, error) { } } +// readAll works the same way as io.ReadAll, but avoids allocations and copies +// by preallocating a byte slice of the necessary size if the size is known up +// front. This is always possible when the input is an archive. In that case, +// NewReader will return the known size using an io.LimitedReader. +func readAll(r io.Reader) ([]byte, error) { + if lr, ok := r.(*io.LimitedReader); ok { + data := make([]byte, lr.N) + _, err := io.ReadFull(lr, data) + return data, err + } + return io.ReadAll(r) +} + // Read reads export data from in, decodes it, and returns type // information for the package. -// The package name is specified by path. +// +// The package path (effectively its linker symbol prefix) is +// specified by path, since unlike the package name, this information +// may not be recorded in the export data. +// // File position information is added to fset. // // Read may inspect and add to the imports map to ensure that references @@ -98,7 +114,7 @@ func NewReader(r io.Reader) (io.Reader, error) { // // On return, the state of the reader is undefined. func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) { - data, err := ioutil.ReadAll(in) + data, err := readAll(in) if err != nil { return nil, fmt.Errorf("reading export data for %q: %v", path, err) } @@ -107,12 +123,6 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, return nil, fmt.Errorf("can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)", path) } - // The App Engine Go runtime v1.6 uses the old export data format. - // TODO(adonovan): delete once v1.7 has been around for a while. - if bytes.HasPrefix(data, []byte("package ")) { - return gcimporter.ImportData(imports, path, path, bytes.NewReader(data)) - } - // The indexed export format starts with an 'i'; the older // binary export format starts with a 'c', 'd', or 'v' // (from "version"). Select appropriate importer. @@ -161,7 +171,7 @@ func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error { // // Experimental: This API is experimental and may change in the future. func ReadBundle(in io.Reader, fset *token.FileSet, imports map[string]*types.Package) ([]*types.Package, error) { - data, err := ioutil.ReadAll(in) + data, err := readAll(in) if err != nil { return nil, fmt.Errorf("reading export bundle: %v", err) } diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go b/go/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go deleted file mode 100644 index e96c39600d1..00000000000 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go +++ /dev/null @@ -1,1125 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file is a modified copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go, -// but it also contains the original source-based importer code for Go1.6. -// Once we stop supporting 1.6, we can remove that code. - -// Package gcimporter provides various functions for reading -// gc-generated object files that can be used to implement the -// Importer interface defined by the Go 1.5 standard library package. -package gcimporter // import "golang.org/x/tools/go/internal/gcimporter" - -import ( - "bufio" - "errors" - "fmt" - "go/build" - "go/constant" - "go/token" - "go/types" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - "text/scanner" -) - -const ( - // Enable debug during development: it adds some additional checks, and - // prevents errors from being recovered. - debug = false - - // If trace is set, debugging output is printed to std out. - trace = false -) - -var pkgExts = [...]string{".a", ".o"} - -// FindPkg returns the filename and unique package id for an import -// path based on package information provided by build.Import (using -// the build.Default build.Context). A relative srcDir is interpreted -// relative to the current working directory. -// If no file was found, an empty filename is returned. -func FindPkg(path, srcDir string) (filename, id string) { - if path == "" { - return - } - - var noext string - switch { - default: - // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" - // Don't require the source files to be present. - if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 - srcDir = abs - } - bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) - if bp.PkgObj == "" { - id = path // make sure we have an id to print in error message - return - } - noext = strings.TrimSuffix(bp.PkgObj, ".a") - id = bp.ImportPath - - case build.IsLocalImport(path): - // "./x" -> "/this/directory/x.ext", "/this/directory/x" - noext = filepath.Join(srcDir, path) - id = noext - - case filepath.IsAbs(path): - // for completeness only - go/build.Import - // does not support absolute imports - // "/x" -> "/x.ext", "/x" - noext = path - id = path - } - - if false { // for debugging - if path != id { - fmt.Printf("%s -> %s\n", path, id) - } - } - - // try extensions - for _, ext := range pkgExts { - filename = noext + ext - if f, err := os.Stat(filename); err == nil && !f.IsDir() { - return - } - } - - filename = "" // not found - return -} - -// ImportData imports a package by reading the gc-generated export data, -// adds the corresponding package object to the packages map indexed by id, -// and returns the object. -// -// The packages map must contains all packages already imported. The data -// reader position must be the beginning of the export data section. The -// filename is only used in error messages. -// -// If packages[id] contains the completely imported package, that package -// can be used directly, and there is no need to call this function (but -// there is also no harm but for extra time used). -func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) { - // support for parser error handling - defer func() { - switch r := recover().(type) { - case nil: - // nothing to do - case importError: - err = r - default: - panic(r) // internal error - } - }() - - var p parser - p.init(filename, id, data, packages) - pkg = p.parseExport() - - return -} - -// Import imports a gc-generated package given its import path and srcDir, adds -// the corresponding package object to the packages map, and returns the object. -// The packages map must contain all packages already imported. -func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { - var rc io.ReadCloser - var filename, id string - if lookup != nil { - // With custom lookup specified, assume that caller has - // converted path to a canonical import path for use in the map. - if path == "unsafe" { - return types.Unsafe, nil - } - id = path - - // No need to re-import if the package was imported completely before. - if pkg = packages[id]; pkg != nil && pkg.Complete() { - return - } - f, err := lookup(path) - if err != nil { - return nil, err - } - rc = f - } else { - filename, id = FindPkg(path, srcDir) - if filename == "" { - if path == "unsafe" { - return types.Unsafe, nil - } - return nil, fmt.Errorf("can't find import: %q", id) - } - - // no need to re-import if the package was imported completely before - if pkg = packages[id]; pkg != nil && pkg.Complete() { - return - } - - // open file - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - // add file name to error - err = fmt.Errorf("%s: %v", filename, err) - } - }() - rc = f - } - defer rc.Close() - - var hdr string - var size int64 - buf := bufio.NewReader(rc) - if hdr, size, err = FindExportData(buf); err != nil { - return - } - - switch hdr { - case "$$\n": - // Work-around if we don't have a filename; happens only if lookup != nil. - // Either way, the filename is only needed for importer error messages, so - // this is fine. - if filename == "" { - filename = path - } - return ImportData(packages, filename, id, buf) - - case "$$B\n": - var data []byte - data, err = ioutil.ReadAll(buf) - if err != nil { - break - } - - // TODO(gri): allow clients of go/importer to provide a FileSet. - // Or, define a new standard go/types/gcexportdata package. - fset := token.NewFileSet() - - // The indexed export format starts with an 'i'; the older - // binary export format starts with a 'c', 'd', or 'v' - // (from "version"). Select appropriate importer. - if len(data) > 0 { - switch data[0] { - case 'i': - _, pkg, err := IImportData(fset, packages, data[1:], id) - return pkg, err - - case 'v', 'c', 'd': - _, pkg, err := BImportData(fset, packages, data, id) - return pkg, err - - case 'u': - _, pkg, err := UImportData(fset, packages, data[1:size], id) - return pkg, err - - default: - l := len(data) - if l > 10 { - l = 10 - } - return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id) - } - } - - default: - err = fmt.Errorf("unknown export data header: %q", hdr) - } - - return -} - -// ---------------------------------------------------------------------------- -// Parser - -// TODO(gri) Imported objects don't have position information. -// Ideally use the debug table line info; alternatively -// create some fake position (or the position of the -// import). That way error messages referring to imported -// objects can print meaningful information. - -// parser parses the exports inside a gc compiler-produced -// object/archive file and populates its scope with the results. -type parser struct { - scanner scanner.Scanner - tok rune // current token - lit string // literal string; only valid for Ident, Int, String tokens - id string // package id of imported package - sharedPkgs map[string]*types.Package // package id -> package object (across importer) - localPkgs map[string]*types.Package // package id -> package object (just this package) -} - -func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) { - p.scanner.Init(src) - p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } - p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments - p.scanner.Whitespace = 1<<'\t' | 1<<' ' - p.scanner.Filename = filename // for good error messages - p.next() - p.id = id - p.sharedPkgs = packages - if debug { - // check consistency of packages map - for _, pkg := range packages { - if pkg.Name() == "" { - fmt.Printf("no package name for %s\n", pkg.Path()) - } - } - } -} - -func (p *parser) next() { - p.tok = p.scanner.Scan() - switch p.tok { - case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·': - p.lit = p.scanner.TokenText() - default: - p.lit = "" - } - if debug { - fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit) - } -} - -func declTypeName(pkg *types.Package, name string) *types.TypeName { - scope := pkg.Scope() - if obj := scope.Lookup(name); obj != nil { - return obj.(*types.TypeName) - } - obj := types.NewTypeName(token.NoPos, pkg, name, nil) - // a named type may be referred to before the underlying type - // is known - set it up - types.NewNamed(obj, nil, nil) - scope.Insert(obj) - return obj -} - -// ---------------------------------------------------------------------------- -// Error handling - -// Internal errors are boxed as importErrors. -type importError struct { - pos scanner.Position - err error -} - -func (e importError) Error() string { - return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) -} - -func (p *parser) error(err interface{}) { - if s, ok := err.(string); ok { - err = errors.New(s) - } - // panic with a runtime.Error if err is not an error - panic(importError{p.scanner.Pos(), err.(error)}) -} - -func (p *parser) errorf(format string, args ...interface{}) { - p.error(fmt.Sprintf(format, args...)) -} - -func (p *parser) expect(tok rune) string { - lit := p.lit - if p.tok != tok { - p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) - } - p.next() - return lit -} - -func (p *parser) expectSpecial(tok string) { - sep := 'x' // not white space - i := 0 - for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' { - sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token - p.next() - i++ - } - if i < len(tok) { - p.errorf("expected %q, got %q", tok, tok[0:i]) - } -} - -func (p *parser) expectKeyword(keyword string) { - lit := p.expect(scanner.Ident) - if lit != keyword { - p.errorf("expected keyword %s, got %q", keyword, lit) - } -} - -// ---------------------------------------------------------------------------- -// Qualified and unqualified names - -// parsePackageID parses a PackageId: -// -// PackageId = string_lit . -func (p *parser) parsePackageID() string { - id, err := strconv.Unquote(p.expect(scanner.String)) - if err != nil { - p.error(err) - } - // id == "" stands for the imported package id - // (only known at time of package installation) - if id == "" { - id = p.id - } - return id -} - -// parsePackageName parse a PackageName: -// -// PackageName = ident . -func (p *parser) parsePackageName() string { - return p.expect(scanner.Ident) -} - -// parseDotIdent parses a dotIdentifier: -// -// dotIdentifier = ( ident | '·' ) { ident | int | '·' } . -func (p *parser) parseDotIdent() string { - ident := "" - if p.tok != scanner.Int { - sep := 'x' // not white space - for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { - ident += p.lit - sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token - p.next() - } - } - if ident == "" { - p.expect(scanner.Ident) // use expect() for error handling - } - return ident -} - -// parseQualifiedName parses a QualifiedName: -// -// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) . -func (p *parser) parseQualifiedName() (id, name string) { - p.expect('@') - id = p.parsePackageID() - p.expect('.') - // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields. - if p.tok == '?' { - p.next() - } else { - name = p.parseDotIdent() - } - return -} - -// getPkg returns the package for a given id. If the package is -// not found, create the package and add it to the p.localPkgs -// and p.sharedPkgs maps. name is the (expected) name of the -// package. If name == "", the package name is expected to be -// set later via an import clause in the export data. -// -// id identifies a package, usually by a canonical package path like -// "encoding/json" but possibly by a non-canonical import path like -// "./json". -func (p *parser) getPkg(id, name string) *types.Package { - // package unsafe is not in the packages maps - handle explicitly - if id == "unsafe" { - return types.Unsafe - } - - pkg := p.localPkgs[id] - if pkg == nil { - // first import of id from this package - pkg = p.sharedPkgs[id] - if pkg == nil { - // first import of id by this importer; - // add (possibly unnamed) pkg to shared packages - pkg = types.NewPackage(id, name) - p.sharedPkgs[id] = pkg - } - // add (possibly unnamed) pkg to local packages - if p.localPkgs == nil { - p.localPkgs = make(map[string]*types.Package) - } - p.localPkgs[id] = pkg - } else if name != "" { - // package exists already and we have an expected package name; - // make sure names match or set package name if necessary - if pname := pkg.Name(); pname == "" { - pkg.SetName(name) - } else if pname != name { - p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name) - } - } - return pkg -} - -// parseExportedName is like parseQualifiedName, but -// the package id is resolved to an imported *types.Package. -func (p *parser) parseExportedName() (pkg *types.Package, name string) { - id, name := p.parseQualifiedName() - pkg = p.getPkg(id, "") - return -} - -// ---------------------------------------------------------------------------- -// Types - -// parseBasicType parses a BasicType: -// -// BasicType = identifier . -func (p *parser) parseBasicType() types.Type { - id := p.expect(scanner.Ident) - obj := types.Universe.Lookup(id) - if obj, ok := obj.(*types.TypeName); ok { - return obj.Type() - } - p.errorf("not a basic type: %s", id) - return nil -} - -// parseArrayType parses an ArrayType: -// -// ArrayType = "[" int_lit "]" Type . -func (p *parser) parseArrayType(parent *types.Package) types.Type { - // "[" already consumed and lookahead known not to be "]" - lit := p.expect(scanner.Int) - p.expect(']') - elem := p.parseType(parent) - n, err := strconv.ParseInt(lit, 10, 64) - if err != nil { - p.error(err) - } - return types.NewArray(elem, n) -} - -// parseMapType parses a MapType: -// -// MapType = "map" "[" Type "]" Type . -func (p *parser) parseMapType(parent *types.Package) types.Type { - p.expectKeyword("map") - p.expect('[') - key := p.parseType(parent) - p.expect(']') - elem := p.parseType(parent) - return types.NewMap(key, elem) -} - -// parseName parses a Name: -// -// Name = identifier | "?" | QualifiedName . -// -// For unqualified and anonymous names, the returned package is the parent -// package unless parent == nil, in which case the returned package is the -// package being imported. (The parent package is not nil if the name -// is an unqualified struct field or interface method name belonging to a -// type declared in another package.) -// -// For qualified names, the returned package is nil (and not created if -// it doesn't exist yet) unless materializePkg is set (which creates an -// unnamed package with valid package path). In the latter case, a -// subsequent import clause is expected to provide a name for the package. -func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) { - pkg = parent - if pkg == nil { - pkg = p.sharedPkgs[p.id] - } - switch p.tok { - case scanner.Ident: - name = p.lit - p.next() - case '?': - // anonymous - p.next() - case '@': - // exported name prefixed with package path - pkg = nil - var id string - id, name = p.parseQualifiedName() - if materializePkg { - pkg = p.getPkg(id, "") - } - default: - p.error("name expected") - } - return -} - -func deref(typ types.Type) types.Type { - if p, _ := typ.(*types.Pointer); p != nil { - return p.Elem() - } - return typ -} - -// parseField parses a Field: -// -// Field = Name Type [ string_lit ] . -func (p *parser) parseField(parent *types.Package) (*types.Var, string) { - pkg, name := p.parseName(parent, true) - - if name == "_" { - // Blank fields should be package-qualified because they - // are unexported identifiers, but gc does not qualify them. - // Assuming that the ident belongs to the current package - // causes types to change during re-exporting, leading - // to spurious "can't assign A to B" errors from go/types. - // As a workaround, pretend all blank fields belong - // to the same unique dummy package. - const blankpkg = "<_>" - pkg = p.getPkg(blankpkg, blankpkg) - } - - typ := p.parseType(parent) - anonymous := false - if name == "" { - // anonymous field - typ must be T or *T and T must be a type name - switch typ := deref(typ).(type) { - case *types.Basic: // basic types are named types - pkg = nil // objects defined in Universe scope have no package - name = typ.Name() - case *types.Named: - name = typ.Obj().Name() - default: - p.errorf("anonymous field expected") - } - anonymous = true - } - tag := "" - if p.tok == scanner.String { - s := p.expect(scanner.String) - var err error - tag, err = strconv.Unquote(s) - if err != nil { - p.errorf("invalid struct tag %s: %s", s, err) - } - } - return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag -} - -// parseStructType parses a StructType: -// -// StructType = "struct" "{" [ FieldList ] "}" . -// FieldList = Field { ";" Field } . -func (p *parser) parseStructType(parent *types.Package) types.Type { - var fields []*types.Var - var tags []string - - p.expectKeyword("struct") - p.expect('{') - for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { - if i > 0 { - p.expect(';') - } - fld, tag := p.parseField(parent) - if tag != "" && tags == nil { - tags = make([]string, i) - } - if tags != nil { - tags = append(tags, tag) - } - fields = append(fields, fld) - } - p.expect('}') - - return types.NewStruct(fields, tags) -} - -// parseParameter parses a Parameter: -// -// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . -func (p *parser) parseParameter() (par *types.Var, isVariadic bool) { - _, name := p.parseName(nil, false) - // remove gc-specific parameter numbering - if i := strings.Index(name, "·"); i >= 0 { - name = name[:i] - } - if p.tok == '.' { - p.expectSpecial("...") - isVariadic = true - } - typ := p.parseType(nil) - if isVariadic { - typ = types.NewSlice(typ) - } - // ignore argument tag (e.g. "noescape") - if p.tok == scanner.String { - p.next() - } - // TODO(gri) should we provide a package? - par = types.NewVar(token.NoPos, nil, name, typ) - return -} - -// parseParameters parses a Parameters: -// -// Parameters = "(" [ ParameterList ] ")" . -// ParameterList = { Parameter "," } Parameter . -func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) { - p.expect('(') - for p.tok != ')' && p.tok != scanner.EOF { - if len(list) > 0 { - p.expect(',') - } - par, variadic := p.parseParameter() - list = append(list, par) - if variadic { - if isVariadic { - p.error("... not on final argument") - } - isVariadic = true - } - } - p.expect(')') - - return -} - -// parseSignature parses a Signature: -// -// Signature = Parameters [ Result ] . -// Result = Type | Parameters . -func (p *parser) parseSignature(recv *types.Var) *types.Signature { - params, isVariadic := p.parseParameters() - - // optional result type - var results []*types.Var - if p.tok == '(' { - var variadic bool - results, variadic = p.parseParameters() - if variadic { - p.error("... not permitted on result type") - } - } - - return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic) -} - -// parseInterfaceType parses an InterfaceType: -// -// InterfaceType = "interface" "{" [ MethodList ] "}" . -// MethodList = Method { ";" Method } . -// Method = Name Signature . -// -// The methods of embedded interfaces are always "inlined" -// by the compiler and thus embedded interfaces are never -// visible in the export data. -func (p *parser) parseInterfaceType(parent *types.Package) types.Type { - var methods []*types.Func - - p.expectKeyword("interface") - p.expect('{') - for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { - if i > 0 { - p.expect(';') - } - pkg, name := p.parseName(parent, true) - sig := p.parseSignature(nil) - methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig)) - } - p.expect('}') - - // Complete requires the type's embedded interfaces to be fully defined, - // but we do not define any - return newInterface(methods, nil).Complete() -} - -// parseChanType parses a ChanType: -// -// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type . -func (p *parser) parseChanType(parent *types.Package) types.Type { - dir := types.SendRecv - if p.tok == scanner.Ident { - p.expectKeyword("chan") - if p.tok == '<' { - p.expectSpecial("<-") - dir = types.SendOnly - } - } else { - p.expectSpecial("<-") - p.expectKeyword("chan") - dir = types.RecvOnly - } - elem := p.parseType(parent) - return types.NewChan(dir, elem) -} - -// parseType parses a Type: -// -// Type = -// BasicType | TypeName | ArrayType | SliceType | StructType | -// PointerType | FuncType | InterfaceType | MapType | ChanType | -// "(" Type ")" . -// -// BasicType = ident . -// TypeName = ExportedName . -// SliceType = "[" "]" Type . -// PointerType = "*" Type . -// FuncType = "func" Signature . -func (p *parser) parseType(parent *types.Package) types.Type { - switch p.tok { - case scanner.Ident: - switch p.lit { - default: - return p.parseBasicType() - case "struct": - return p.parseStructType(parent) - case "func": - // FuncType - p.next() - return p.parseSignature(nil) - case "interface": - return p.parseInterfaceType(parent) - case "map": - return p.parseMapType(parent) - case "chan": - return p.parseChanType(parent) - } - case '@': - // TypeName - pkg, name := p.parseExportedName() - return declTypeName(pkg, name).Type() - case '[': - p.next() // look ahead - if p.tok == ']' { - // SliceType - p.next() - return types.NewSlice(p.parseType(parent)) - } - return p.parseArrayType(parent) - case '*': - // PointerType - p.next() - return types.NewPointer(p.parseType(parent)) - case '<': - return p.parseChanType(parent) - case '(': - // "(" Type ")" - p.next() - typ := p.parseType(parent) - p.expect(')') - return typ - } - p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) - return nil -} - -// ---------------------------------------------------------------------------- -// Declarations - -// parseImportDecl parses an ImportDecl: -// -// ImportDecl = "import" PackageName PackageId . -func (p *parser) parseImportDecl() { - p.expectKeyword("import") - name := p.parsePackageName() - p.getPkg(p.parsePackageID(), name) -} - -// parseInt parses an int_lit: -// -// int_lit = [ "+" | "-" ] { "0" ... "9" } . -func (p *parser) parseInt() string { - s := "" - switch p.tok { - case '-': - s = "-" - p.next() - case '+': - p.next() - } - return s + p.expect(scanner.Int) -} - -// parseNumber parses a number: -// -// number = int_lit [ "p" int_lit ] . -func (p *parser) parseNumber() (typ *types.Basic, val constant.Value) { - // mantissa - mant := constant.MakeFromLiteral(p.parseInt(), token.INT, 0) - if mant == nil { - panic("invalid mantissa") - } - - if p.lit == "p" { - // exponent (base 2) - p.next() - exp, err := strconv.ParseInt(p.parseInt(), 10, 0) - if err != nil { - p.error(err) - } - if exp < 0 { - denom := constant.MakeInt64(1) - denom = constant.Shift(denom, token.SHL, uint(-exp)) - typ = types.Typ[types.UntypedFloat] - val = constant.BinaryOp(mant, token.QUO, denom) - return - } - if exp > 0 { - mant = constant.Shift(mant, token.SHL, uint(exp)) - } - typ = types.Typ[types.UntypedFloat] - val = mant - return - } - - typ = types.Typ[types.UntypedInt] - val = mant - return -} - -// parseConstDecl parses a ConstDecl: -// -// ConstDecl = "const" ExportedName [ Type ] "=" Literal . -// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit . -// bool_lit = "true" | "false" . -// complex_lit = "(" float_lit "+" float_lit "i" ")" . -// rune_lit = "(" int_lit "+" int_lit ")" . -// string_lit = `"` { unicode_char } `"` . -func (p *parser) parseConstDecl() { - p.expectKeyword("const") - pkg, name := p.parseExportedName() - - var typ0 types.Type - if p.tok != '=' { - // constant types are never structured - no need for parent type - typ0 = p.parseType(nil) - } - - p.expect('=') - var typ types.Type - var val constant.Value - switch p.tok { - case scanner.Ident: - // bool_lit - if p.lit != "true" && p.lit != "false" { - p.error("expected true or false") - } - typ = types.Typ[types.UntypedBool] - val = constant.MakeBool(p.lit == "true") - p.next() - - case '-', scanner.Int: - // int_lit - typ, val = p.parseNumber() - - case '(': - // complex_lit or rune_lit - p.next() - if p.tok == scanner.Char { - p.next() - p.expect('+') - typ = types.Typ[types.UntypedRune] - _, val = p.parseNumber() - p.expect(')') - break - } - _, re := p.parseNumber() - p.expect('+') - _, im := p.parseNumber() - p.expectKeyword("i") - p.expect(')') - typ = types.Typ[types.UntypedComplex] - val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - - case scanner.Char: - // rune_lit - typ = types.Typ[types.UntypedRune] - val = constant.MakeFromLiteral(p.lit, token.CHAR, 0) - p.next() - - case scanner.String: - // string_lit - typ = types.Typ[types.UntypedString] - val = constant.MakeFromLiteral(p.lit, token.STRING, 0) - p.next() - - default: - p.errorf("expected literal got %s", scanner.TokenString(p.tok)) - } - - if typ0 == nil { - typ0 = typ - } - - pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val)) -} - -// parseTypeDecl parses a TypeDecl: -// -// TypeDecl = "type" ExportedName Type . -func (p *parser) parseTypeDecl() { - p.expectKeyword("type") - pkg, name := p.parseExportedName() - obj := declTypeName(pkg, name) - - // The type object may have been imported before and thus already - // have a type associated with it. We still need to parse the type - // structure, but throw it away if the object already has a type. - // This ensures that all imports refer to the same type object for - // a given type declaration. - typ := p.parseType(pkg) - - if name := obj.Type().(*types.Named); name.Underlying() == nil { - name.SetUnderlying(typ) - } -} - -// parseVarDecl parses a VarDecl: -// -// VarDecl = "var" ExportedName Type . -func (p *parser) parseVarDecl() { - p.expectKeyword("var") - pkg, name := p.parseExportedName() - typ := p.parseType(pkg) - pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ)) -} - -// parseFunc parses a Func: -// -// Func = Signature [ Body ] . -// Body = "{" ... "}" . -func (p *parser) parseFunc(recv *types.Var) *types.Signature { - sig := p.parseSignature(recv) - if p.tok == '{' { - p.next() - for i := 1; i > 0; p.next() { - switch p.tok { - case '{': - i++ - case '}': - i-- - } - } - } - return sig -} - -// parseMethodDecl parses a MethodDecl: -// -// MethodDecl = "func" Receiver Name Func . -// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" . -func (p *parser) parseMethodDecl() { - // "func" already consumed - p.expect('(') - recv, _ := p.parseParameter() // receiver - p.expect(')') - - // determine receiver base type object - base := deref(recv.Type()).(*types.Named) - - // parse method name, signature, and possibly inlined body - _, name := p.parseName(nil, false) - sig := p.parseFunc(recv) - - // methods always belong to the same package as the base type object - pkg := base.Obj().Pkg() - - // add method to type unless type was imported before - // and method exists already - // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small. - base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) -} - -// parseFuncDecl parses a FuncDecl: -// -// FuncDecl = "func" ExportedName Func . -func (p *parser) parseFuncDecl() { - // "func" already consumed - pkg, name := p.parseExportedName() - typ := p.parseFunc(nil) - pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ)) -} - -// parseDecl parses a Decl: -// -// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . -func (p *parser) parseDecl() { - if p.tok == scanner.Ident { - switch p.lit { - case "import": - p.parseImportDecl() - case "const": - p.parseConstDecl() - case "type": - p.parseTypeDecl() - case "var": - p.parseVarDecl() - case "func": - p.next() // look ahead - if p.tok == '(' { - p.parseMethodDecl() - } else { - p.parseFuncDecl() - } - } - } - p.expect('\n') -} - -// ---------------------------------------------------------------------------- -// Export - -// parseExport parses an Export: -// -// Export = "PackageClause { Decl } "$$" . -// PackageClause = "package" PackageName [ "safe" ] "\n" . -func (p *parser) parseExport() *types.Package { - p.expectKeyword("package") - name := p.parsePackageName() - if p.tok == scanner.Ident && p.lit == "safe" { - // package was compiled with -u option - ignore - p.next() - } - p.expect('\n') - - pkg := p.getPkg(p.id, name) - - for p.tok != '$' && p.tok != scanner.EOF { - p.parseDecl() - } - - if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' { - // don't call next()/expect() since reading past the - // export data may cause scanner errors (e.g. NUL chars) - p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch) - } - - if n := p.scanner.ErrorCount; n != 0 { - p.errorf("expected no scanner errors, got %d", n) - } - - // Record all locally referenced packages as imports. - var imports []*types.Package - for id, pkg2 := range p.localPkgs { - if pkg2.Name() == "" { - p.errorf("%s package has no name", id) - } - if id == p.id { - continue // avoid self-edge - } - imports = append(imports, pkg2) - } - sort.Sort(byPath(imports)) - pkg.SetImports(imports) - - // package was imported completely and without errors - pkg.MarkComplete() - - return pkg -} - -type byPath []*types.Package - -func (a byPath) Len() int { return len(a) } -func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/go/vendor/golang.org/x/tools/go/packages/golist.go b/go/vendor/golang.org/x/tools/go/packages/golist.go index de881562de1..6bb7168d2e3 100644 --- a/go/vendor/golang.org/x/tools/go/packages/golist.go +++ b/go/vendor/golang.org/x/tools/go/packages/golist.go @@ -60,6 +60,7 @@ func (r *responseDeduper) addAll(dr *driverResponse) { for _, root := range dr.Roots { r.addRoot(root) } + r.dr.GoVersion = dr.GoVersion } func (r *responseDeduper) addPackage(p *Package) { @@ -454,11 +455,14 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse if err != nil { return nil, err } + seen := make(map[string]*jsonPackage) pkgs := make(map[string]*Package) additionalErrors := make(map[string][]Error) // Decode the JSON and convert it to Package form. - var response driverResponse + response := &driverResponse{ + GoVersion: goVersion, + } for dec := json.NewDecoder(buf); dec.More(); { p := new(jsonPackage) if err := dec.Decode(p); err != nil { @@ -600,17 +604,12 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse // Work around https://golang.org/issue/28749: // cmd/go puts assembly, C, and C++ files in CompiledGoFiles. - // Filter out any elements of CompiledGoFiles that are also in OtherFiles. - // We have to keep this workaround in place until go1.12 is a distant memory. - if len(pkg.OtherFiles) > 0 { - other := make(map[string]bool, len(pkg.OtherFiles)) - for _, f := range pkg.OtherFiles { - other[f] = true - } - + // Remove files from CompiledGoFiles that are non-go files + // (or are not files that look like they are from the cache). + if len(pkg.CompiledGoFiles) > 0 { out := pkg.CompiledGoFiles[:0] for _, f := range pkg.CompiledGoFiles { - if other[f] { + if ext := filepath.Ext(f); ext != ".go" && ext != "" { // ext == "" means the file is from the cache, so probably cgo-processed file continue } out = append(out, f) @@ -730,7 +729,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse } sort.Slice(response.Packages, func(i, j int) bool { return response.Packages[i].ID < response.Packages[j].ID }) - return &response, nil + return response, nil } func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { @@ -756,6 +755,7 @@ func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { return len(p.Error.ImportStack) == 0 || p.Error.ImportStack[len(p.Error.ImportStack)-1] == p.ImportPath } +// getGoVersion returns the effective minor version of the go command. func (state *golistState) getGoVersion() (int, error) { state.goVersionOnce.Do(func() { state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.cfg.gocmdRunner) diff --git a/go/vendor/golang.org/x/tools/go/packages/packages.go b/go/vendor/golang.org/x/tools/go/packages/packages.go index a93dc6add4d..0f1505b808a 100644 --- a/go/vendor/golang.org/x/tools/go/packages/packages.go +++ b/go/vendor/golang.org/x/tools/go/packages/packages.go @@ -15,10 +15,12 @@ import ( "go/scanner" "go/token" "go/types" + "io" "io/ioutil" "log" "os" "path/filepath" + "runtime" "strings" "sync" "time" @@ -233,6 +235,11 @@ type driverResponse struct { // Imports will be connected and then type and syntax information added in a // later pass (see refine). Packages []*Package + + // GoVersion is the minor version number used by the driver + // (e.g. the go command on the PATH) when selecting .go files. + // Zero means unknown. + GoVersion int } // Load loads and returns the Go packages named by the given patterns. @@ -256,7 +263,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) { return nil, err } l.sizes = response.Sizes - return l.refine(response.Roots, response.Packages...) + return l.refine(response) } // defaultDriver is a driver that implements go/packages' fallback behavior. @@ -297,6 +304,9 @@ type Package struct { // of the package, or while parsing or type-checking its files. Errors []Error + // TypeErrors contains the subset of errors produced during type checking. + TypeErrors []types.Error + // GoFiles lists the absolute file paths of the package's Go source files. GoFiles []string @@ -532,6 +542,7 @@ type loaderPackage struct { needsrc bool // load from source (Mode >= LoadTypes) needtypes bool // type information is either requested or depended on initial bool // package was matched by a pattern + goVersion int // minor version number of go command on PATH } // loader holds the working state of a single call to load. @@ -618,7 +629,8 @@ func newLoader(cfg *Config) *loader { // refine connects the supplied packages into a graph and then adds type and // and syntax information as requested by the LoadMode. -func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { +func (ld *loader) refine(response *driverResponse) ([]*Package, error) { + roots := response.Roots rootMap := make(map[string]int, len(roots)) for i, root := range roots { rootMap[root] = i @@ -626,7 +638,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { ld.pkgs = make(map[string]*loaderPackage) // first pass, fixup and build the map and roots var initial = make([]*loaderPackage, len(roots)) - for _, pkg := range list { + for _, pkg := range response.Packages { rootIndex := -1 if i, found := rootMap[pkg.ID]; found { rootIndex = i @@ -648,6 +660,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { Package: pkg, needtypes: needtypes, needsrc: needsrc, + goVersion: response.GoVersion, } ld.pkgs[lpkg.ID] = lpkg if rootIndex >= 0 { @@ -865,12 +878,19 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { // never has to create a types.Package for an indirect dependency, // which would then require that such created packages be explicitly // inserted back into the Import graph as a final step after export data loading. + // (Hence this return is after the Types assignment.) // The Diamond test exercises this case. if !lpkg.needtypes && !lpkg.needsrc { return } if !lpkg.needsrc { - ld.loadFromExportData(lpkg) + if err := ld.loadFromExportData(lpkg); err != nil { + lpkg.Errors = append(lpkg.Errors, Error{ + Pos: "-", + Msg: err.Error(), + Kind: UnknownError, // e.g. can't find/open/parse export data + }) + } return // not a source package, don't get syntax trees } @@ -902,6 +922,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { case types.Error: // from type checker + lpkg.TypeErrors = append(lpkg.TypeErrors, err) errs = append(errs, Error{ Pos: err.Fset.Position(err.Pos).String(), Msg: err.Msg, @@ -923,11 +944,41 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { lpkg.Errors = append(lpkg.Errors, errs...) } + // If the go command on the PATH is newer than the runtime, + // then the go/{scanner,ast,parser,types} packages from the + // standard library may be unable to process the files + // selected by go list. + // + // There is currently no way to downgrade the effective + // version of the go command (see issue 52078), so we proceed + // with the newer go command but, in case of parse or type + // errors, we emit an additional diagnostic. + // + // See: + // - golang.org/issue/52078 (flag to set release tags) + // - golang.org/issue/50825 (gopls legacy version support) + // - golang.org/issue/55883 (go/packages confusing error) + // + // Should we assert a hard minimum of (currently) go1.16 here? + var runtimeVersion int + if _, err := fmt.Sscanf(runtime.Version(), "go1.%d", &runtimeVersion); err == nil && runtimeVersion < lpkg.goVersion { + defer func() { + if len(lpkg.Errors) > 0 { + appendError(Error{ + Pos: "-", + Msg: fmt.Sprintf("This application uses version go1.%d of the source-processing packages but runs version go1.%d of 'go list'. It may fail to process source files that rely on newer language features. If so, rebuild the application using a newer version of Go.", runtimeVersion, lpkg.goVersion), + Kind: UnknownError, + }) + } + }() + } + if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" { // The config requested loading sources and types, but sources are missing. // Add an error to the package and fall back to loading from export data. appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError}) - ld.loadFromExportData(lpkg) + _ = ld.loadFromExportData(lpkg) // ignore any secondary errors + return // can't get syntax trees for this package } @@ -981,7 +1032,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { tc := &types.Config{ Importer: importer, - // Type-check bodies of functions only in non-initial packages. + // Type-check bodies of functions only in initial packages. // Example: for import graph A->B->C and initial packages {A,C}, // we can ignore function bodies in B. IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial, @@ -1151,9 +1202,10 @@ func sameFile(x, y string) bool { return false } -// loadFromExportData returns type information for the specified +// loadFromExportData ensures that type information is present for the specified // package, loading it from an export data file on the first request. -func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) { +// On success it sets lpkg.Types to a new Package. +func (ld *loader) loadFromExportData(lpkg *loaderPackage) error { if lpkg.PkgPath == "" { log.Fatalf("internal error: Package %s has no PkgPath", lpkg) } @@ -1164,8 +1216,8 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error // must be sequential. (Finer-grained locking would require // changes to the gcexportdata API.) // - // The exportMu lock guards the Package.Pkg field and the - // types.Package it points to, for each Package in the graph. + // The exportMu lock guards the lpkg.Types field and the + // types.Package it points to, for each loaderPackage in the graph. // // Not all accesses to Package.Pkg need to be protected by exportMu: // graph ordering ensures that direct dependencies of source @@ -1174,18 +1226,18 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error defer ld.exportMu.Unlock() if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() { - return tpkg, nil // cache hit + return nil // cache hit } lpkg.IllTyped = true // fail safe if lpkg.ExportFile == "" { // Errors while building export data will have been printed to stderr. - return nil, fmt.Errorf("no export data file") + return fmt.Errorf("no export data file") } f, err := os.Open(lpkg.ExportFile) if err != nil { - return nil, err + return err } defer f.Close() @@ -1197,7 +1249,7 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error // queries.) r, err := gcexportdata.NewReader(f) if err != nil { - return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) + return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) } // Build the view. @@ -1241,7 +1293,7 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error // (May modify incomplete packages in view but not create new ones.) tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath) if err != nil { - return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) + return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) } if _, ok := view["go.shape"]; ok { // Account for the pseudopackage "go.shape" that gets @@ -1254,8 +1306,7 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error lpkg.Types = tpkg lpkg.IllTyped = false - - return tpkg, nil + return nil } // impliedLoadMode returns loadMode with its dependencies. @@ -1271,3 +1322,5 @@ func impliedLoadMode(loadMode LoadMode) LoadMode { func usesExportData(cfg *Config) bool { return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0 } + +var _ interface{} = io.Discard // assert build toolchain is go1.16 or later diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go b/go/vendor/golang.org/x/tools/internal/gcimporter/bexport.go similarity index 99% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/bexport.go index 196cb3f9b41..30582ed6d3d 100644 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/bexport.go @@ -12,7 +12,6 @@ import ( "bytes" "encoding/binary" "fmt" - "go/ast" "go/constant" "go/token" "go/types" @@ -145,7 +144,7 @@ func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) objcount := 0 scope := pkg.Scope() for _, name := range scope.Names() { - if !ast.IsExported(name) { + if !token.IsExported(name) { continue } if trace { @@ -482,7 +481,7 @@ func (p *exporter) method(m *types.Func) { p.pos(m) p.string(m.Name()) - if m.Name() != "_" && !ast.IsExported(m.Name()) { + if m.Name() != "_" && !token.IsExported(m.Name()) { p.pkg(m.Pkg(), false) } @@ -501,7 +500,7 @@ func (p *exporter) fieldName(f *types.Var) { // 3) field name doesn't match base type name (alias name) bname := basetypeName(f.Type()) if name == bname { - if ast.IsExported(name) { + if token.IsExported(name) { name = "" // 1) we don't need to know the field name or package } else { name = "?" // 2) use unexported name "?" to force package export @@ -514,7 +513,7 @@ func (p *exporter) fieldName(f *types.Var) { } p.string(name) - if name != "" && !ast.IsExported(name) { + if name != "" && !token.IsExported(name) { p.pkg(f.Pkg(), false) } } diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go b/go/vendor/golang.org/x/tools/internal/gcimporter/bimport.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/bimport.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go b/go/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go diff --git a/go/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go b/go/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go new file mode 100644 index 00000000000..0372fb3a646 --- /dev/null +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go @@ -0,0 +1,265 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is a reduced copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go. + +// Package gcimporter provides various functions for reading +// gc-generated object files that can be used to implement the +// Importer interface defined by the Go 1.5 standard library package. +package gcimporter // import "golang.org/x/tools/internal/gcimporter" + +import ( + "bufio" + "bytes" + "fmt" + "go/build" + "go/token" + "go/types" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" +) + +const ( + // Enable debug during development: it adds some additional checks, and + // prevents errors from being recovered. + debug = false + + // If trace is set, debugging output is printed to std out. + trace = false +) + +var exportMap sync.Map // package dir → func() (string, bool) + +// lookupGorootExport returns the location of the export data +// (normally found in the build cache, but located in GOROOT/pkg +// in prior Go releases) for the package located in pkgDir. +// +// (We use the package's directory instead of its import path +// mainly to simplify handling of the packages in src/vendor +// and cmd/vendor.) +func lookupGorootExport(pkgDir string) (string, bool) { + f, ok := exportMap.Load(pkgDir) + if !ok { + var ( + listOnce sync.Once + exportPath string + ) + f, _ = exportMap.LoadOrStore(pkgDir, func() (string, bool) { + listOnce.Do(func() { + cmd := exec.Command("go", "list", "-export", "-f", "{{.Export}}", pkgDir) + cmd.Dir = build.Default.GOROOT + var output []byte + output, err := cmd.Output() + if err != nil { + return + } + + exports := strings.Split(string(bytes.TrimSpace(output)), "\n") + if len(exports) != 1 { + return + } + + exportPath = exports[0] + }) + + return exportPath, exportPath != "" + }) + } + + return f.(func() (string, bool))() +} + +var pkgExts = [...]string{".a", ".o"} + +// FindPkg returns the filename and unique package id for an import +// path based on package information provided by build.Import (using +// the build.Default build.Context). A relative srcDir is interpreted +// relative to the current working directory. +// If no file was found, an empty filename is returned. +func FindPkg(path, srcDir string) (filename, id string) { + if path == "" { + return + } + + var noext string + switch { + default: + // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" + // Don't require the source files to be present. + if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 + srcDir = abs + } + bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) + if bp.PkgObj == "" { + var ok bool + if bp.Goroot && bp.Dir != "" { + filename, ok = lookupGorootExport(bp.Dir) + } + if !ok { + id = path // make sure we have an id to print in error message + return + } + } else { + noext = strings.TrimSuffix(bp.PkgObj, ".a") + id = bp.ImportPath + } + + case build.IsLocalImport(path): + // "./x" -> "/this/directory/x.ext", "/this/directory/x" + noext = filepath.Join(srcDir, path) + id = noext + + case filepath.IsAbs(path): + // for completeness only - go/build.Import + // does not support absolute imports + // "/x" -> "/x.ext", "/x" + noext = path + id = path + } + + if false { // for debugging + if path != id { + fmt.Printf("%s -> %s\n", path, id) + } + } + + if filename != "" { + if f, err := os.Stat(filename); err == nil && !f.IsDir() { + return + } + } + + // try extensions + for _, ext := range pkgExts { + filename = noext + ext + if f, err := os.Stat(filename); err == nil && !f.IsDir() { + return + } + } + + filename = "" // not found + return +} + +// Import imports a gc-generated package given its import path and srcDir, adds +// the corresponding package object to the packages map, and returns the object. +// The packages map must contain all packages already imported. +func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { + var rc io.ReadCloser + var filename, id string + if lookup != nil { + // With custom lookup specified, assume that caller has + // converted path to a canonical import path for use in the map. + if path == "unsafe" { + return types.Unsafe, nil + } + id = path + + // No need to re-import if the package was imported completely before. + if pkg = packages[id]; pkg != nil && pkg.Complete() { + return + } + f, err := lookup(path) + if err != nil { + return nil, err + } + rc = f + } else { + filename, id = FindPkg(path, srcDir) + if filename == "" { + if path == "unsafe" { + return types.Unsafe, nil + } + return nil, fmt.Errorf("can't find import: %q", id) + } + + // no need to re-import if the package was imported completely before + if pkg = packages[id]; pkg != nil && pkg.Complete() { + return + } + + // open file + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer func() { + if err != nil { + // add file name to error + err = fmt.Errorf("%s: %v", filename, err) + } + }() + rc = f + } + defer rc.Close() + + var hdr string + var size int64 + buf := bufio.NewReader(rc) + if hdr, size, err = FindExportData(buf); err != nil { + return + } + + switch hdr { + case "$$B\n": + var data []byte + data, err = ioutil.ReadAll(buf) + if err != nil { + break + } + + // TODO(gri): allow clients of go/importer to provide a FileSet. + // Or, define a new standard go/types/gcexportdata package. + fset := token.NewFileSet() + + // The indexed export format starts with an 'i'; the older + // binary export format starts with a 'c', 'd', or 'v' + // (from "version"). Select appropriate importer. + if len(data) > 0 { + switch data[0] { + case 'i': + _, pkg, err := IImportData(fset, packages, data[1:], id) + return pkg, err + + case 'v', 'c', 'd': + _, pkg, err := BImportData(fset, packages, data, id) + return pkg, err + + case 'u': + _, pkg, err := UImportData(fset, packages, data[1:size], id) + return pkg, err + + default: + l := len(data) + if l > 10 { + l = 10 + } + return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id) + } + } + + default: + err = fmt.Errorf("unknown export data header: %q", hdr) + } + + return +} + +func deref(typ types.Type) types.Type { + if p, _ := typ.(*types.Pointer); p != nil { + return p.Elem() + } + return typ +} + +type byPath []*types.Package + +func (a byPath) Len() int { return len(a) } +func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go b/go/vendor/golang.org/x/tools/internal/gcimporter/iexport.go similarity index 78% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 9a4ff329e12..ba53cdcdd10 100644 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -12,7 +12,6 @@ import ( "bytes" "encoding/binary" "fmt" - "go/ast" "go/constant" "go/token" "go/types" @@ -23,9 +22,45 @@ import ( "strconv" "strings" + "golang.org/x/tools/internal/tokeninternal" "golang.org/x/tools/internal/typeparams" ) +// IExportShallow encodes "shallow" export data for the specified package. +// +// No promises are made about the encoding other than that it can be +// decoded by the same version of IIExportShallow. If you plan to save +// export data in the file system, be sure to include a cryptographic +// digest of the executable in the key to avoid version skew. +func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) { + // In principle this operation can only fail if out.Write fails, + // but that's impossible for bytes.Buffer---and as a matter of + // fact iexportCommon doesn't even check for I/O errors. + // TODO(adonovan): handle I/O errors properly. + // TODO(adonovan): use byte slices throughout, avoiding copying. + const bundle, shallow = false, true + var out bytes.Buffer + err := iexportCommon(&out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg}) + return out.Bytes(), err +} + +// IImportShallow decodes "shallow" types.Package data encoded by IExportShallow +// in the same executable. This function cannot import data from +// cmd/compile or gcexportdata.Write. +func IImportShallow(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string, insert InsertType) (*types.Package, error) { + const bundle = false + pkgs, err := iimportCommon(fset, imports, data, bundle, path, insert) + if err != nil { + return nil, err + } + return pkgs[0], nil +} + +// InsertType is the type of a function that creates a types.TypeName +// object for a named type and inserts it into the scope of the +// specified Package. +type InsertType = func(pkg *types.Package, name string) + // Current bundled export format version. Increase with each format change. // 0: initial implementation const bundleVersion = 0 @@ -36,15 +71,17 @@ const bundleVersion = 0 // The package path of the top-level package will not be recorded, // so that calls to IImportData can override with a provided package path. func IExportData(out io.Writer, fset *token.FileSet, pkg *types.Package) error { - return iexportCommon(out, fset, false, iexportVersion, []*types.Package{pkg}) + const bundle, shallow = false, false + return iexportCommon(out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg}) } // IExportBundle writes an indexed export bundle for pkgs to out. func IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error { - return iexportCommon(out, fset, true, iexportVersion, pkgs) + const bundle, shallow = true, false + return iexportCommon(out, fset, bundle, shallow, iexportVersion, pkgs) } -func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, pkgs []*types.Package) (err error) { +func iexportCommon(out io.Writer, fset *token.FileSet, bundle, shallow bool, version int, pkgs []*types.Package) (err error) { if !debug { defer func() { if e := recover(); e != nil { @@ -61,6 +98,7 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, p := iexporter{ fset: fset, version: version, + shallow: shallow, allPkgs: map[*types.Package]bool{}, stringIndex: map[string]uint64{}, declIndex: map[types.Object]uint64{}, @@ -82,7 +120,7 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, for _, pkg := range pkgs { scope := pkg.Scope() for _, name := range scope.Names() { - if ast.IsExported(name) { + if token.IsExported(name) { p.pushDecl(scope.Lookup(name)) } } @@ -101,6 +139,17 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, p.doDecl(p.declTodo.popHead()) } + // Produce index of offset of each file record in files. + var files intWriter + var fileOffset []uint64 // fileOffset[i] is offset in files of file encoded as i + if p.shallow { + fileOffset = make([]uint64, len(p.fileInfos)) + for i, info := range p.fileInfos { + fileOffset[i] = uint64(files.Len()) + p.encodeFile(&files, info.file, info.needed) + } + } + // Append indices to data0 section. dataLen := uint64(p.data0.Len()) w := p.newWriter() @@ -126,16 +175,75 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, } hdr.uint64(uint64(p.version)) hdr.uint64(uint64(p.strings.Len())) + if p.shallow { + hdr.uint64(uint64(files.Len())) + hdr.uint64(uint64(len(fileOffset))) + for _, offset := range fileOffset { + hdr.uint64(offset) + } + } hdr.uint64(dataLen) // Flush output. io.Copy(out, &hdr) io.Copy(out, &p.strings) + if p.shallow { + io.Copy(out, &files) + } io.Copy(out, &p.data0) return nil } +// encodeFile writes to w a representation of the file sufficient to +// faithfully restore position information about all needed offsets. +// Mutates the needed array. +func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) { + _ = needed[0] // precondition: needed is non-empty + + w.uint64(p.stringOff(file.Name())) + + size := uint64(file.Size()) + w.uint64(size) + + // Sort the set of needed offsets. Duplicates are harmless. + sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] }) + + lines := tokeninternal.GetLines(file) // byte offset of each line start + w.uint64(uint64(len(lines))) + + // Rather than record the entire array of line start offsets, + // we save only a sparse list of (index, offset) pairs for + // the start of each line that contains a needed position. + var sparse [][2]int // (index, offset) pairs +outer: + for i, lineStart := range lines { + lineEnd := size + if i < len(lines)-1 { + lineEnd = uint64(lines[i+1]) + } + // Does this line contains a needed offset? + if needed[0] < lineEnd { + sparse = append(sparse, [2]int{i, lineStart}) + for needed[0] < lineEnd { + needed = needed[1:] + if len(needed) == 0 { + break outer + } + } + } + } + + // Delta-encode the columns. + w.uint64(uint64(len(sparse))) + var prev [2]int + for _, pair := range sparse { + w.uint64(uint64(pair[0] - prev[0])) + w.uint64(uint64(pair[1] - prev[1])) + prev = pair + } +} + // writeIndex writes out an object index. mainIndex indicates whether // we're writing out the main index, which is also read by // non-compiler tools and includes a complete package description @@ -205,7 +313,8 @@ type iexporter struct { out *bytes.Buffer version int - localpkg *types.Package + shallow bool // don't put types from other packages in the index + localpkg *types.Package // (nil in bundle mode) // allPkgs tracks all packages that have been referenced by // the export data, so we can ensure to include them in the @@ -217,6 +326,12 @@ type iexporter struct { strings intWriter stringIndex map[string]uint64 + // In shallow mode, object positions are encoded as (file, offset). + // Each file is recorded as a line-number table. + // Only the lines of needed positions are saved faithfully. + fileInfo map[*token.File]uint64 // value is index in fileInfos + fileInfos []*filePositions + data0 intWriter declIndex map[types.Object]uint64 tparamNames map[types.Object]string // typeparam->exported name @@ -225,6 +340,11 @@ type iexporter struct { indent int // for tracing support } +type filePositions struct { + file *token.File + needed []uint64 // unordered list of needed file offsets +} + func (p *iexporter) trace(format string, args ...interface{}) { if !trace { // Call sites should also be guarded, but having this check here allows @@ -248,6 +368,25 @@ func (p *iexporter) stringOff(s string) uint64 { return off } +// fileIndexAndOffset returns the index of the token.File and the byte offset of pos within it. +func (p *iexporter) fileIndexAndOffset(file *token.File, pos token.Pos) (uint64, uint64) { + index, ok := p.fileInfo[file] + if !ok { + index = uint64(len(p.fileInfo)) + p.fileInfos = append(p.fileInfos, &filePositions{file: file}) + if p.fileInfo == nil { + p.fileInfo = make(map[*token.File]uint64) + } + p.fileInfo[file] = index + } + // Record each needed offset. + info := p.fileInfos[index] + offset := uint64(file.Offset(pos)) + info.needed = append(info.needed, offset) + + return index, offset +} + // pushDecl adds n to the declaration work queue, if not already present. func (p *iexporter) pushDecl(obj types.Object) { // Package unsafe is known to the compiler and predeclared. @@ -256,6 +395,11 @@ func (p *iexporter) pushDecl(obj types.Object) { panic("cannot export package unsafe") } + // Shallow export data: don't index decls from other packages. + if p.shallow && obj.Pkg() != p.localpkg { + return + } + if _, ok := p.declIndex[obj]; ok { return } @@ -303,7 +447,13 @@ func (p *iexporter) doDecl(obj types.Object) { case *types.Func: sig, _ := obj.Type().(*types.Signature) if sig.Recv() != nil { - panic(internalErrorf("unexpected method: %v", sig)) + // We shouldn't see methods in the package scope, + // but the type checker may repair "func () F() {}" + // to "func (Invalid) F()" and then treat it like "func F()", + // so allow that. See golang/go#57729. + if sig.Recv().Type() != types.Typ[types.Invalid] { + panic(internalErrorf("unexpected method: %v", sig)) + } } // Function. @@ -415,13 +565,30 @@ func (w *exportWriter) tag(tag byte) { } func (w *exportWriter) pos(pos token.Pos) { - if w.p.version >= iexportVersionPosCol { + if w.p.shallow { + w.posV2(pos) + } else if w.p.version >= iexportVersionPosCol { w.posV1(pos) } else { w.posV0(pos) } } +// posV2 encoding (used only in shallow mode) records positions as +// (file, offset), where file is the index in the token.File table +// (which records the file name and newline offsets) and offset is a +// byte offset. It effectively ignores //line directives. +func (w *exportWriter) posV2(pos token.Pos) { + if pos == token.NoPos { + w.uint64(0) + return + } + file := w.p.fset.File(pos) // fset must be non-nil + index, offset := w.p.fileIndexAndOffset(file, pos) + w.uint64(1 + index) + w.uint64(offset) +} + func (w *exportWriter) posV1(pos token.Pos) { if w.p.fset == nil { w.int64(0) @@ -497,7 +664,7 @@ func (w *exportWriter) pkg(pkg *types.Package) { w.string(w.exportPath(pkg)) } -func (w *exportWriter) qualifiedIdent(obj types.Object) { +func (w *exportWriter) qualifiedType(obj *types.TypeName) { name := w.p.exportName(obj) // Ensure any referenced declarations are written out too. @@ -556,11 +723,11 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { return } w.startType(definedType) - w.qualifiedIdent(t.Obj()) + w.qualifiedType(t.Obj()) case *typeparams.TypeParam: w.startType(typeParamType) - w.qualifiedIdent(t.Obj()) + w.qualifiedType(t.Obj()) case *types.Pointer: w.startType(pointerType) @@ -602,14 +769,17 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { case *types.Struct: w.startType(structType) - w.setPkg(pkg, true) - n := t.NumFields() + if n > 0 { + w.setPkg(t.Field(0).Pkg(), true) // qualifying package for field objects + } else { + w.setPkg(pkg, true) + } w.uint64(uint64(n)) for i := 0; i < n; i++ { f := t.Field(i) w.pos(f.Pos()) - w.string(f.Name()) + w.string(f.Name()) // unexported fields implicitly qualified by prior setPkg w.typ(f.Type(), pkg) w.bool(f.Anonymous()) w.string(t.Tag(i)) // note (or tag) diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go b/go/vendor/golang.org/x/tools/internal/gcimporter/iimport.go similarity index 86% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index 4caa0f55d9d..448f903e86a 100644 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -51,6 +51,8 @@ const ( iexportVersionPosCol = 1 iexportVersionGo1_18 = 2 iexportVersionGenerics = 2 + + iexportVersionCurrent = 2 ) type ident struct { @@ -83,7 +85,7 @@ const ( // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) { - pkgs, err := iimportCommon(fset, imports, data, false, path) + pkgs, err := iimportCommon(fset, imports, data, false, path, nil) if err != nil { return 0, nil, err } @@ -92,11 +94,11 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data [] // IImportBundle imports a set of packages from the serialized package bundle. func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) { - return iimportCommon(fset, imports, data, true, "") + return iimportCommon(fset, imports, data, true, "", nil) } -func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) { - const currentVersion = 1 +func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) { + const currentVersion = iexportVersionCurrent version := int64(-1) if !debug { defer func() { @@ -135,19 +137,34 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data } sLen := int64(r.uint64()) + var fLen int64 + var fileOffset []uint64 + if insert != nil { + // Shallow mode uses a different position encoding. + fLen = int64(r.uint64()) + fileOffset = make([]uint64, r.uint64()) + for i := range fileOffset { + fileOffset[i] = r.uint64() + } + } dLen := int64(r.uint64()) whence, _ := r.Seek(0, io.SeekCurrent) stringData := data[whence : whence+sLen] - declData := data[whence+sLen : whence+sLen+dLen] - r.Seek(sLen+dLen, io.SeekCurrent) + fileData := data[whence+sLen : whence+sLen+fLen] + declData := data[whence+sLen+fLen : whence+sLen+fLen+dLen] + r.Seek(sLen+fLen+dLen, io.SeekCurrent) p := iimporter{ version: int(version), ipath: path, + insert: insert, stringData: stringData, stringCache: make(map[uint64]string), + fileOffset: fileOffset, + fileData: fileData, + fileCache: make([]*token.File, len(fileOffset)), pkgCache: make(map[uint64]*types.Package), declData: declData, @@ -185,11 +202,18 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data } else if pkg.Name() != pkgName { errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) } + if i == 0 && !bundle { + p.localpkg = pkg + } p.pkgCache[pkgPathOff] = pkg + // Read index for package. nameIndex := make(map[string]uint64) - for nSyms := r.uint64(); nSyms > 0; nSyms-- { + nSyms := r.uint64() + // In shallow mode we don't expect an index for other packages. + assert(nSyms == 0 || p.localpkg == pkg || p.insert == nil) + for ; nSyms > 0; nSyms-- { name := p.stringAt(r.uint64()) nameIndex[name] = r.uint64() } @@ -265,8 +289,14 @@ type iimporter struct { version int ipath string + localpkg *types.Package + insert func(pkg *types.Package, name string) // "shallow" mode only + stringData []byte stringCache map[uint64]string + fileOffset []uint64 // fileOffset[i] is offset in fileData for info about file encoded as i + fileData []byte + fileCache []*token.File // memoized decoding of file encoded as i pkgCache map[uint64]*types.Package declData []byte @@ -308,6 +338,13 @@ func (p *iimporter) doDecl(pkg *types.Package, name string) { off, ok := p.pkgIndex[pkg][name] if !ok { + // In "shallow" mode, call back to the application to + // find the object and insert it into the package scope. + if p.insert != nil { + assert(pkg != p.localpkg) + p.insert(pkg, name) // "can't fail" + return + } errorf("%v.%v not in index", pkg, name) } @@ -332,6 +369,55 @@ func (p *iimporter) stringAt(off uint64) string { return s } +func (p *iimporter) fileAt(index uint64) *token.File { + file := p.fileCache[index] + if file == nil { + off := p.fileOffset[index] + file = p.decodeFile(intReader{bytes.NewReader(p.fileData[off:]), p.ipath}) + p.fileCache[index] = file + } + return file +} + +func (p *iimporter) decodeFile(rd intReader) *token.File { + filename := p.stringAt(rd.uint64()) + size := int(rd.uint64()) + file := p.fake.fset.AddFile(filename, -1, size) + + // SetLines requires a nondecreasing sequence. + // Because it is common for clients to derive the interval + // [start, start+len(name)] from a start position, and we + // want to ensure that the end offset is on the same line, + // we fill in the gaps of the sparse encoding with values + // that strictly increase by the largest possible amount. + // This allows us to avoid having to record the actual end + // offset of each needed line. + + lines := make([]int, int(rd.uint64())) + var index, offset int + for i, n := 0, int(rd.uint64()); i < n; i++ { + index += int(rd.uint64()) + offset += int(rd.uint64()) + lines[index] = offset + + // Ensure monotonicity between points. + for j := index - 1; j > 0 && lines[j] == 0; j-- { + lines[j] = lines[j+1] - 1 + } + } + + // Ensure monotonicity after last point. + for j := len(lines) - 1; j > 0 && lines[j] == 0; j-- { + size-- + lines[j] = size + } + + if !file.SetLines(lines) { + errorf("SetLines failed: %d", lines) // can't happen + } + return file +} + func (p *iimporter) pkgAt(off uint64) *types.Package { if pkg, ok := p.pkgCache[off]; ok { return pkg @@ -625,6 +711,9 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) { } func (r *importReader) pos() token.Pos { + if r.p.insert != nil { // shallow mode + return r.posv2() + } if r.p.version >= iexportVersionPosCol { r.posv1() } else { @@ -661,6 +750,15 @@ func (r *importReader) posv1() { } } +func (r *importReader) posv2() token.Pos { + file := r.uint64() + if file == 0 { + return token.NoPos + } + tf := r.p.fileAt(file - 1) + return tf.Pos(int(r.uint64())) +} + func (r *importReader) typ() types.Type { return r.p.typAt(r.uint64(), nil) } diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go b/go/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go b/go/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go b/go/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go b/go/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go similarity index 62% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go index a993843230c..edbe6ea7041 100644 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go @@ -21,3 +21,17 @@ func additionalPredeclared() []types.Type { types.Universe.Lookup("any").Type(), } } + +// See cmd/compile/internal/types.SplitVargenSuffix. +func splitVargenSuffix(name string) (base, suffix string) { + i := len(name) + for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { + i-- + } + const dot = "·" + if i >= len(dot) && name[i-len(dot):i] == dot { + i -= len(dot) + return name[:i], name[i:] + } + return name, "" +} diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/unified_no.go b/go/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/unified_no.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/unified_yes.go b/go/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/unified_yes.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/ureader_no.go b/go/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/ureader_no.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go diff --git a/go/vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go b/go/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go similarity index 70% rename from go/vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go rename to go/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go index 3c1a4375435..b285a11ce25 100644 --- a/go/vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go +++ b/go/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go @@ -14,7 +14,7 @@ import ( "go/types" "strings" - "golang.org/x/tools/go/internal/pkgbits" + "golang.org/x/tools/internal/pkgbits" ) // A pkgReader holds the shared state for reading a unified IR package @@ -36,6 +36,12 @@ type pkgReader struct { // laterFns holds functions that need to be invoked at the end of // import reading. laterFns []func() + // laterFors is used in case of 'type A B' to ensure that B is processed before A. + laterFors map[types.Type]int + + // ifaces holds a list of constructed Interfaces, which need to have + // Complete called after importing is done. + ifaces []*types.Interface } // later adds a function to be invoked at the end of import reading. @@ -63,6 +69,15 @@ func UImportData(fset *token.FileSet, imports map[string]*types.Package, data [] return } +// laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing. +func (pr *pkgReader) laterFor(t types.Type, fn func()) { + if pr.laterFors == nil { + pr.laterFors = make(map[types.Type]int) + } + pr.laterFors[t] = len(pr.laterFns) + pr.laterFns = append(pr.laterFns, fn) +} + // readUnifiedPackage reads a package description from the given // unified IR export data decoder. func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package { @@ -102,6 +117,10 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st fn() } + for _, iface := range pr.ifaces { + iface.Complete() + } + pkg.MarkComplete() return pkg } @@ -139,6 +158,17 @@ func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pk } } +func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { + return &reader{ + Decoder: pr.TempDecoder(k, idx, marker), + p: pr, + } +} + +func (pr *pkgReader) retireReader(r *reader) { + pr.RetireDecoder(&r.Decoder) +} + // @@@ Positions func (r *reader) pos() token.Pos { @@ -163,26 +193,29 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string { return b } - r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) + var filename string + { + r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) - // Within types2, position bases have a lot more details (e.g., - // keeping track of where //line directives appeared exactly). - // - // For go/types, we just track the file name. + // Within types2, position bases have a lot more details (e.g., + // keeping track of where //line directives appeared exactly). + // + // For go/types, we just track the file name. - filename := r.String() + filename = r.String() - if r.Bool() { // file base - // Was: "b = token.NewTrimmedFileBase(filename, true)" - } else { // line base - pos := r.pos() - line := r.Uint() - col := r.Uint() + if r.Bool() { // file base + // Was: "b = token.NewTrimmedFileBase(filename, true)" + } else { // line base + pos := r.pos() + line := r.Uint() + col := r.Uint() - // Was: "b = token.NewLineBase(pos, filename, true, line, col)" - _, _, _ = pos, line, col + // Was: "b = token.NewLineBase(pos, filename, true, line, col)" + _, _, _ = pos, line, col + } + pr.retireReader(r) } - b := filename pr.posBases[idx] = b return b @@ -231,11 +264,35 @@ func (r *reader) doPkg() *types.Package { for i := range imports { imports[i] = r.pkg() } - pkg.SetImports(imports) + pkg.SetImports(flattenImports(imports)) return pkg } +// flattenImports returns the transitive closure of all imported +// packages rooted from pkgs. +func flattenImports(pkgs []*types.Package) []*types.Package { + var res []*types.Package + seen := make(map[*types.Package]struct{}) + for _, pkg := range pkgs { + if _, ok := seen[pkg]; ok { + continue + } + seen[pkg] = struct{}{} + res = append(res, pkg) + + // pkg.Imports() is already flattened. + for _, pkg := range pkg.Imports() { + if _, ok := seen[pkg]; ok { + continue + } + seen[pkg] = struct{}{} + res = append(res, pkg) + } + } + return res +} + // @@@ Types func (r *reader) typ() types.Type { @@ -264,12 +321,15 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type { return typ } - r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) - r.dict = dict - - typ := r.doTyp() - assert(typ != nil) + var typ types.Type + { + r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) + r.dict = dict + typ = r.doTyp() + assert(typ != nil) + pr.retireReader(r) + } // See comment in pkgReader.typIdx explaining how this happens. if prev := *where; prev != nil { return prev @@ -372,6 +432,16 @@ func (r *reader) interfaceType() *types.Interface { if implicit { iface.MarkImplicit() } + + // We need to call iface.Complete(), but if there are any embedded + // defined types, then we may not have set their underlying + // interface type yet. So we need to defer calling Complete until + // after we've called SetUnderlying everywhere. + // + // TODO(mdempsky): After CL 424876 lands, it should be safe to call + // iface.Complete() immediately. + r.p.ifaces = append(r.p.ifaces, iface) + return iface } @@ -425,18 +495,30 @@ func (r *reader) obj() (types.Object, []types.Type) { } func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { - rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) - objPkg, objName := rname.qualifiedIdent() - assert(objName != "") + var objPkg *types.Package + var objName string + var tag pkgbits.CodeObj + { + rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) - tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) + objPkg, objName = rname.qualifiedIdent() + assert(objName != "") + + tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) + pr.retireReader(rname) + } if tag == pkgbits.ObjStub { assert(objPkg == nil || objPkg == types.Unsafe) return objPkg, objName } + // Ignore local types promoted to global scope (#55110). + if _, suffix := splitVargenSuffix(objName); suffix != "" { + return objPkg, objName + } + if objPkg.Scope().Lookup(objName) == nil { dict := pr.objDictIdx(idx) @@ -477,15 +559,56 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { named.SetTypeParams(r.typeParamNames()) - // TODO(mdempsky): Rewrite receiver types to underlying is an - // Interface? The go/types importer does this (I think because - // unit tests expected that), but cmd/compile doesn't care - // about it, so maybe we can avoid worrying about that here. - rhs := r.typ() - r.p.later(func() { - underlying := rhs.Underlying() + setUnderlying := func(underlying types.Type) { + // If the underlying type is an interface, we need to + // duplicate its methods so we can replace the receiver + // parameter's type (#49906). + if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { + methods := make([]*types.Func, iface.NumExplicitMethods()) + for i := range methods { + fn := iface.ExplicitMethod(i) + sig := fn.Type().(*types.Signature) + + recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named) + methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic())) + } + + embeds := make([]types.Type, iface.NumEmbeddeds()) + for i := range embeds { + embeds[i] = iface.EmbeddedType(i) + } + + newIface := types.NewInterfaceType(methods, embeds) + r.p.ifaces = append(r.p.ifaces, newIface) + underlying = newIface + } + named.SetUnderlying(underlying) - }) + } + + // Since go.dev/cl/455279, we can assume rhs.Underlying() will + // always be non-nil. However, to temporarily support users of + // older snapshot releases, we continue to fallback to the old + // behavior for now. + // + // TODO(mdempsky): Remove fallback code and simplify after + // allowing time for snapshot users to upgrade. + rhs := r.typ() + if underlying := rhs.Underlying(); underlying != nil { + setUnderlying(underlying) + } else { + pk := r.p + pk.laterFor(named, func() { + // First be sure that the rhs is initialized, if it needs to be initialized. + delete(pk.laterFors, named) // prevent cycles + if i, ok := pk.laterFors[rhs]; ok { + f := pk.laterFns[i] + pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op + f() // initialize RHS + } + setUnderlying(rhs.Underlying()) + }) + } for i, n := 0, r.Len(); i < n; i++ { named.AddMethod(r.method()) @@ -502,25 +625,28 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { } func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { - r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) var dict readerDict - if implicits := r.Len(); implicits != 0 { - errorf("unexpected object with %v implicit type parameter(s)", implicits) - } + { + r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) + if implicits := r.Len(); implicits != 0 { + errorf("unexpected object with %v implicit type parameter(s)", implicits) + } - dict.bounds = make([]typeInfo, r.Len()) - for i := range dict.bounds { - dict.bounds[i] = r.typInfo() - } + dict.bounds = make([]typeInfo, r.Len()) + for i := range dict.bounds { + dict.bounds[i] = r.typInfo() + } - dict.derived = make([]derivedInfo, r.Len()) - dict.derivedTypes = make([]types.Type, len(dict.derived)) - for i := range dict.derived { - dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} - } + dict.derived = make([]derivedInfo, r.Len()) + dict.derivedTypes = make([]types.Type, len(dict.derived)) + for i := range dict.derived { + dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} + } + pr.retireReader(r) + } // function references follow, but reader doesn't need those return &dict diff --git a/go/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/go/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 67256dc3974..d50551693f3 100644 --- a/go/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/go/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -10,8 +10,10 @@ import ( "context" "fmt" "io" + "log" "os" "regexp" + "runtime" "strconv" "strings" "sync" @@ -232,6 +234,12 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error { return runCmdContext(ctx, cmd) } +// DebugHangingGoCommands may be set by tests to enable additional +// instrumentation (including panics) for debugging hanging Go commands. +// +// See golang/go#54461 for details. +var DebugHangingGoCommands = false + // runCmdContext is like exec.CommandContext except it sends os.Interrupt // before os.Kill. func runCmdContext(ctx context.Context, cmd *exec.Cmd) error { @@ -243,11 +251,24 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error { resChan <- cmd.Wait() }() - select { - case err := <-resChan: - return err - case <-ctx.Done(): + // If we're interested in debugging hanging Go commands, stop waiting after a + // minute and panic with interesting information. + if DebugHangingGoCommands { + select { + case err := <-resChan: + return err + case <-time.After(1 * time.Minute): + HandleHangingGoCommand(cmd.Process) + case <-ctx.Done(): + } + } else { + select { + case err := <-resChan: + return err + case <-ctx.Done(): + } } + // Cancelled. Interrupt and see if it ends voluntarily. cmd.Process.Signal(os.Interrupt) select { @@ -255,11 +276,63 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error { return err case <-time.After(time.Second): } + // Didn't shut down in response to interrupt. Kill it hard. - cmd.Process.Kill() + // TODO(rfindley): per advice from bcmills@, it may be better to send SIGQUIT + // on certain platforms, such as unix. + if err := cmd.Process.Kill(); err != nil && DebugHangingGoCommands { + // Don't panic here as this reliably fails on windows with EINVAL. + log.Printf("error killing the Go command: %v", err) + } + + // See above: don't wait indefinitely if we're debugging hanging Go commands. + if DebugHangingGoCommands { + select { + case err := <-resChan: + return err + case <-time.After(10 * time.Second): // a shorter wait as resChan should return quickly following Kill + HandleHangingGoCommand(cmd.Process) + } + } return <-resChan } +func HandleHangingGoCommand(proc *os.Process) { + switch runtime.GOOS { + case "linux", "darwin", "freebsd", "netbsd": + fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND + +The gopls test runner has detected a hanging go command. In order to debug +this, the output of ps and lsof/fstat is printed below. + +See golang/go#54461 for more details.`) + + fmt.Fprintln(os.Stderr, "\nps axo ppid,pid,command:") + fmt.Fprintln(os.Stderr, "-------------------------") + psCmd := exec.Command("ps", "axo", "ppid,pid,command") + psCmd.Stdout = os.Stderr + psCmd.Stderr = os.Stderr + if err := psCmd.Run(); err != nil { + panic(fmt.Sprintf("running ps: %v", err)) + } + + listFiles := "lsof" + if runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" { + listFiles = "fstat" + } + + fmt.Fprintln(os.Stderr, "\n"+listFiles+":") + fmt.Fprintln(os.Stderr, "-----") + listFilesCmd := exec.Command(listFiles) + listFilesCmd.Stdout = os.Stderr + listFilesCmd.Stderr = os.Stderr + if err := listFilesCmd.Run(); err != nil { + panic(fmt.Sprintf("running %s: %v", listFiles, err)) + } + } + panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid)) +} + func cmdDebugStr(cmd *exec.Cmd) string { env := make(map[string]string) for _, kv := range cmd.Env { diff --git a/go/vendor/golang.org/x/tools/internal/gocommand/version.go b/go/vendor/golang.org/x/tools/internal/gocommand/version.go index 71304368020..307a76d474a 100644 --- a/go/vendor/golang.org/x/tools/internal/gocommand/version.go +++ b/go/vendor/golang.org/x/tools/internal/gocommand/version.go @@ -7,11 +7,19 @@ package gocommand import ( "context" "fmt" + "regexp" "strings" ) -// GoVersion checks the go version by running "go list" with modules off. -// It returns the X in Go 1.X. +// GoVersion reports the minor version number of the highest release +// tag built into the go command on the PATH. +// +// Note that this may be higher than the version of the go tool used +// to build this application, and thus the versions of the standard +// go/{scanner,parser,ast,types} packages that are linked into it. +// In that case, callers should either downgrade to the version of +// go used to build the application, or report an error that the +// application is too old to use the go command on the PATH. func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) { inv.Verb = "list" inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`, `--`, `unsafe`} @@ -38,7 +46,7 @@ func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) { if len(stdout) < 3 { return 0, fmt.Errorf("bad ReleaseTags output: %q", stdout) } - // Split up "[go1.1 go1.15]" + // Split up "[go1.1 go1.15]" and return highest go1.X value. tags := strings.Fields(stdout[1 : len(stdout)-2]) for i := len(tags) - 1; i >= 0; i-- { var version int @@ -49,3 +57,25 @@ func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) { } return 0, fmt.Errorf("no parseable ReleaseTags in %v", tags) } + +// GoVersionOutput returns the complete output of the go version command. +func GoVersionOutput(ctx context.Context, inv Invocation, r *Runner) (string, error) { + inv.Verb = "version" + goVersion, err := r.Run(ctx, inv) + if err != nil { + return "", err + } + return goVersion.String(), nil +} + +// ParseGoVersionOutput extracts the Go version string +// from the output of the "go version" command. +// Given an unrecognized form, it returns an empty string. +func ParseGoVersionOutput(data string) string { + re := regexp.MustCompile(`^go version (go\S+|devel \S+)`) + m := re.FindStringSubmatch(data) + if len(m) != 2 { + return "" // unrecognized version + } + return m[1] +} diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/codes.go b/go/vendor/golang.org/x/tools/internal/pkgbits/codes.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/codes.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/codes.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go b/go/vendor/golang.org/x/tools/internal/pkgbits/decoder.go similarity index 83% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/decoder.go index 2bc793668ec..b92e8e6eb32 100644 --- a/go/vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go +++ b/go/vendor/golang.org/x/tools/internal/pkgbits/decoder.go @@ -6,9 +6,11 @@ package pkgbits import ( "encoding/binary" + "errors" "fmt" "go/constant" "go/token" + "io" "math/big" "os" "runtime" @@ -51,6 +53,8 @@ type PkgDecoder struct { // For example, section K's end positions start at elemEndsEnds[K-1] // (or 0, if K==0) and end at elemEndsEnds[K]. elemEndsEnds [numRelocs]uint32 + + scratchRelocEnt []RelocEnt } // PkgPath returns the package path for the package @@ -94,7 +98,7 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder { pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1]) assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil) - pos, err := r.Seek(0, os.SEEK_CUR) + pos, err := r.Seek(0, io.SeekCurrent) assert(err == nil) pr.elemData = input[pos:] @@ -164,6 +168,21 @@ func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Deco return r } +// TempDecoder returns a Decoder for the given (section, index) pair, +// and decodes the given SyncMarker from the element bitstream. +// If possible the Decoder should be RetireDecoder'd when it is no longer +// needed, this will avoid heap allocations. +func (pr *PkgDecoder) TempDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder { + r := pr.TempDecoderRaw(k, idx) + r.Sync(marker) + return r +} + +func (pr *PkgDecoder) RetireDecoder(d *Decoder) { + pr.scratchRelocEnt = d.Relocs + d.Relocs = nil +} + // NewDecoderRaw returns a Decoder for the given (section, index) pair. // // Most callers should use NewDecoder instead. @@ -187,6 +206,30 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder { return r } +func (pr *PkgDecoder) TempDecoderRaw(k RelocKind, idx Index) Decoder { + r := Decoder{ + common: pr, + k: k, + Idx: idx, + } + + r.Data.Reset(pr.DataIdx(k, idx)) + r.Sync(SyncRelocs) + l := r.Len() + if cap(pr.scratchRelocEnt) >= l { + r.Relocs = pr.scratchRelocEnt[:l] + pr.scratchRelocEnt = nil + } else { + r.Relocs = make([]RelocEnt, l) + } + for i := range r.Relocs { + r.Sync(SyncReloc) + r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())} + } + + return r +} + // A Decoder provides methods for decoding an individual element's // bitstream data. type Decoder struct { @@ -206,11 +249,39 @@ func (r *Decoder) checkErr(err error) { } func (r *Decoder) rawUvarint() uint64 { - x, err := binary.ReadUvarint(&r.Data) + x, err := readUvarint(&r.Data) r.checkErr(err) return x } +// readUvarint is a type-specialized copy of encoding/binary.ReadUvarint. +// This avoids the interface conversion and thus has better escape properties, +// which flows up the stack. +func readUvarint(r *strings.Reader) (uint64, error) { + var x uint64 + var s uint + for i := 0; i < binary.MaxVarintLen64; i++ { + b, err := r.ReadByte() + if err != nil { + if i > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return x, err + } + if b < 0x80 { + if i == binary.MaxVarintLen64-1 && b > 1 { + return x, overflow + } + return x | uint64(b)<= 0); w.Uint64(uint64(x)) } // Int encodes and writes an int value into the element bitstream. func (w *Encoder) Int(x int) { w.Int64(int64(x)) } -// Len encodes and writes a uint value into the element bitstream. +// Uint encodes and writes a uint value into the element bitstream. func (w *Encoder) Uint(x uint) { w.Uint64(uint64(x)) } // Reloc encodes and writes a relocation for the given (section, diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/flags.go b/go/vendor/golang.org/x/tools/internal/pkgbits/flags.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/flags.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/flags.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/frames_go1.go b/go/vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/frames_go1.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/frames_go17.go b/go/vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/frames_go17.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go b/go/vendor/golang.org/x/tools/internal/pkgbits/reloc.go similarity index 95% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/reloc.go index 7a8f04ab3fc..fcdfb97ca99 100644 --- a/go/vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go +++ b/go/vendor/golang.org/x/tools/internal/pkgbits/reloc.go @@ -5,11 +5,11 @@ package pkgbits // A RelocKind indicates a particular section within a unified IR export. -type RelocKind int +type RelocKind int32 // An Index represents a bitstream element index within a particular // section. -type Index int +type Index int32 // A relocEnt (relocation entry) is an entry in an element's local // reference table. diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/support.go b/go/vendor/golang.org/x/tools/internal/pkgbits/support.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/support.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/support.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/sync.go b/go/vendor/golang.org/x/tools/internal/pkgbits/sync.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/sync.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/sync.go diff --git a/go/vendor/golang.org/x/tools/go/internal/pkgbits/syncmarker_string.go b/go/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go similarity index 100% rename from go/vendor/golang.org/x/tools/go/internal/pkgbits/syncmarker_string.go rename to go/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go diff --git a/go/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go b/go/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go new file mode 100644 index 00000000000..a3fb2d4f29d --- /dev/null +++ b/go/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go @@ -0,0 +1,59 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package tokeninternal provides access to some internal features of the token +// package. +package tokeninternal + +import ( + "go/token" + "sync" + "unsafe" +) + +// GetLines returns the table of line-start offsets from a token.File. +func GetLines(file *token.File) []int { + // token.File has a Lines method on Go 1.21 and later. + if file, ok := (interface{})(file).(interface{ Lines() []int }); ok { + return file.Lines() + } + + // This declaration must match that of token.File. + // This creates a risk of dependency skew. + // For now we check that the size of the two + // declarations is the same, on the (fragile) assumption + // that future changes would add fields. + type tokenFile119 struct { + _ string + _ int + _ int + mu sync.Mutex // we're not complete monsters + lines []int + _ []struct{} + } + type tokenFile118 struct { + _ *token.FileSet // deleted in go1.19 + tokenFile119 + } + + type uP = unsafe.Pointer + switch unsafe.Sizeof(*file) { + case unsafe.Sizeof(tokenFile118{}): + var ptr *tokenFile118 + *(*uP)(uP(&ptr)) = uP(file) + ptr.mu.Lock() + defer ptr.mu.Unlock() + return ptr.lines + + case unsafe.Sizeof(tokenFile119{}): + var ptr *tokenFile119 + *(*uP)(uP(&ptr)) = uP(file) + ptr.mu.Lock() + defer ptr.mu.Unlock() + return ptr.lines + + default: + panic("unexpected token.File size") + } +} diff --git a/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go b/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go index d38ee3c27cd..07484073a57 100644 --- a/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go +++ b/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go @@ -30,6 +30,12 @@ type ErrorCode int // convention that "bad" implies a problem with syntax, and "invalid" implies a // problem with types. +const ( + // InvalidSyntaxTree occurs if an invalid syntax tree is provided + // to the type checker. It should never happen. + InvalidSyntaxTree ErrorCode = -1 +) + const ( _ ErrorCode = iota @@ -153,12 +159,12 @@ const ( /* decls > var (+ other variable assignment codes) */ - // UntypedNil occurs when the predeclared (untyped) value nil is used to + // UntypedNilUse occurs when the predeclared (untyped) value nil is used to // initialize a variable declared without an explicit type. // // Example: // var x = nil - UntypedNil + UntypedNilUse // WrongAssignCount occurs when the number of values on the right-hand side // of an assignment or or initialization expression does not match the number @@ -1523,4 +1529,32 @@ const ( // Example: // type T[P any] struct{ *P } MisplacedTypeParam + + // InvalidUnsafeSliceData occurs when unsafe.SliceData is called with + // an argument that is not of slice type. It also occurs if it is used + // in a package compiled for a language version before go1.20. + // + // Example: + // import "unsafe" + // + // var x int + // var _ = unsafe.SliceData(x) + InvalidUnsafeSliceData + + // InvalidUnsafeString occurs when unsafe.String is called with + // a length argument that is not of integer type, negative, or + // out of bounds. It also occurs if it is used in a package + // compiled for a language version before go1.20. + // + // Example: + // import "unsafe" + // + // var b [10]byte + // var _ = unsafe.String(&b[0], -1) + InvalidUnsafeString + + // InvalidUnsafeStringData occurs if it is used in a package + // compiled for a language version before go1.20. + _ // not used anymore + ) diff --git a/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go b/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go index de90e9515ae..15ecf7c5ded 100644 --- a/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go +++ b/go/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go @@ -8,6 +8,7 @@ func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} + _ = x[InvalidSyntaxTree - -1] _ = x[Test-1] _ = x[BlankPkgName-2] _ = x[MismatchedPkgName-3] @@ -23,7 +24,7 @@ func _() { _ = x[InvalidConstInit-13] _ = x[InvalidConstVal-14] _ = x[InvalidConstType-15] - _ = x[UntypedNil-16] + _ = x[UntypedNilUse-16] _ = x[WrongAssignCount-17] _ = x[UnassignableOperand-18] _ = x[NoNewVar-19] @@ -152,16 +153,27 @@ func _() { _ = x[MisplacedConstraintIface-142] _ = x[InvalidMethodTypeParams-143] _ = x[MisplacedTypeParam-144] + _ = x[InvalidUnsafeSliceData-145] + _ = x[InvalidUnsafeString-146] } -const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParam" +const ( + _ErrorCode_name_0 = "InvalidSyntaxTree" + _ErrorCode_name_1 = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilUseWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParamInvalidUnsafeSliceDataInvalidUnsafeString" +) -var _ErrorCode_index = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 215, 231, 250, 258, 274, 292, 309, 327, 351, 359, 374, 390, 408, 425, 440, 447, 458, 481, 496, 508, 519, 534, 548, 563, 578, 591, 600, 614, 629, 640, 655, 664, 680, 700, 718, 737, 749, 768, 787, 803, 820, 839, 853, 864, 879, 892, 907, 923, 937, 953, 968, 985, 1003, 1018, 1028, 1038, 1055, 1077, 1091, 1105, 1125, 1143, 1163, 1181, 1204, 1220, 1235, 1248, 1258, 1270, 1281, 1295, 1308, 1319, 1329, 1344, 1355, 1366, 1379, 1395, 1412, 1436, 1453, 1468, 1478, 1487, 1500, 1516, 1532, 1543, 1558, 1574, 1588, 1604, 1618, 1635, 1655, 1668, 1684, 1698, 1715, 1732, 1749, 1764, 1778, 1792, 1803, 1815, 1828, 1845, 1858, 1869, 1882, 1894, 1903, 1910, 1922, 1938, 1956, 1974, 1989, 2006, 2025, 2039, 2059, 2071, 2095, 2118, 2136} +var ( + _ErrorCode_index_1 = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 218, 234, 253, 261, 277, 295, 312, 330, 354, 362, 377, 393, 411, 428, 443, 450, 461, 484, 499, 511, 522, 537, 551, 566, 581, 594, 603, 617, 632, 643, 658, 667, 683, 703, 721, 740, 752, 771, 790, 806, 823, 842, 856, 867, 882, 895, 910, 926, 940, 956, 971, 988, 1006, 1021, 1031, 1041, 1058, 1080, 1094, 1108, 1128, 1146, 1166, 1184, 1207, 1223, 1238, 1251, 1261, 1273, 1284, 1298, 1311, 1322, 1332, 1347, 1358, 1369, 1382, 1398, 1415, 1439, 1456, 1471, 1481, 1490, 1503, 1519, 1535, 1546, 1561, 1577, 1591, 1607, 1621, 1638, 1658, 1671, 1687, 1701, 1718, 1735, 1752, 1767, 1781, 1795, 1806, 1818, 1831, 1848, 1861, 1872, 1885, 1897, 1906, 1913, 1925, 1941, 1959, 1977, 1992, 2009, 2028, 2042, 2062, 2074, 2098, 2121, 2139, 2161, 2180} +) func (i ErrorCode) String() string { - i -= 1 - if i < 0 || i >= ErrorCode(len(_ErrorCode_index)-1) { - return "ErrorCode(" + strconv.FormatInt(int64(i+1), 10) + ")" + switch { + case i == -1: + return _ErrorCode_name_0 + case 1 <= i && i <= 146: + i -= 1 + return _ErrorCode_name_1[_ErrorCode_index_1[i]:_ErrorCode_index_1[i+1]] + default: + return "ErrorCode(" + strconv.FormatInt(int64(i), 10) + ")" } - return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]] } diff --git a/go/vendor/modules.txt b/go/vendor/modules.txt index 47121546873..596bd8e8ae9 100644 --- a/go/vendor/modules.txt +++ b/go/vendor/modules.txt @@ -1,25 +1,26 @@ -# golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 +# golang.org/x/mod v0.8.0 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f +# golang.org/x/sys v0.5.0 ## explicit; go 1.17 golang.org/x/sys/execabs -# golang.org/x/tools v0.1.12 +# golang.org/x/tools v0.6.0 ## explicit; go 1.18 golang.org/x/tools/go/gcexportdata -golang.org/x/tools/go/internal/gcimporter golang.org/x/tools/go/internal/packagesdriver -golang.org/x/tools/go/internal/pkgbits golang.org/x/tools/go/packages golang.org/x/tools/internal/event golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event/keys golang.org/x/tools/internal/event/label +golang.org/x/tools/internal/gcimporter golang.org/x/tools/internal/gocommand golang.org/x/tools/internal/packagesinternal +golang.org/x/tools/internal/pkgbits +golang.org/x/tools/internal/tokeninternal golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index e834d085511..fbdd50b2091 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -1,132 +1,132 @@ -package,sink,source,summary,sink:bean-validation,sink:create-file,sink:fragment-injection,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:regex-use,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:set-hostname-verifier,sink:sql,sink:ssti,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-external-storage-dir,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value -android.app,35,,103,,,11,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,18,85 -android.content,24,31,154,,,,,,,16,,,,,,,,,,,,,,,,,,8,,,,,,,,4,,27,,63,91 -android.database,59,,39,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,39, -android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15 -android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,41,81 -android.support.v4.app,11,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -android.util,6,16,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,16,, -android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,2,, -android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,1, -androidx.core.app,6,,95,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,12,83 -androidx.fragment.app,11,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -androidx.slice,2,5,88,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,5,,27,61 -cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, -com.google.common.base,4,,85,,,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,,62,23 -com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17 -com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551 -com.google.common.flogger,29,,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,,,, -com.google.common.io,6,,73,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,72,1 -com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, -com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, -com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,, -com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7, -com.unboundid.ldap.sdk,17,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,, -com.zaxxer.hikari,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 -freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, -freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, -groovy.lang,26,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -groovy.util,5,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -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,13,,76,,,,,,,,,,,,8,,,,,,4,,,1,,,,,,,,,,,,,,,,53,23 -java.net,10,3,7,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,3,7, -java.nio,15,,16,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,16, -java.sql,11,,2,,,,,,,,4,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,1,1 -java.util,44,,465,,,,,,,,,,,,34,,,,,,,5,2,,1,2,,,,,,,,,,,,,,38,427 -javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, -javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, -javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 -javax.management.remote,2,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,, -javax.naming,7,,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,,,, -javax.net.ssl,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,, -javax.script,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,, -javax.servlet,4,21,2,,,,,3,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,2, -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.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,, -jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10 -kotlin,12,,1835,,10,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,1828,7 -net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,, -ognl,6,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,, -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.jexl2,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.jexl3,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.lang3,6,,424,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,293,131 -org.apache.commons.logging,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.ognl,6,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52 -org.apache.directory.ldap.client.api,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -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.http,27,3,70,,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,,,2,,,,3,62,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.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, -org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, -org.codehaus.groovy.control,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, -org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, -org.jboss.logging,324,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,, -org.jdbi.v3.core,6,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,, -org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38 -org.mvel2,16,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,,, -org.scijava.log,13,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,,, -org.slf4j,55,,6,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,2,4 -org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30 -org.springframework.boot.jdbc,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13 -org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 -org.springframework.http,14,,70,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,,60,10 -org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,, -org.springframework.jdbc.datasource,4,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,, -org.springframework.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.ldap,47,,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,, -org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32 -org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52 -org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13, -org.springframework.web.client,13,3,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,3,, -org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,, -org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13, -org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,, -org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,25 -org.thymeleaf,2,,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,2, -org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,, -play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,, -ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48 -ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 -ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 -retrofit2,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,, +package,sink,source,summary,sink:bean-validation,sink:create-file,sink:fragment-injection,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:read-file,sink:regex-use,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:set-hostname-verifier,sink:sql,sink:ssti,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-external-storage-dir,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value +android.app,35,,103,,,11,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,18,85 +android.content,24,31,154,,,,,,,16,,,,,,,,,,,,,,,,,,,8,,,,,,,,4,,27,,63,91 +android.database,59,,39,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,39, +android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15 +android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,41,81 +android.support.v4.app,11,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +android.util,6,16,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,16,, +android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,2,, +android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,1, +androidx.core.app,6,,95,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,12,83 +androidx.fragment.app,11,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +androidx.slice,2,5,88,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,5,,27,61 +cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, +com.google.common.base,4,,85,,,,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,,62,23 +com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17 +com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551 +com.google.common.flogger,29,,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,,,,, +com.google.common.io,6,,73,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,72,1 +com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, +com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, +com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,, +com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7, +com.unboundid.ldap.sdk,17,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,, +com.zaxxer.hikari,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 +freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, +freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, +groovy.lang,26,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +groovy.util,5,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +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,13,,76,,,,,,,,,,,,8,,,,,,,4,,,1,,,,,,,,,,,,,,,,53,23 +java.net,10,3,7,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,,3,7, +java.nio,16,,16,,13,,,,,,,,,,,,,,,1,,,,,,,,,,,,,2,,,,,,,,16, +java.sql,11,,2,,,,,,,,4,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,1,1 +java.util,44,,465,,,,,,,,,,,,34,,,,,,,,5,2,,1,2,,,,,,,,,,,,,,38,427 +javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, +javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, +javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 +javax.management.remote,2,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.naming,7,,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.net.ssl,2,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,, +javax.script,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.servlet,4,21,2,,,,,3,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,2, +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.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,, +jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10 +kotlin,12,,1835,,10,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,1828,7 +net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,, +ognl,6,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,, +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.jexl2,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.jexl3,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.lang3,6,,424,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,293,131 +org.apache.commons.logging,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.ognl,6,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52 +org.apache.directory.ldap.client.api,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +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.http,27,3,70,,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,,,,2,,,,3,62,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.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, +org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, +org.codehaus.groovy.control,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, +org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, +org.jboss.logging,324,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.jdbi.v3.core,6,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,, +org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38 +org.mvel2,16,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,,,, +org.scijava.log,13,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.slf4j,55,,6,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,2,4 +org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30 +org.springframework.boot.jdbc,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13 +org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 +org.springframework.http,14,,70,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,,,60,10 +org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,, +org.springframework.jdbc.datasource,4,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,, +org.springframework.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.ldap,47,,,,,,,,,,,,33,14,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,, +org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32 +org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,87,52 +org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13, +org.springframework.web.client,13,3,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,3,, +org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,, +org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13, +org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,, +org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,25 +org.thymeleaf,2,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,2, +org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,, +play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,, +ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48 +ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 +ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35 +retrofit2,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index c4630ca11d6..59c21e3ed29 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -18,10 +18,10 @@ Java framework & library support `Google Guava `_,``com.google.common.*``,,728,39,,6,,,,, JBoss Logging,``org.jboss.logging``,,,324,,,,,,, `JSON-java `_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,609,130,28,,,7,,,10 + Java Standard Library,``java.*``,3,609,131,28,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,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.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,269,,,,14,18,,3 - Totals,,217,8456,1563,129,6,10,107,33,1,86 + Totals,,217,8456,1564,129,6,10,107,33,1,86 diff --git a/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/classes.ql b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/classes.ql new file mode 100644 index 00000000000..82123848cb7 --- /dev/null +++ b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/classes.ql @@ -0,0 +1,11 @@ +class ClassOrInterface extends @classorinterface { + string toString() { result = "class-or-interface" } +} + +class Package extends @package { + string toString() { result = "package" } +} + +from ClassOrInterface id, string nodeName, Package parentId, ClassOrInterface sourceId +where classes_or_interfaces(id, nodeName, parentId, sourceId) and not isInterface(id) +select id, nodeName, parentId, sourceId diff --git a/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/interfaces.ql b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/interfaces.ql new file mode 100644 index 00000000000..83d804fcf80 --- /dev/null +++ b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/interfaces.ql @@ -0,0 +1,11 @@ +class ClassOrInterface extends @classorinterface { + string toString() { result = "class-or-interface" } +} + +class Package extends @package { + string toString() { result = "package" } +} + +from ClassOrInterface id, string nodeName, Package parentId, ClassOrInterface sourceId +where classes_or_interfaces(id, nodeName, parentId, sourceId) and isInterface(id) +select id, nodeName, parentId, sourceId diff --git a/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme new file mode 100644 index 00000000000..934bf10b4bd --- /dev/null +++ b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme @@ -0,0 +1,1242 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme new file mode 100644 index 00000000000..44d61b266be --- /dev/null +++ b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme @@ -0,0 +1,1246 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +file_class( + int id: @class ref +); + +class_object( + unique int id: @class ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @class ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isRecord( + unique int id: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterface = @interface | @class; +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @class | @interface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @class | @interface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @class ref +) diff --git a/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties new file mode 100644 index 00000000000..ad10ae1fc72 --- /dev/null +++ b/java/downgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties @@ -0,0 +1,6 @@ +description: Seperate class and interface tables +compatibility: full +classes.rel: run classes.qlo +interfaces.rel: run interfaces.qlo +isInterface.rel: delete +classes_or_interfaces.rel: delete diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 793d7b15b6f..b93bfa369f5 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -351,18 +351,14 @@ open class KotlinFileExtractor( val pkgId = extractPackage(pkg) // TODO: There's lots of duplication between this and extractClassSource. // Can we share it? + val sourceId = useClassSource(c) + tw.writeClasses_or_interfaces(id, cls, pkgId, sourceId) if (c.isInterfaceLike) { - val interfaceId = id.cast() - val sourceInterfaceId = useClassSource(c).cast() - tw.writeInterfaces(interfaceId, cls, pkgId, sourceInterfaceId) + tw.writeIsInterface(id) } else { - val classId = id.cast() - val sourceClassId = useClassSource(c).cast() - tw.writeClasses(classId, cls, pkgId, sourceClassId) - val kind = c.kind if (kind == ClassKind.ENUM_CLASS) { - tw.writeIsEnumType(classId) + tw.writeIsEnumType(id) } else if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) { logger.errorElement("Unrecognised class kind $kind", c) } @@ -459,11 +455,11 @@ open class KotlinFileExtractor( } private fun extractLocalTypeDeclStmt(c: IrClass, callable: Label, parent: Label, idx: Int) { - val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true).cast() + val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true) extractLocalTypeDeclStmt(id, c, callable, parent, idx) } - private fun extractLocalTypeDeclStmt(id: Label, locElement: IrElement, callable: Label, parent: Label, idx: Int) { + private fun extractLocalTypeDeclStmt(id: Label, locElement: IrElement, callable: Label, parent: Label, idx: Int) { val stmtId = tw.getFreshIdLabel() tw.writeStmts_localtypedeclstmt(stmtId, parent, idx, callable) tw.writeIsLocalClassOrInterface(id, stmtId) @@ -630,26 +626,22 @@ open class KotlinFileExtractor( val pkg = c.packageFqName?.asString() ?: "" val cls = if (c.isAnonymousObject) "" else c.name.asString() val pkgId = extractPackage(pkg) + tw.writeClasses_or_interfaces(id, cls, pkgId, id) if (c.isInterfaceLike) { - val interfaceId = id.cast() - tw.writeInterfaces(interfaceId, cls, pkgId, interfaceId) - + tw.writeIsInterface(id) if (c.kind == ClassKind.ANNOTATION_CLASS) { - tw.writeIsAnnotType(interfaceId) + tw.writeIsAnnotType(id) } } else { - val classId = id.cast() - tw.writeClasses(classId, cls, pkgId, classId) - val kind = c.kind if (kind == ClassKind.ENUM_CLASS) { - tw.writeIsEnumType(classId) + tw.writeIsEnumType(id) } else if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) { logger.warnElement("Unrecognised class kind $kind", c) } if (c.isData) { - tw.writeKtDataClasses(classId) + tw.writeKtDataClasses(id) } } @@ -694,7 +686,7 @@ open class KotlinFileExtractor( tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id) tw.writeHasLocation(instance.id, locId) addModifiers(instance.id, "public", "static", "final") - tw.writeClass_object(id.cast(), instance.id) + tw.writeClass_object(id, instance.id) } if (c.isObject) { addModifiers(id, "static") @@ -830,7 +822,7 @@ open class KotlinFileExtractor( tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id) tw.writeHasLocation(instance.id, innerLocId) addModifiers(instance.id, "public", "static", "final") - tw.writeType_companion_object(parentId, instance.id, innerId.cast()) + tw.writeType_companion_object(parentId, instance.id, innerId) } } @@ -4448,7 +4440,7 @@ open class KotlinFileExtractor( } private open inner class GeneratedClassHelper(protected val locId: Label, protected val ids: GeneratedClassLabels) { - protected val classId = ids.type.javaResult.id.cast() + protected val classId = ids.type.javaResult.id.cast() /** * Extract a parameter to field assignment, such as `this.field = paramName` below: @@ -4788,7 +4780,7 @@ open class KotlinFileExtractor( val locId = tw.getLocation(propertyReferenceExpr) - val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") + val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = GeneratedClassLabels( @@ -4980,7 +4972,7 @@ open class KotlinFileExtractor( val locId = tw.getLocation(functionReferenceExpr) - val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") + val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = LocallyVisibleFunctionLabels( @@ -5550,7 +5542,7 @@ open class KotlinFileExtractor( return } - val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") + val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = LocallyVisibleFunctionLabels( @@ -5659,7 +5651,7 @@ open class KotlinFileExtractor( val idNewexpr = extractNewExpr(ids.constructor, ids.type, locId, id, 1, callable, enclosingStmt) - tw.writeIsAnonymClass(ids.type.javaResult.id.cast(), idNewexpr) + tw.writeIsAnonymClass(ids.type.javaResult.id.cast(), idNewexpr) extractTypeAccessRecursive(e.typeOperand, locId, idNewexpr, -3, callable, enclosingStmt) @@ -5705,11 +5697,11 @@ open class KotlinFileExtractor( compilerGeneratedKindOverride: CompilerGeneratedKinds? = null, superConstructorSelector: (IrFunction) -> Boolean = { it.valueParameters.isEmpty() }, extractSuperconstructorArgs: (Label) -> Unit = {}, - ): Label { + ): Label { // Write class - val id = ids.type.javaResult.id.cast() + val id = ids.type.javaResult.id.cast() val pkgId = extractPackage("") - tw.writeClasses(id, "", pkgId, id) + tw.writeClasses_or_interfaces(id, "", pkgId, id) tw.writeCompiler_generated(id, (compilerGeneratedKindOverride ?: CompilerGeneratedKinds.CALLABLE_CLASS).kind) tw.writeHasLocation(id, locId) @@ -5761,7 +5753,7 @@ open class KotlinFileExtractor( localFunction: IrFunction, superTypes: List, compilerGeneratedKindOverride: CompilerGeneratedKinds? = null - ) : Label { + ) : Label { with("generated class", localFunction) { val ids = getLocallyVisibleFunctionLabels(localFunction) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 92fc961dd0f..c72f094808b 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -71,16 +71,16 @@ open class KotlinUsesExtractor( TypeResult(fakeKotlinType(), "", "") ) - fun extractFileClass(f: IrFile): Label { + fun extractFileClass(f: IrFile): Label { val pkg = f.fqName.asString() val jvmName = getFileClassName(f) val qualClassName = if (pkg.isEmpty()) jvmName else "$pkg.$jvmName" val label = "@\"class;$qualClassName\"" - val id: Label = tw.getLabelFor(label) { + val id: Label = tw.getLabelFor(label) { val fileId = tw.mkFileId(f.path, false) val locId = tw.getWholeFileLocation(fileId) val pkgId = extractPackage(pkg) - tw.writeClasses(it, jvmName, pkgId, it) + tw.writeClasses_or_interfaces(it, jvmName, pkgId, it) tw.writeFile_class(it) tw.writeHasLocation(it, locId) @@ -478,7 +478,7 @@ open class KotlinUsesExtractor( private fun useAnonymousClass(c: IrClass) = tw.lm.anonymousTypeMapping.getOrPut(c) { TypeResults( - TypeResult(tw.getFreshIdLabel(), "", ""), + TypeResult(tw.getFreshIdLabel(), "", ""), TypeResult(fakeKotlinType(), "TODO", "TODO") ) } @@ -487,8 +487,8 @@ open class KotlinUsesExtractor( val fakeKotlinPackageId: Label = tw.getLabelFor("@\"FakeKotlinPackage\"", { tw.writePackages(it, "fake.kotlin") }) - val fakeKotlinClassId: Label = tw.getLabelFor("@\"FakeKotlinClass\"", { - tw.writeClasses(it, "FakeKotlinClass", fakeKotlinPackageId, it) + val fakeKotlinClassId: Label = tw.getLabelFor("@\"FakeKotlinClass\"", { + tw.writeClasses_or_interfaces(it, "FakeKotlinClass", fakeKotlinPackageId, it) }) val fakeKotlinTypeId: Label = tw.getLabelFor("@\"FakeKotlinType\"", { tw.writeKt_nullable_types(it, fakeKotlinClassId) @@ -650,11 +650,11 @@ open class KotlinUsesExtractor( // We use this when we don't actually have an IrClass for a class // we want to refer to // TODO: Eliminate the need for this if possible - fun makeClass(pkgName: String, className: String): Label { + fun makeClass(pkgName: String, className: String): Label { val pkgId = extractPackage(pkgName) val label = "@\"class;$pkgName.$className\"" - val classId: Label = tw.getLabelFor(label, { - tw.writeClasses(it, className, pkgId, it) + val classId: Label = tw.getLabelFor(label, { + tw.writeClasses_or_interfaces(it, className, pkgId, it) }) return classId } @@ -1237,7 +1237,7 @@ open class KotlinUsesExtractor( var res = tw.lm.locallyVisibleFunctionLabelMapping[f] if (res == null) { - val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") + val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) res = LocallyVisibleFunctionLabels( diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/.gitattributes b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/build.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/build.gradle new file mode 100644 index 00000000000..b2708d1ac3d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/build.gradle @@ -0,0 +1,13 @@ +plugins { + + /** + * Use `apply false` in the top-level build.gradle file to add a Gradle + * plugin as a build dependency but not apply it to the current (root) + * project. Don't use `apply false` in sub-projects. For more information, + * see Applying external plugins with same version to subprojects. + */ + + id 'com.android.application' version '7.3.1' apply false + id 'com.android.library' version '7.3.1' apply false + id 'org.jetbrains.kotlin.android' version '1.7.20' apply false +} 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 new file mode 100644 index 00000000000..29e2215412e --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/diagnostics.expected @@ -0,0 +1,28 @@ +{ + "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). Suspicious 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", + "id": "java/autobuilder/android-build-failure", + "name": "Android build failure" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "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). Suspicious 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", + "id": "java/autobuilder/android-build-failure", + "name": "Android build failure" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/force_sequential_test_execution b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/force_sequential_test_execution new file mode 100644 index 00000000000..4947fd6fe51 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/force_sequential_test_execution @@ -0,0 +1,4 @@ +# We currently have a bug where gradle tests become flaky when executed in parallel +# - sometimes, gradle fails to connect to the gradle daemon. +# Therefore, force this test to run sequentially. +# Additionally, Android SDK on-demand downloading can fail when multiple tests try to download the same SDK in parallel. diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..249e5832f09 Binary files /dev/null and b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..e750102e092 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew new file mode 100755 index 00000000000..a69d9cb6c20 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew @@ -0,0 +1,240 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew.bat b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew.bat new file mode 100644 index 00000000000..f127cfd49d4 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/build.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/build.gradle new file mode 100644 index 00000000000..7751b92ae54 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/build.gradle @@ -0,0 +1,58 @@ +/** + * The first line in the build configuration applies the Android Gradle plugin + * to this build and makes the android block available to specify + * Android-specific build options. + */ + +plugins { + id 'com.android.application' +} + +/** + * The android block is where you configure all your Android-specific + * build options. + */ + +android { + + /** + * The app's namespace. Used primarily to access app resources. + */ + + namespace 'com.github.androidsample' + + /** + * compileSdk specifies the Android API level Gradle should use to + * compile your app. This means your app can use the API features included in + * this API level and lower. + */ + + compileSdk 33 + + /** + * The defaultConfig block encapsulates default settings and entries for all + * build variants and can override some attributes in main/AndroidManifest.xml + * dynamically from the build system. You can configure product flavors to override + * these values for different versions of your app. + */ + + defaultConfig { + + // Uniquely identifies the package for publishing. + applicationId 'com.github.androidsample' + + // Defines the minimum API level required to run the app. + minSdk 21 + + // Specifies the API level used to test the app. + targetSdk 33 + + // Defines the version number of your app. + versionCode 1 + + // Defines a user-friendly version name for your app. + versionName "1.0" + } + + variantFilter { variant -> if (variant.buildType.name == "debug") { setIgnore(true) } } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/AndroidManifest.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..1352b0d90fa --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/java/com/github/androidsample/Main.java b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/java/com/github/androidsample/Main.java new file mode 100644 index 00000000000..000b12d036d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/project/src/main/java/com/github/androidsample/Main.java @@ -0,0 +1,11 @@ +package com.github.androidsample; + +import android.app.Activity; +import android.os.Bundle; + +public class Main extends Activity +{ + @Override + public void onCreate(Bundle savedInstanceState) { + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/settings.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/settings.gradle new file mode 100644 index 00000000000..1fa19406e1a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/settings.gradle @@ -0,0 +1,40 @@ +pluginManagement { + + /** + * The pluginManagement {repositories {...}} block configures the + * repositories Gradle uses to search or download the Gradle plugins and + * their transitive dependencies. Gradle pre-configures support for remote + * repositories such as JCenter, Maven Central, and Ivy. You can also use + * local repositories or define your own remote repositories. The code below + * defines the Gradle Plugin Portal, Google's Maven repository, + * and the Maven Central Repository as the repositories Gradle should use to look for its + * dependencies. + */ + + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + + /** + * The dependencyResolutionManagement {repositories {...}} + * block is where you configure the repositories and dependencies used by + * all modules in your project, such as libraries that you are using to + * create your application. However, you should configure module-specific + * dependencies in each module-level build.gradle file. For new projects, + * Android Studio includes Google's Maven repository and the Maven Central + * Repository by default, but it does not configure any dependencies (unless + * you select a template that requires some). + */ + + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "Android Sample" +include ':project' diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() 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 new file mode 100644 index 00000000000..81b15627115 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/diagnostics.expected @@ -0,0 +1,42 @@ +{ + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious output line: `[ERROR] COMPILATION ERROR : `", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/autobuilder/compilation-error", + "name": "Some of your code may have failed to compile" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious 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", + "id": "java/autobuilder/compilation-error", + "name": "Some of your code may have failed to compile" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} +{ + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious 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", + "id": "java/autobuilder/compilation-error", + "name": "Some of your code may have failed to compile" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/pom.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/pom.xml new file mode 100644 index 00000000000..ec4aaf128c1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + com.example + maven-sample + 1.0-SNAPSHOT + + maven-sample + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit + 4.11 + test + + + + + + + exec-maven-plugin + org.codehaus.mojo + 1.1.1 + + + check-maven-version + package + + java + + + + + com.example.App + + + + com.diffplug.spotless + spotless-maven-plugin + 2.19.1 + + + + check + + compile + + + + + + /* FAIL ME */ + + + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + \ No newline at end of file diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/java/com/example/App.java new file mode 100644 index 00000000000..175dc00f5ee --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/java/com/example/App.java @@ -0,0 +1,30 @@ +paaaaaaaaaaaaaaaackage com.example; + +import java.util.regex.Pattern; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + String expectedVersion = System.getenv("EXPECT_MAVEN"); + Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize(); + String observedVersion = mavenHome.getFileName().toString(); + if (expectedVersion != null && !expectedVersion.equals(observedVersion)) { + System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome); + System.exit(1); + } + String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX"); + String command = System.getProperty("sun.java.command"); + if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) { + System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'"); + System.exit(1); + } + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/my-app.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/my-app.properties new file mode 100644 index 00000000000..e566b49a29a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/my-app.properties @@ -0,0 +1 @@ +version=1.0 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/page.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/page.xml new file mode 100644 index 00000000000..2bab459cb03 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/page.xml @@ -0,0 +1,8 @@ + + +A sample + + +

Hello world!

+ + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/struts.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/struts.xml new file mode 100644 index 00000000000..73fc0c6b9cb --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/main/resources/struts.xml @@ -0,0 +1,4 @@ + + +This is a sample file + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..22a94ca6f01 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/src/test/java/com/example/AppTest.java @@ -0,0 +1,20 @@ +package com.example; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() 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 new file mode 100644 index 00000000000..21fa19216be --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "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). Suspicious 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", + "id": "java/autobuilder/dependency-download-failure", + "name": "Failed to download a dependency" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/pom.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/pom.xml new file mode 100644 index 00000000000..b5e230d9d56 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + com.example + maven-sample + 1.0-SNAPSHOT + + maven-sample + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit-nonesuch + 4.11 + test + + + + + + + exec-maven-plugin + org.codehaus.mojo + 1.1.1 + + + check-maven-version + package + + java + + + + + com.example.App + + + + com.diffplug.spotless + spotless-maven-plugin + 2.19.1 + + + + check + + compile + + + + + + /* FAIL ME */ + + + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/java/com/example/App.java new file mode 100644 index 00000000000..c9eec918587 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/java/com/example/App.java @@ -0,0 +1,30 @@ +package com.example; + +import java.util.regex.Pattern; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + String expectedVersion = System.getenv("EXPECT_MAVEN"); + Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize(); + String observedVersion = mavenHome.getFileName().toString(); + if (expectedVersion != null && !expectedVersion.equals(observedVersion)) { + System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome); + System.exit(1); + } + String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX"); + String command = System.getProperty("sun.java.command"); + if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) { + System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'"); + System.exit(1); + } + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/my-app.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/my-app.properties new file mode 100644 index 00000000000..e566b49a29a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/my-app.properties @@ -0,0 +1 @@ +version=1.0 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/page.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/page.xml new file mode 100644 index 00000000000..2bab459cb03 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/page.xml @@ -0,0 +1,8 @@ + + +A sample + + +

Hello world!

+ + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/struts.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/struts.xml new file mode 100644 index 00000000000..73fc0c6b9cb --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/main/resources/struts.xml @@ -0,0 +1,4 @@ + + +This is a sample file + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..22a94ca6f01 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/src/test/java/com/example/AppTest.java @@ -0,0 +1,20 @@ +package com.example; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/test.py new file mode 100644 index 00000000000..ee07cd14bdf --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/test.py @@ -0,0 +1,16 @@ +import os +import pathlib +import shutil + +from create_database_utils import * +from diagnostics_test_utils import * + +# Ensure the intended dependency download failure is not cached: +try: + shutil.rmtree(pathlib.Path.home().joinpath(".m2", "repository", "junit", "junit-nonesuch")) +except FileNotFoundError: + pass + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitattributes b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitignore b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitignore new file mode 100644 index 00000000000..1b6985c0094 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/build.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/build.gradle new file mode 100644 index 00000000000..c3b774e3d50 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/build.gradle @@ -0,0 +1,34 @@ +/* + * This build file was auto generated by running the Gradle 'init' task + * by 'arthur' at '28/11/20 22:29' with Gradle 3.0 + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * user guide available at https://docs.gradle.org/3.0/userguide/tutorial_java_projects.html + */ + +// Apply the java plugin to add support for Java +apply plugin: 'java' + +// In this section you declare where to find the dependencies of your project +repositories { + // Use 'jcenter' for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + jcenter() +} + +// In this section you declare the dependencies for your production and test code +dependencies { + // The production code uses the SLF4J logging API at compile time + compile 'org.slf4j:slf4j-api:1.7.21' + + // Declare the dependency for your favourite test framework you want to use in your tests. + // TestNG is also supported by the Gradle Test task. Just change the + // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add + // 'test.useTestNG()' to your build script. + testCompile 'junit:junit:4.12' +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 +} 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 new file mode 100644 index 00000000000..a48a1e1dd07 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/diagnostics.expected @@ -0,0 +1,28 @@ +{ + "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). Suspicious output line: `> Could not target platform: 'Java SE 11' using tool chain: 'JDK 8 (1.8)'.`", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/autobuilder/wrong-jdk-version", + "name": "Your project may need a different JDK version" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "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). Suspicious 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", + "id": "java/autobuilder/wrong-jdk-version", + "name": "Your project may need a different JDK version" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/force_sequential_test_execution b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/force_sequential_test_execution new file mode 100644 index 00000000000..b0e2500b259 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/force_sequential_test_execution @@ -0,0 +1,3 @@ +# We currently have a bug where gradle tests become flaky when executed in parallel +# - sometimes, gradle fails to connect to the gradle daemon. +# Therefore, force this test to run sequentially. diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/verification-metadata.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/verification-metadata.xml new file mode 100644 index 00000000000..14a69b8178b --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/verification-metadata.xml @@ -0,0 +1,7 @@ + + + + true + false + + \ No newline at end of file diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..12d38de6a48 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew.bat b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew.bat new file mode 100644 index 00000000000..107acd32c4e --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/settings.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/settings.gradle new file mode 100644 index 00000000000..233410459f6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'arthur' at '28/11/20 22:29' with Gradle 3.0 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/3.0/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'gradle-sample' diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/main/java/com/example/App.java new file mode 100644 index 00000000000..1c13f7d885e --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/main/java/com/example/App.java @@ -0,0 +1,14 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package com.example; + +public class App { + public String getGreeting() { + return "Hello world."; + } + + public static void main(String[] args) { + System.out.println(new App().getGreeting()); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..813bc5e1a2a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/src/test/java/com/example/AppTest.java @@ -0,0 +1,14 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package com.example; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class AppTest { + @Test public void testAppHasAGreeting() { + App classUnderTest = new App(); + assertNotNull("app should have a greeting", classUnderTest.getGreeting()); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py new file mode 100644 index 00000000000..9def03947b3 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py @@ -0,0 +1,13 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +# Ensure we're using an old Java version that won't work with Gradle +if "JAVA_HOME_8_X64" in os.environ: + os.environ["JAVA_HOME"] = os.environ["JAVA_HOME_8_X64"] + sep = ";" if platform.system() == "Windows" else ":" + os.environ["PATH"] = "".join([os.path.join(os.environ["JAVA_HOME"], "bin"), sep, os.environ["PATH"]]) + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() 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 new file mode 100644 index 00000000000..56c315303c1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/diagnostics.expected @@ -0,0 +1,56 @@ +{ + "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). Suspicious 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" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} +{ + "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). Suspicious 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" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} +{ + "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). Suspicious 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" + }, + "visibility": { + "cliSummaryTable": false, + "statusPage": false, + "telemetry": true + } +} +{ + "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). Suspicious 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" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/pom.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/pom.xml new file mode 100644 index 00000000000..a1ae8eda7e6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + com.example + maven-sample + 1.0-SNAPSHOT + + maven-sample + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + insecure + Insecure HTTP Repository + http://repo.maven.apache.org/maven2/ + default + + + + + + junit-nonesuch + junit-nonesuch + 4.11 + test + + + + + + + exec-maven-plugin + org.codehaus.mojo + 1.1.1 + + + check-maven-version + package + + java + + + + + com.example.App + + + + com.diffplug.spotless + spotless-maven-plugin + 2.19.1 + + + + check + + compile + + + + + + /* FAIL ME */ + + + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/java/com/example/App.java new file mode 100644 index 00000000000..c9eec918587 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/java/com/example/App.java @@ -0,0 +1,30 @@ +package com.example; + +import java.util.regex.Pattern; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + String expectedVersion = System.getenv("EXPECT_MAVEN"); + Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize(); + String observedVersion = mavenHome.getFileName().toString(); + if (expectedVersion != null && !expectedVersion.equals(observedVersion)) { + System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome); + System.exit(1); + } + String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX"); + String command = System.getProperty("sun.java.command"); + if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) { + System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'"); + System.exit(1); + } + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/my-app.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/my-app.properties new file mode 100644 index 00000000000..e566b49a29a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/my-app.properties @@ -0,0 +1 @@ +version=1.0 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/page.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/page.xml new file mode 100644 index 00000000000..2bab459cb03 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/page.xml @@ -0,0 +1,8 @@ + + +A sample + + +

Hello world!

+ + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/struts.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/struts.xml new file mode 100644 index 00000000000..73fc0c6b9cb --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/main/resources/struts.xml @@ -0,0 +1,4 @@ + + +This is a sample file + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..22a94ca6f01 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/src/test/java/com/example/AppTest.java @@ -0,0 +1,20 @@ +package com.example; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() 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 new file mode 100644 index 00000000000..07c5d942baa --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/diagnostics.expected @@ -0,0 +1,28 @@ +{ + "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)", + "severity": "warning", + "source": { + "extractorName": "java", + "id": "java/autobuilder/multiple-candidate-build-directories", + "name": "Multiple candidate Maven build directories" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "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)", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/autobuilder/multiple-candidate-build-directories-fatal", + "name": "No build system could identify a unique top-level project" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/pom.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/pom.xml new file mode 100644 index 00000000000..ec4aaf128c1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + com.example + maven-sample + 1.0-SNAPSHOT + + maven-sample + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit + 4.11 + test + + + + + + + exec-maven-plugin + org.codehaus.mojo + 1.1.1 + + + check-maven-version + package + + java + + + + + com.example.App + + + + com.diffplug.spotless + spotless-maven-plugin + 2.19.1 + + + + check + + compile + + + + + + /* FAIL ME */ + + + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + \ No newline at end of file diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/java/com/example/App.java new file mode 100644 index 00000000000..c9eec918587 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/java/com/example/App.java @@ -0,0 +1,30 @@ +package com.example; + +import java.util.regex.Pattern; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + String expectedVersion = System.getenv("EXPECT_MAVEN"); + Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize(); + String observedVersion = mavenHome.getFileName().toString(); + if (expectedVersion != null && !expectedVersion.equals(observedVersion)) { + System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome); + System.exit(1); + } + String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX"); + String command = System.getProperty("sun.java.command"); + if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) { + System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'"); + System.exit(1); + } + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/my-app.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/my-app.properties new file mode 100644 index 00000000000..e566b49a29a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/my-app.properties @@ -0,0 +1 @@ +version=1.0 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/page.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/page.xml new file mode 100644 index 00000000000..2bab459cb03 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/page.xml @@ -0,0 +1,8 @@ + + +A sample + + +

Hello world!

+ + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/struts.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/struts.xml new file mode 100644 index 00000000000..73fc0c6b9cb --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/main/resources/struts.xml @@ -0,0 +1,4 @@ + + +This is a sample file + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..22a94ca6f01 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-1/src/test/java/com/example/AppTest.java @@ -0,0 +1,20 @@ +package com.example; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/pom.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/pom.xml new file mode 100644 index 00000000000..ec4aaf128c1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + com.example + maven-sample + 1.0-SNAPSHOT + + maven-sample + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit + 4.11 + test + + + + + + + exec-maven-plugin + org.codehaus.mojo + 1.1.1 + + + check-maven-version + package + + java + + + + + com.example.App + + + + com.diffplug.spotless + spotless-maven-plugin + 2.19.1 + + + + check + + compile + + + + + + /* FAIL ME */ + + + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + \ No newline at end of file diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/java/com/example/App.java new file mode 100644 index 00000000000..c9eec918587 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/java/com/example/App.java @@ -0,0 +1,30 @@ +package com.example; + +import java.util.regex.Pattern; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + String expectedVersion = System.getenv("EXPECT_MAVEN"); + Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize(); + String observedVersion = mavenHome.getFileName().toString(); + if (expectedVersion != null && !expectedVersion.equals(observedVersion)) { + System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome); + System.exit(1); + } + String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX"); + String command = System.getProperty("sun.java.command"); + if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) { + System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'"); + System.exit(1); + } + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/my-app.properties b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/my-app.properties new file mode 100644 index 00000000000..e566b49a29a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/my-app.properties @@ -0,0 +1 @@ +version=1.0 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/page.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/page.xml new file mode 100644 index 00000000000..2bab459cb03 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/page.xml @@ -0,0 +1,8 @@ + + +A sample + + +

Hello world!

+ + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/struts.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/struts.xml new file mode 100644 index 00000000000..73fc0c6b9cb --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/main/resources/struts.xml @@ -0,0 +1,4 @@ + + +This is a sample file + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..22a94ca6f01 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/maven-project-2/src/test/java/com/example/AppTest.java @@ -0,0 +1,20 @@ +package com.example; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/Test.java b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/Test.java new file mode 100644 index 00000000000..ef22a69f193 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/Test.java @@ -0,0 +1 @@ +class Test {} 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 new file mode 100644 index 00000000000..e7a8e2ed10d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "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)", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/autobuilder/no-build-command", + "name": "No build command found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/build.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/build.gradle new file mode 100644 index 00000000000..8591a5fdd8d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/build.gradle @@ -0,0 +1,3 @@ +task clean { + println 'Clean task executed' +} 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 new file mode 100644 index 00000000000..c5d896da5be --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/diagnostics.expected @@ -0,0 +1,28 @@ +{ + "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", + "id": "java/autobuilder/guessed-gradle-version", + "name": "Required Gradle version not specified" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "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. Suspicious output line: `org.gradle.execution.TaskSelectionException: Task 'testClasses' not found in root project 'no-gradle-test-classes'.`", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/autobuilder/test-classes-gradle-target", + "name": "Gradle target 'testClasses' not found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/settings.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/settings.gradle new file mode 100644 index 00000000000..a6635527945 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/settings.gradle @@ -0,0 +1 @@ +// Empty project, which doesn't have a testClasses goal. diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitattributes b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitignore b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitignore new file mode 100644 index 00000000000..1b6985c0094 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/build.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/build.gradle new file mode 100644 index 00000000000..071a12b7691 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/build.gradle @@ -0,0 +1,30 @@ +/* + * This build file was auto generated by running the Gradle 'init' task + * by 'arthur' at '28/11/20 22:29' with Gradle 3.0 + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * user guide available at https://docs.gradle.org/3.0/userguide/tutorial_java_projects.html + */ + +// Apply the java plugin to add support for Java +apply plugin: 'java' + +// In this section you declare where to find the dependencies of your project +repositories { + // Use 'jcenter' for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + jcenter() +} + +// In this section you declare the dependencies for your production and test code +dependencies { + // The production code uses the SLF4J logging API at compile time + compile 'org.slf4j:slf4j-api:1.7.21' + + // Declare the dependency for your favourite test framework you want to use in your tests. + // TestNG is also supported by the Gradle Test task. Just change the + // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add + // 'test.useTestNG()' to your build script. + testCompile 'junit:junit:4.12' +} 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 new file mode 100644 index 00000000000..ad5c5bdb7c6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "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", + "id": "java/autobuilder/guessed-gradle-version", + "name": "Required Gradle version not specified" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/force_sequential_test_execution b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/force_sequential_test_execution new file mode 100644 index 00000000000..b0e2500b259 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/force_sequential_test_execution @@ -0,0 +1,3 @@ +# We currently have a bug where gradle tests become flaky when executed in parallel +# - sometimes, gradle fails to connect to the gradle daemon. +# Therefore, force this test to run sequentially. diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/settings.gradle b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/settings.gradle new file mode 100644 index 00000000000..233410459f6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'arthur' at '28/11/20 22:29' with Gradle 3.0 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/3.0/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'gradle-sample' diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/main/java/com/example/App.java b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/main/java/com/example/App.java new file mode 100644 index 00000000000..1c13f7d885e --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/main/java/com/example/App.java @@ -0,0 +1,14 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package com.example; + +public class App { + public String getGreeting() { + return "Hello world."; + } + + public static void main(String[] args) { + System.out.println(new App().getGreeting()); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/test/java/com/example/AppTest.java b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/test/java/com/example/AppTest.java new file mode 100644 index 00000000000..813bc5e1a2a --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/src/test/java/com/example/AppTest.java @@ -0,0 +1,14 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package com.example; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class AppTest { + @Test public void testAppHasAGreeting() { + App classUnderTest = new App(); + assertNotNull("app should have a greeting", classUnderTest.getGreeting()); + } +} diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/test.py new file mode 100644 index 00000000000..23fe1d32fd8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/.gitattributes b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..ccebba7710d Binary files /dev/null and b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..f398c33c4b0 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew new file mode 100755 index 00000000000..79a61d421cc --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew.bat b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew.bat new file mode 100644 index 00000000000..93e3f59f135 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/test.py b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/test.py index c1ba4d3370b..359771ac6c0 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/compiler_arguments/test.py @@ -1,5 +1,7 @@ +import platform from create_database_utils import * +gradle_cmd = "gradlew.bat" if platform.system() == "Windows" else "./gradlew" + run_codeql_database_create( - ["gradle build --no-daemon --no-build-cache"], lang="java") -runSuccessfully([get_cmd("gradle"), "clean"]) + ["%s build --no-daemon --no-build-cache" % gradle_cmd], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/diagnostics.expected b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/diagnostics.expected new file mode 100644 index 00000000000..3494b6a6f7d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 1.8.30", + "severity": "error", + "source": { + "extractorName": "java", + "id": "java/extractor-agent/kotlin-version-too-new", + "name": "Android build failure" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/mock/MockProject.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/mock/MockProject.java new file mode 100644 index 00000000000..75eaf862803 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/mock/MockProject.java @@ -0,0 +1,3 @@ +package com.intellij.mock; + +public class MockProject { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/openapi/Disposable.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/openapi/Disposable.java new file mode 100644 index 00000000000..c4c7538d732 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/com/intellij/openapi/Disposable.java @@ -0,0 +1,3 @@ +package com.intellij.openapi; + +public class Disposable { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/driver/Main.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/driver/Main.java new file mode 100644 index 00000000000..8a2c7b74ed7 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/driver/Main.java @@ -0,0 +1,20 @@ +package driver; + +import java.util.ArrayList; +import java.util.List; +import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments; +import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt; +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; + +public class Main { + + public static void main(String[] args) { + + List compilerArgs = new ArrayList(); + K2JVMCompilerArguments parsedArgs = new K2JVMCompilerArguments(); + (new ParseCommandLineArgumentsKt()).parseCommandLineArguments(compilerArgs, parsedArgs); + (new K2JVMCompiler()).doExecute(parsedArgs, null, null, null); + + } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/kotlin/KotlinVersion.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/kotlin/KotlinVersion.java new file mode 100644 index 00000000000..e4bd4ecb7e1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/kotlin/KotlinVersion.java @@ -0,0 +1,7 @@ +package kotlin; + +public class KotlinVersion { + + public static String CURRENT = "999.999.999"; + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/ExitCode.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/ExitCode.java new file mode 100644 index 00000000000..017c62b8d12 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/ExitCode.java @@ -0,0 +1,3 @@ +package org.jetbrains.kotlin.cli.common; + +public class ExitCode { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/CommonToolArguments.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/CommonToolArguments.java new file mode 100644 index 00000000000..fda9bc15320 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/CommonToolArguments.java @@ -0,0 +1,3 @@ +package org.jetbrains.kotlin.cli.common.arguments; + +class CommonToolArguments { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java new file mode 100644 index 00000000000..68a08768490 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java @@ -0,0 +1,3 @@ +package org.jetbrains.kotlin.cli.common.arguments; + +public class K2JVMCompilerArguments extends CommonToolArguments { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/ParseCommandLineArgumentsKt.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/ParseCommandLineArgumentsKt.java new file mode 100644 index 00000000000..3aa2a64dcee --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/common/arguments/ParseCommandLineArgumentsKt.java @@ -0,0 +1,7 @@ +package org.jetbrains.kotlin.cli.common.arguments; + +public class ParseCommandLineArgumentsKt { + + public void parseCommandLineArguments(java.util.List p0, org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments p1) { } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.java new file mode 100644 index 00000000000..4ac8813e1d6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.java @@ -0,0 +1,9 @@ +package org.jetbrains.kotlin.cli.jvm; + +public class K2JVMCompiler { + + public org.jetbrains.kotlin.cli.common.ExitCode doExecute(org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments p0, org.jetbrains.kotlin.config.CompilerConfiguration p1, com.intellij.openapi.Disposable p2, org.jetbrains.kotlin.utils.KotlinPaths p3) { + return null; + } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/config/CompilerConfiguration.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/config/CompilerConfiguration.java new file mode 100644 index 00000000000..36bbae2044d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/config/CompilerConfiguration.java @@ -0,0 +1,3 @@ +package org.jetbrains.kotlin.config; + +public class CompilerConfiguration { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/utils/KotlinPaths.java b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/utils/KotlinPaths.java new file mode 100644 index 00000000000..82babe67d77 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/fake-kotlinc-source/org/jetbrains/kotlin/utils/KotlinPaths.java @@ -0,0 +1,3 @@ +package org.jetbrains.kotlin.utils; + +public class KotlinPaths { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/test.py b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/test.py new file mode 100644 index 00000000000..484ea6c0486 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/diagnostics/kotlin-version-too-new/test.py @@ -0,0 +1,11 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +import glob +import os.path + +os.mkdir('fake-kotlinc-classes') +runSuccessfully(["javac"] + [os.path.relpath(x, "fake-kotlinc-source") for x in glob.glob("fake-kotlinc-source/**/*.java", recursive = True)] + ["-d", "../fake-kotlinc-classes"], cwd = "fake-kotlinc-source") +run_codeql_database_create(["java -cp fake-kotlinc-classes driver.Main"], lang = "java", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/.gitattributes b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..ccebba7710d Binary files /dev/null and b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..f398c33c4b0 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew new file mode 100755 index 00000000000..79a61d421cc --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew.bat b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew.bat new file mode 100644 index 00000000000..93e3f59f135 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/test.py b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/test.py index 25737233d4a..359771ac6c0 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_groovy_app/test.py @@ -1,4 +1,7 @@ +import platform from create_database_utils import * -run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java") -runSuccessfully([get_cmd("gradle"), "clean"]) +gradle_cmd = "gradlew.bat" if platform.system() == "Windows" else "./gradlew" + +run_codeql_database_create( + ["%s build --no-daemon --no-build-cache" % gradle_cmd], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/.gitattributes b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..ccebba7710d Binary files /dev/null and b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..f398c33c4b0 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew new file mode 100755 index 00000000000..79a61d421cc --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew.bat b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew.bat new file mode 100644 index 00000000000..93e3f59f135 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/test.py b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/test.py index 25737233d4a..359771ac6c0 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/test.py @@ -1,4 +1,7 @@ +import platform from create_database_utils import * -run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java") -runSuccessfully([get_cmd("gradle"), "clean"]) +gradle_cmd = "gradlew.bat" if platform.system() == "Windows" else "./gradlew" + +run_codeql_database_create( + ["%s build --no-daemon --no-build-cache" % gradle_cmd], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/.gitattributes b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/.gitattributes new file mode 100644 index 00000000000..00a51aff5e5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.jar b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..ccebba7710d Binary files /dev/null and b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.properties b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..f398c33c4b0 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew new file mode 100755 index 00000000000..79a61d421cc --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew.bat b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew.bat new file mode 100644 index 00000000000..93e3f59f135 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/test.py b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/test.py index 0f2facdec07..359771ac6c0 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/kotlin_kfunction/test.py @@ -1,5 +1,7 @@ +import platform from create_database_utils import * +gradle_cmd = "gradlew.bat" if platform.system() == "Windows" else "./gradlew" + run_codeql_database_create( - ["gradle build --no-daemon --no-build-cache --rerun-tasks"], lang="java") -runSuccessfully([get_cmd("gradle"), "clean"]) + ["%s build --no-daemon --no-build-cache" % gradle_cmd], lang="java") diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index 1aa4de9efe6..a7710c105fd 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.5.3 + +### New Features + +* Kotlin versions up to 1.8.20 are now supported. + +### Minor Analysis Improvements + +* Removed the first argument of `java.nio.file.Files#createTempDirectory(String,FileAttribute[])` as a "create-file" sink. +* Added the first argument of `java.nio.file.Files#copy` as a "read-file" sink for the `java/path-injection` query. +* The data flow library now disregards flow through code that is dead based on some basic constant propagation, for example, guards like `if (1+1>3)`. + ## 0.5.2 ### Minor Analysis Improvements diff --git a/java/ql/lib/change-notes/2023-02-06-dataflow-deadcode.md b/java/ql/lib/change-notes/2023-02-06-dataflow-deadcode.md deleted file mode 100644 index d802e802a18..00000000000 --- a/java/ql/lib/change-notes/2023-02-06-dataflow-deadcode.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The data flow library now disregards flow through code that is dead based on some basic constant propagation, for example, guards like `if (1+1>3)`. diff --git a/java/ql/lib/change-notes/2023-02-08-kotlin-1.8.20.md b/java/ql/lib/change-notes/2023-02-08-kotlin-1.8.20.md deleted file mode 100644 index f328dd7f05f..00000000000 --- a/java/ql/lib/change-notes/2023-02-08-kotlin-1.8.20.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: feature ---- -* Kotlin versions up to 1.8.20 are now supported. 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 new file mode 100644 index 00000000000..63fbb5647c1 --- /dev/null +++ b/java/ql/lib/change-notes/2023-02-15-mssql-jdbc-hardcoded-credential-api.md @@ -0,0 +1,4 @@ +--- +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-jdk20.md b/java/ql/lib/change-notes/2023-02-17-jdk20.md new file mode 100644 index 00000000000..a2f674cc275 --- /dev/null +++ b/java/ql/lib/change-notes/2023-02-17-jdk20.md @@ -0,0 +1,4 @@ +--- +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/released/0.5.3.md b/java/ql/lib/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..e16561a850d --- /dev/null +++ b/java/ql/lib/change-notes/released/0.5.3.md @@ -0,0 +1,11 @@ +## 0.5.3 + +### New Features + +* Kotlin versions up to 1.8.20 are now supported. + +### Minor Analysis Improvements + +* Removed the first argument of `java.nio.file.Files#createTempDirectory(String,FileAttribute[])` as a "create-file" sink. +* Added the first argument of `java.nio.file.Files#copy` as a "read-file" sink for the `java/path-injection` query. +* The data flow library now disregards flow through code that is dead based on some basic constant propagation, for example, guards like `if (1+1>3)`. diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index 44d61b266be..934bf10b4bd 100644 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -346,26 +346,26 @@ error_type( unique int id: @errortype ); -classes( - unique int id: @class, +classes_or_interfaces( + unique int id: @classorinterface, string nodeName: string ref, int parentid: @package ref, - int sourceid: @class ref + int sourceid: @classorinterface ref ); file_class( - int id: @class ref + int id: @classorinterface ref ); class_object( - unique int id: @class ref, + unique int id: @classorinterface ref, unique int instance: @field ref ); type_companion_object( unique int id: @classorinterface ref, unique int instance: @field ref, - unique int companion_object: @class ref + unique int companion_object: @classorinterface ref ); kt_nullable_types( @@ -386,15 +386,12 @@ kt_type_alias( @kt_type = @kt_nullable_type | @kt_notnull_type -isRecord( - unique int id: @class ref +isInterface( + unique int id: @classorinterface ref ); -interfaces( - unique int id: @interface, - string nodeName: string ref, - int parentid: @package ref, - int sourceid: @interface ref +isRecord( + unique int id: @classorinterface ref ); fielddecls( @@ -480,7 +477,7 @@ exceptions( ); isAnnotType( - int interfaceid: @interface ref + int interfaceid: @classorinterface ref ); isAnnotElem( @@ -494,7 +491,7 @@ annotValue( ); isEnumType( - int classid: @class ref + int classid: @classorinterface ref ); isEnumConst( @@ -546,7 +543,7 @@ erasure( #keyset[classid] #keyset[parent] isAnonymClass( - int classid: @class ref, + int classid: @classorinterface ref, int parent: @classinstancexpr ref ); @@ -586,7 +583,7 @@ extendsReftype( implInterface( int id1: @classorarray ref, - int id2: @interface ref + int id2: @classorinterface ref ); permits( @@ -868,7 +865,7 @@ propertyRefSetBinding( int setter: @callable ref ); -@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; variableBinding( unique int expr: @varaccess ref, @@ -1022,12 +1019,11 @@ javadocText( @javadocParent = @javadoc | @javadocTag; @javadocElement = @javadocTag | @javadocText; -@classorinterface = @interface | @class; @classorinterfaceorpackage = @classorinterface | @package; @classorinterfaceorcallable = @classorinterface | @callable; @boundedtype = @typevariable | @wildcard; @reftype = @classorinterface | @array | @boundedtype | @errortype; -@classorarray = @class | @array; +@classorarray = @classorinterface | @array; @type = @primitive | @reftype; @callable = @method | @constructor; @@ -1035,13 +1031,13 @@ javadocText( @element = @package | @modifier | @annotation | @errortype | @locatableElement; -@locatableElement = @file | @primitive | @class | @interface | @method | @constructor | @param | @exception | @field | +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | @kt_property; @modifiable = @member_modifiable| @param | @localvar | @typevariable; -@member_modifiable = @class | @interface | @method | @constructor | @field | @kt_property; +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; @member = @method | @constructor | @field | @reftype ; @@ -1242,5 +1238,5 @@ ktFunctionOriginalNames( ) ktDataClasses( - unique int id: @class ref + unique int id: @classorinterface ref ) diff --git a/java/ql/lib/config/semmlecode.dbscheme.stats b/java/ql/lib/config/semmlecode.dbscheme.stats index 7ebc6e0b93e..05a477fec73 100644 --- a/java/ql/lib/config/semmlecode.dbscheme.stats +++ b/java/ql/lib/config/semmlecode.dbscheme.stats @@ -6,11 +6,11 @@ @kotlincompilation - 7683 + 2356 @diagnostic - 61632 + 64190 @externalDataElement @@ -26,71 +26,67 @@ @file - 9158642 + 1291911 @folder - 1415670 - - - @location_default - 602747369 + 293711 @package - 580098 + 121135 @primitive - 17287 + 5690 @modifier - 26891 + 6259 @errortype - 1 + 22 - @class - 12618104 + @classorinterface + 22273131 @kt_nullable_type - 1920 + 262 @kt_notnull_type - 172391 + 156265 @kt_type_alias - 1821 - - - @interface - 23200100 + 707 @fielddecl - 199475 + 210035 + + + @location_default + 82315299 @field - 19350704 + 2886451 @constructor - 8006128 + 1103682 @method - 109719302 + 15113893 @param - 120852585 + 16587479 @exception @@ -98,27 +94,27 @@ @typevariable - 6288883 + 864332 @wildcard - 3338447 + 458250 @typebound - 4229725 + 581989 @array - 1375332 + 190588 @import - 368550 + 441072 @block - 756817 + 707376 @ifstmt @@ -130,7 +126,7 @@ @enhancedforstmt - 18520 + 23697 @whilestmt @@ -138,7 +134,7 @@ @dostmt - 2405 + 2251 @trystmt @@ -150,11 +146,11 @@ @synchronizedstmt - 18206 + 23121 @returnstmt - 532846 + 345813 @throwstmt @@ -166,7 +162,7 @@ @continuestmt - 3211 + 3257 @emptystmt @@ -178,7 +174,7 @@ @assertstmt - 10815 + 15159 @localvariabledeclstmt @@ -186,7 +182,7 @@ @localtypedeclstmt - 3841 + 3533 @constructorinvocationstmt @@ -194,7 +190,7 @@ @superconstructorinvocationstmt - 201354 + 182518 @case @@ -206,7 +202,7 @@ @labeledstmt - 2342 + 4493 @yieldstmt @@ -218,7 +214,7 @@ @whenbranch - 225101 + 207293 @arrayaccess @@ -290,7 +286,7 @@ @nullliteral - 434113 + 355806 @mulexpr @@ -322,15 +318,15 @@ @urshiftexpr - 5463 + 9644 @andbitexpr - 110212 + 29089 @orbitexpr - 12590 + 11594 @xorbitexpr @@ -362,7 +358,7 @@ @eqexpr - 128429 + 104275 @neexpr @@ -370,7 +366,7 @@ @postincexpr - 29632 + 41859 @postdecexpr @@ -422,15 +418,15 @@ @typeliteral - 144350 + 98504 @thisaccess - 756915 + 490120 @superaccess - 99884 + 53024 @varaccess @@ -442,7 +438,7 @@ @unannotatedtypeaccess - 2608638 + 2374849 @arraytypeaccess @@ -450,7 +446,7 @@ @wildcardtypeaccess - 64091 + 74889 @declannotation @@ -458,7 +454,7 @@ @assignremexpr - 47 + 62 @assignxorexpr @@ -486,11 +482,11 @@ @uniontypeaccess - 917 + 1010 @lambdaexpr - 167982 + 152268 @memberref @@ -518,43 +514,43 @@ @whenexpr - 152111 + 116200 @getclassexpr - 1920 + 733 @safecastexpr - 6402 + 6086 @implicitcastexpr - 30316 + 28818 @implicitnotnullexpr - 216630 + 163412 @implicitcoerciontounitexpr - 81396 + 73781 @notinstanceofexpr - 17306 + 3981 @stmtexpr - 55704 + 50553 @stringtemplateexpr - 59546 + 24879 @notnullexpr - 18820 + 23342 @unsafecoerceexpr @@ -562,15 +558,15 @@ @valueeqexpr - 93060 + 85697 @valueneexpr - 95639 + 22980 @propertyref - 8878 + 8440 @localvar @@ -582,7 +578,7 @@ @requires - 1991 + 3190 @exports @@ -618,23 +614,23 @@ @xmlelement - 150282022 + 20510401 @xmlattribute - 182798274 + 24948200 @xmlnamespace - 11525 + 2845 @xmlcomment - 151257816 + 20643577 @xmlcharacters - 142938589 + 19508174 @config @@ -650,15 +646,15 @@ @ktcomment - 188243 + 74439 @ktcommentsection - 52611 + 47690 @kt_property - 21895839 + 2989117 @@ -880,30 +876,30 @@ compilation_started - 7683 + 2261 id - 7683 + 2261 compilation_info - 15366 + 4523 id - 7683 + 2261 info_key - 3841 + 188 info_value - 3841 + 188 @@ -917,7 +913,7 @@ 2 3 - 7683 + 2261 @@ -933,7 +929,7 @@ 2 3 - 7683 + 2261 @@ -947,9 +943,9 @@ 12 - 4 - 5 - 3841 + 24 + 25 + 188 @@ -965,7 +961,7 @@ 1 2 - 3841 + 188 @@ -979,9 +975,9 @@ 12 - 4 - 5 - 3841 + 24 + 25 + 188 @@ -997,7 +993,7 @@ 1 2 - 3841 + 188 @@ -1007,19 +1003,19 @@ compilation_args - 169035 + 69266 id - 7683 + 2356 num - 48021 + 12062 arg - 90280 + 35151 @@ -1030,20 +1026,45 @@ 12 + + 19 + 20 + 565 + 20 21 - 3841 + 753 - 23 - 24 - 1920 + 21 + 22 + 188 - 25 - 26 - 1920 + 22 + 25 + 188 + + + 32 + 33 + 188 + + + 34 + 43 + 188 + + + 52 + 54 + 188 + + + 128 + 129 + 94 @@ -1056,20 +1077,45 @@ 12 + + 19 + 20 + 565 + 20 21 - 3841 + 753 - 23 - 24 - 1920 + 21 + 22 + 188 - 25 - 26 - 1920 + 22 + 25 + 188 + + + 32 + 33 + 188 + + + 34 + 43 + 188 + + + 52 + 54 + 188 + + + 127 + 128 + 94 @@ -1085,17 +1131,32 @@ 1 2 - 3841 + 7068 2 - 3 - 5762 + 4 + 1036 4 - 5 - 38417 + 6 + 942 + + + 7 + 9 + 942 + + + 9 + 20 + 282 + + + 25 + 26 + 1790 @@ -1111,22 +1172,32 @@ 1 2 - 9604 + 7350 2 3 - 17287 + 188 3 4 - 11525 + 1507 4 - 5 - 9604 + 6 + 1036 + + + 6 + 9 + 942 + + + 9 + 26 + 1036 @@ -1142,17 +1213,12 @@ 1 2 - 61467 + 32607 2 - 3 - 3841 - - - 4 - 5 - 24971 + 26 + 2544 @@ -1168,17 +1234,12 @@ 1 2 - 67229 + 33078 2 - 3 - 19208 - - - 3 - 4 - 3841 + 12 + 2073 @@ -1188,19 +1249,19 @@ compilation_compiling_files - 59495 + 62421 id - 2275 + 731 num - 17556 + 9199 file - 49742 + 62421 @@ -1214,22 +1275,67 @@ 1 2 - 325 + 59 2 - 3 - 650 + 6 + 59 - 35 - 36 - 650 + 6 + 10 + 59 - 54 - 55 - 650 + 10 + 14 + 59 + + + 14 + 20 + 59 + + + 20 + 27 + 67 + + + 27 + 35 + 59 + + + 36 + 47 + 59 + + + 51 + 70 + 59 + + + 72 + 123 + 59 + + + 124 + 176 + 59 + + + 208 + 1130 + 59 + + + 1233 + 1234 + 7 @@ -1245,22 +1351,67 @@ 1 2 - 325 + 59 2 - 3 - 650 + 6 + 59 - 35 - 36 - 650 + 6 + 10 + 59 - 54 - 55 - 650 + 10 + 14 + 59 + + + 14 + 20 + 59 + + + 20 + 27 + 67 + + + 27 + 35 + 59 + + + 36 + 47 + 59 + + + 51 + 70 + 59 + + + 72 + 123 + 59 + + + 124 + 176 + 59 + + + 208 + 1130 + 59 + + + 1233 + 1234 + 7 @@ -1274,19 +1425,44 @@ 12 - 2 - 3 - 6177 + 1 + 2 + 775 - 4 + 2 + 3 + 4342 + + + 3 5 - 10728 + 790 + + + 5 + 6 + 880 6 8 - 650 + 686 + + + 8 + 16 + 768 + + + 16 + 42 + 701 + + + 42 + 99 + 253 @@ -1299,20 +1475,45 @@ 12 + + 1 + 2 + 775 + 2 3 - 6177 + 4342 3 - 4 - 9753 + 5 + 790 - 4 + 5 + 6 + 880 + + + 6 8 - 1625 + 686 + + + 8 + 16 + 768 + + + 16 + 42 + 701 + + + 42 + 99 + 253 @@ -1328,12 +1529,7 @@ 1 2 - 39989 - - - 2 - 3 - 9753 + 62421 @@ -1349,7 +1545,7 @@ 1 2 - 49742 + 62421 @@ -1359,19 +1555,19 @@ compilation_compiling_files_completed - 59495 + 62421 id - 2275 + 731 num - 17556 + 9199 result - 325 + 7 @@ -1385,22 +1581,67 @@ 1 2 - 325 + 59 2 - 3 - 650 + 6 + 59 - 35 - 36 - 650 + 6 + 10 + 59 - 54 - 55 - 650 + 10 + 14 + 59 + + + 14 + 20 + 59 + + + 20 + 27 + 67 + + + 27 + 35 + 59 + + + 36 + 47 + 59 + + + 51 + 70 + 59 + + + 72 + 123 + 59 + + + 124 + 176 + 59 + + + 208 + 1130 + 59 + + + 1233 + 1234 + 7 @@ -1416,7 +1657,7 @@ 1 2 - 2275 + 731 @@ -1430,19 +1671,44 @@ 12 - 2 - 3 - 6177 + 1 + 2 + 775 - 4 + 2 + 3 + 4342 + + + 3 5 - 10728 + 790 + + + 5 + 6 + 880 6 8 - 650 + 686 + + + 8 + 16 + 768 + + + 16 + 42 + 701 + + + 42 + 99 + 253 @@ -1458,7 +1724,7 @@ 1 2 - 17556 + 9199 @@ -1472,9 +1738,9 @@ 12 - 7 - 8 - 325 + 98 + 99 + 7 @@ -1488,9 +1754,9 @@ 12 - 54 - 55 - 325 + 1233 + 1234 + 7 @@ -1500,23 +1766,23 @@ compilation_time - 196471 + 252612 id - 8628 + 731 num - 5144 + 9207 kind - 663 + 29 seconds - 89772 + 123672 @@ -1527,55 +1793,70 @@ 12 - - 1 - 2 - 331 - 2 3 - 1659 + 59 3 - 4 - 1161 - - - 4 - 5 - 2157 - - - 5 - 6 - 663 - - - 6 7 - 497 + 59 7 - 8 - 497 + 11 + 59 - 8 - 12 - 663 + 11 + 15 + 59 - 13 - 16 - 663 + 15 + 21 + 59 - 20 - 32 - 331 + 21 + 28 + 67 + + + 28 + 36 + 59 + + + 37 + 48 + 59 + + + 52 + 71 + 59 + + + 73 + 124 + 59 + + + 125 + 177 + 59 + + + 209 + 1131 + 59 + + + 1234 + 1235 + 7 @@ -1591,7 +1872,7 @@ 4 5 - 8628 + 731 @@ -1604,55 +1885,70 @@ 12 - - 2 - 3 - 331 - 4 5 - 1659 + 59 6 - 7 - 1161 - - - 8 - 9 - 2157 - - - 10 - 11 - 663 - - - 12 13 - 497 + 59 14 - 15 - 497 + 21 + 59 - 16 - 23 - 663 + 22 + 29 + 59 - 26 - 31 - 663 + 30 + 41 + 59 - 40 - 63 - 331 + 42 + 55 + 67 + + + 56 + 71 + 59 + + + 74 + 95 + 59 + + + 104 + 141 + 59 + + + 146 + 247 + 59 + + + 250 + 353 + 59 + + + 418 + 2247 + 59 + + + 2436 + 2437 + 7 @@ -1668,52 +1964,42 @@ 1 2 - 1825 + 775 2 3 - 829 + 4342 3 5 - 331 + 790 + + + 5 + 6 + 880 6 - 7 - 331 - - - 7 8 - 331 + 686 8 - 11 - 331 + 16 + 768 - 13 - 17 - 331 + 16 + 42 + 701 - 20 - 34 - 331 - - - 40 - 51 - 331 - - - 52 - 53 - 165 + 42 + 99 + 261 @@ -1729,7 +2015,7 @@ 4 5 - 5144 + 9207 @@ -1745,52 +2031,42 @@ 3 4 - 1825 + 775 5 6 - 829 + 4342 7 10 - 331 + 790 + + + 11 + 12 + 880 13 - 14 - 331 - - - 15 16 - 331 + 686 17 - 22 - 331 + 32 + 768 - 27 - 34 - 331 + 33 + 84 + 701 - 41 - 54 - 331 - - - 67 - 82 - 331 - - - 101 - 102 - 165 + 85 + 198 + 261 @@ -1804,9 +2080,9 @@ 12 - 52 - 53 - 663 + 98 + 99 + 29 @@ -1820,9 +2096,9 @@ 12 - 31 - 32 - 663 + 1234 + 1235 + 29 @@ -1838,17 +2114,17 @@ 1 2 - 331 + 14 - 245 - 246 - 165 + 8222 + 8223 + 7 - 296 - 297 - 165 + 8364 + 8365 + 7 @@ -1864,12 +2140,12 @@ 1 2 - 89606 + 122389 - 52 - 53 - 165 + 2 + 99 + 1283 @@ -1885,12 +2161,12 @@ 1 2 - 89606 + 121889 - 31 - 32 - 165 + 2 + 1235 + 1783 @@ -1906,12 +2182,12 @@ 1 2 - 89606 + 123582 - 3 + 2 4 - 165 + 89 @@ -1921,23 +2197,23 @@ diagnostic_for - 61632 + 64190 diagnostic - 61632 + 64190 compilation - 574 + 716 file_number - 14797 + 7 file_number_diagnostic_number - 2154 + 14475 @@ -1951,7 +2227,7 @@ 1 2 - 61632 + 64190 @@ -1967,7 +2243,7 @@ 1 2 - 61632 + 64190 @@ -1983,7 +2259,7 @@ 1 2 - 61632 + 64190 @@ -1992,94 +2268,6 @@ compilation diagnostic - - - 12 - - - 14 - 15 - 143 - - - 28 - 29 - 143 - - - 123 - 124 - 143 - - - 264 - 265 - 143 - - - - - - - compilation - file_number - - - 12 - - - 7 - 8 - 143 - - - 14 - 15 - 143 - - - 45 - 46 - 143 - - - 103 - 104 - 143 - - - - - - - compilation - file_number_diagnostic_number - - - 12 - - - 2 - 3 - 287 - - - 14 - 15 - 143 - - - 15 - 16 - 143 - - - - - - - file_number - diagnostic 12 @@ -2087,42 +2275,135 @@ 1 2 - 143 - - - 2 - 3 - 6464 + 268 3 - 4 - 718 - - - 4 5 - 3160 + 59 5 - 6 - 1292 - - - 6 8 - 1149 + 52 8 - 11 - 1292 + 14 + 44 - 12 - 21 - 574 + 14 + 22 + 59 + + + 22 + 39 + 59 + + + 42 + 55 + 59 + + + 60 + 169 + 59 + + + 228 + 1941 + 52 + + + + + + + compilation + file_number + + + 12 + + + 1 + 2 + 716 + + + + + + + compilation + file_number_diagnostic_number + + + 12 + + + 1 + 2 + 268 + + + 3 + 5 + 59 + + + 5 + 8 + 52 + + + 8 + 14 + 44 + + + 14 + 22 + 59 + + + 22 + 39 + 59 + + + 42 + 55 + 59 + + + 60 + 169 + 59 + + + 228 + 1941 + 52 + + + + + + + file_number + diagnostic + + + 12 + + + 8603 + 8604 + 7 @@ -2136,24 +2417,9 @@ 12 - 1 - 2 - 8332 - - - 2 - 3 - 4453 - - - 3 - 4 - 1005 - - - 4 - 5 - 1005 + 96 + 97 + 7 @@ -2167,34 +2433,9 @@ 12 - 1 - 2 - 143 - - - 2 - 3 - 10056 - - - 3 - 4 - 2011 - - - 4 - 5 - 1005 - - - 5 - 8 - 1149 - - - 10 - 16 - 430 + 1940 + 1941 + 7 @@ -2210,52 +2451,42 @@ 1 2 - 143 + 3290 2 3 - 574 + 238 3 4 - 430 + 5081 + + + 4 + 5 + 2439 5 6 - 143 + 261 + + + 6 + 7 + 1462 7 - 8 - 143 + 14 + 1208 - 11 - 12 - 143 - - - 18 - 19 - 143 - - - 33 - 34 - 143 - - - 168 - 169 - 143 - - - 169 - 170 - 143 + 14 + 97 + 492 @@ -2271,17 +2502,42 @@ 1 2 - 143 + 3290 2 3 - 1723 + 238 + + + 3 + 4 + 5081 4 5 - 287 + 2439 + + + 5 + 6 + 261 + + + 6 + 7 + 1462 + + + 7 + 14 + 1208 + + + 14 + 97 + 492 @@ -2297,52 +2553,7 @@ 1 2 - 143 - - - 2 - 3 - 574 - - - 3 - 4 - 430 - - - 5 - 6 - 143 - - - 7 - 8 - 143 - - - 11 - 12 - 143 - - - 18 - 19 - 143 - - - 32 - 33 - 143 - - - 102 - 103 - 143 - - - 103 - 104 - 143 + 14475 @@ -2352,19 +2563,19 @@ compilation_compiler_times - 7683 + 2261 id - 7683 + 2261 cpu_seconds - 1920 + 94 elapsed_seconds - 7683 + 2167 @@ -2378,7 +2589,7 @@ 1 2 - 7683 + 2261 @@ -2394,7 +2605,7 @@ 1 2 - 7683 + 2261 @@ -2408,9 +2619,9 @@ 12 - 4 - 5 - 1920 + 24 + 25 + 94 @@ -2424,9 +2635,9 @@ 12 - 4 - 5 - 1920 + 23 + 24 + 94 @@ -2442,7 +2653,12 @@ 1 2 - 7683 + 2073 + + + 2 + 3 + 94 @@ -2458,7 +2674,7 @@ 1 2 - 7683 + 2167 @@ -2684,35 +2900,35 @@ diagnostics - 61632 + 64190 id - 61632 + 64190 generated_by - 143 + 7 severity - 143 + 29 error_tag - 143 + 7 error_message - 1580 + 2604 full_error_message - 40944 + 7 location - 143 + 7 @@ -2726,7 +2942,7 @@ 1 2 - 61632 + 64190 @@ -2742,7 +2958,7 @@ 1 2 - 61632 + 64190 @@ -2758,7 +2974,7 @@ 1 2 - 61632 + 64190 @@ -2774,7 +2990,7 @@ 1 2 - 61632 + 64190 @@ -2790,7 +3006,7 @@ 1 2 - 61632 + 64190 @@ -2806,7 +3022,7 @@ 1 2 - 61632 + 64190 @@ -2820,9 +3036,9 @@ 12 - 429 - 430 - 143 + 8603 + 8604 + 7 @@ -2836,9 +3052,9 @@ 12 - 1 - 2 - 143 + 4 + 5 + 7 @@ -2854,7 +3070,7 @@ 1 2 - 143 + 7 @@ -2868,9 +3084,9 @@ 12 - 11 - 12 - 143 + 349 + 350 + 7 @@ -2884,9 +3100,9 @@ 12 - 285 - 286 - 143 + 1 + 2 + 7 @@ -2902,7 +3118,7 @@ 1 2 - 143 + 7 @@ -2916,9 +3132,24 @@ 12 - 429 - 430 - 143 + 4 + 5 + 7 + + + 13 + 14 + 7 + + + 95 + 96 + 7 + + + 8491 + 8492 + 7 @@ -2934,7 +3165,7 @@ 1 2 - 143 + 29 @@ -2950,7 +3181,7 @@ 1 2 - 143 + 29 @@ -2964,9 +3195,24 @@ 12 - 11 - 12 - 143 + 4 + 5 + 7 + + + 13 + 14 + 7 + + + 95 + 96 + 7 + + + 237 + 238 + 7 @@ -2980,9 +3226,9 @@ 12 - 285 - 286 - 143 + 1 + 2 + 29 @@ -2998,7 +3244,7 @@ 1 2 - 143 + 29 @@ -3012,9 +3258,9 @@ 12 - 429 - 430 - 143 + 8603 + 8604 + 7 @@ -3030,7 +3276,7 @@ 1 2 - 143 + 7 @@ -3044,9 +3290,9 @@ 12 - 1 - 2 - 143 + 4 + 5 + 7 @@ -3060,9 +3306,9 @@ 12 - 11 - 12 - 143 + 349 + 350 + 7 @@ -3076,9 +3322,9 @@ 12 - 285 - 286 - 143 + 1 + 2 + 7 @@ -3094,7 +3340,7 @@ 1 2 - 143 + 7 @@ -3110,47 +3356,17 @@ 1 2 - 143 + 2290 2 - 3 - 143 - - - 3 - 4 - 143 - - - 6 - 7 - 143 + 9 + 201 9 - 10 - 143 - - - 12 - 13 - 287 - - - 24 - 25 - 143 - - - 28 - 29 - 143 - - - 166 - 167 - 287 + 3692 + 111 @@ -3166,7 +3382,7 @@ 1 2 - 1580 + 2604 @@ -3182,7 +3398,7 @@ 1 2 - 1580 + 2604 @@ -3198,7 +3414,7 @@ 1 2 - 1580 + 2604 @@ -3214,52 +3430,7 @@ 1 2 - 143 - - - 2 - 3 - 143 - - - 3 - 4 - 143 - - - 6 - 7 - 143 - - - 9 - 10 - 143 - - - 12 - 13 - 287 - - - 22 - 23 - 143 - - - 24 - 25 - 143 - - - 28 - 29 - 143 - - - 166 - 167 - 143 + 2604 @@ -3275,7 +3446,7 @@ 1 2 - 1580 + 2604 @@ -3289,14 +3460,9 @@ 12 - 1 - 2 - 38358 - - - 2 - 25 - 2585 + 8603 + 8604 + 7 @@ -3312,7 +3478,7 @@ 1 2 - 40944 + 7 @@ -3326,9 +3492,9 @@ 12 - 1 - 2 - 40944 + 4 + 5 + 7 @@ -3344,7 +3510,7 @@ 1 2 - 40944 + 7 @@ -3358,9 +3524,9 @@ 12 - 1 - 2 - 40944 + 349 + 350 + 7 @@ -3376,7 +3542,7 @@ 1 2 - 40944 + 7 @@ -3390,9 +3556,9 @@ 12 - 429 - 430 - 143 + 8603 + 8604 + 7 @@ -3408,7 +3574,7 @@ 1 2 - 143 + 7 @@ -3422,9 +3588,9 @@ 12 - 1 - 2 - 143 + 4 + 5 + 7 @@ -3440,7 +3606,7 @@ 1 2 - 143 + 7 @@ -3454,9 +3620,9 @@ 12 - 11 - 12 - 143 + 349 + 350 + 7 @@ -3470,9 +3636,9 @@ 12 - 285 - 286 - 143 + 1 + 2 + 7 @@ -3637,11 +3803,11 @@ sourceLocationPrefix - 1920 + 569 prefix - 1920 + 569 @@ -4928,31 +5094,31 @@ locations_default - 602747369 + 82315299 id - 602747369 + 82315299 file - 9158642 + 1291911 beginLine - 3943517 + 538208 beginColumn - 247790 + 33818 endLine - 3945438 + 538471 endColumn - 873989 + 119281 @@ -4966,7 +5132,7 @@ 1 2 - 602747369 + 82315299 @@ -4982,7 +5148,7 @@ 1 2 - 602747369 + 82315299 @@ -4998,7 +5164,7 @@ 1 2 - 602747369 + 82315299 @@ -5014,7 +5180,7 @@ 1 2 - 602747369 + 82315299 @@ -5030,7 +5196,7 @@ 1 2 - 602747369 + 82315299 @@ -5046,17 +5212,17 @@ 1 2 - 7986919 + 1131995 2 11 - 714558 + 97522 11 3605 - 457163 + 62393 @@ -5072,17 +5238,17 @@ 1 2 - 7986919 + 1131995 2 9 - 712637 + 97260 9 1830 - 459084 + 62655 @@ -5098,17 +5264,17 @@ 1 2 - 7986919 + 1131995 2 5 - 776025 + 105911 5 105 - 395696 + 54004 @@ -5124,17 +5290,17 @@ 1 2 - 7986919 + 1131995 2 - 10 - 693429 + 11 + 99619 - 10 + 11 1834 - 478293 + 60296 @@ -5150,17 +5316,17 @@ 1 2 - 7986919 + 1131995 2 - 9 - 695349 + 10 + 99619 - 9 + 10 205 - 476372 + 60296 @@ -5176,67 +5342,67 @@ 1 14 - 313099 + 42731 14 125 - 301574 + 41158 125 142 - 307336 + 41945 142 152 - 316941 + 43255 152 159 - 359200 + 49023 159 164 - 272761 + 37226 164 169 - 343833 + 46926 169 173 - 299653 + 40896 173 178 - 332308 + 45353 178 184 - 347674 + 47450 184 193 - 316941 + 43255 193 211 - 297732 + 40372 211 - 4769 - 134459 + 4929 + 18613 @@ -5252,72 +5418,72 @@ 1 7 - 322703 + 44042 7 65 - 299653 + 40896 65 73 - 307336 + 41945 73 78 - 295811 + 40372 78 81 - 265078 + 36177 81 84 - 357279 + 48761 84 86 - 299653 + 40896 86 87 - 188243 + 25691 87 89 - 357279 + 48761 89 91 - 259315 + 35129 91 94 - 324624 + 44566 94 99 - 328466 + 44828 99 - 141 - 295811 + 142 + 40634 - 141 - 4769 - 42258 + 142 + 4929 + 5505 @@ -5333,62 +5499,62 @@ 1 5 - 313099 + 42731 5 17 - 280444 + 38274 17 19 - 251632 + 34342 19 20 - 309257 + 42207 20 21 - 403379 + 55053 21 22 - 420667 + 57412 22 23 - 476372 + 65015 23 24 - 457163 + 62393 24 25 - 339991 + 46401 25 26 - 213215 + 29099 26 29 - 361120 + 49285 29 40 - 117172 + 15991 @@ -5404,32 +5570,32 @@ 1 2 - 1273527 + 173810 2 3 - 1265844 + 172761 3 4 - 674220 + 92017 4 5 - 299653 + 40896 5 11 - 307336 + 41945 11 97 - 122934 + 16778 @@ -5445,72 +5611,72 @@ 1 13 - 309257 + 42207 13 60 - 307336 + 41945 60 64 - 311178 + 42469 64 66 - 311178 + 42207 66 68 - 353437 + 48499 68 69 - 194006 + 26477 69 70 - 217056 + 29361 70 72 - 359200 + 49023 72 74 - 322703 + 44042 74 76 - 245869 + 33818 76 79 - 330387 + 45091 79 83 - 295811 + 40372 83 91 - 316941 + 43255 91 103 - 69150 + 9437 @@ -5526,67 +5692,67 @@ 1 11 - 21129 + 2883 15 24 - 21129 + 2883 28 - 57 - 19208 + 58 + 2883 - 57 - 79 - 19208 + 58 + 88 + 2621 - 87 - 119 - 19208 + 89 + 131 + 2621 - 130 - 177 - 19208 + 131 + 196 + 2883 - 195 - 269 - 19208 + 213 + 297 + 2621 - 270 - 436 - 19208 + 307 + 496 + 2621 - 443 - 835 - 19208 + 513 + 883 + 2621 - 844 - 1367 - 19208 + 933 + 1470 + 2621 - 1419 - 2155 - 19208 + 1665 + 2279 + 2621 - 2252 - 2517 - 19208 + 2295 + 2583 + 2621 - 2521 - 226452 - 13445 + 2694 + 226487 + 1310 @@ -5602,72 +5768,72 @@ 1 9 - 17287 + 2359 9 11 - 21129 + 2883 11 15 - 15366 + 2097 15 19 - 21129 + 2883 23 68 - 19208 + 2621 69 78 - 19208 + 2621 79 100 - 13445 + 1835 100 104 - 21129 + 2883 104 109 - 19208 + 2621 109 112 - 13445 + 1835 112 115 - 19208 + 2621 115 117 - 19208 + 2621 117 123 - 19208 + 2621 145 - 4769 - 9604 + 4929 + 1310 @@ -5683,67 +5849,67 @@ 1 10 - 21129 + 2883 10 22 - 21129 + 2883 23 39 - 19208 + 2621 41 58 - 19208 + 2621 58 84 - 19208 + 2621 84 106 - 19208 + 2621 108 166 - 19208 + 2621 167 225 - 19208 + 2621 230 376 - 19208 + 2621 381 647 - 19208 + 2621 657 941 - 19208 + 2621 941 1090 - 19208 + 2621 1102 2051 - 13445 + 1835 @@ -5759,67 +5925,67 @@ 1 10 - 21129 + 2883 10 22 - 21129 + 2883 23 39 - 19208 + 2621 41 59 - 19208 + 2621 59 86 - 19208 + 2621 86 109 - 19208 + 2621 114 168 - 19208 + 2621 170 224 - 19208 + 2621 229 379 - 19208 + 2621 382 647 - 19208 + 2621 658 941 - 19208 + 2621 941 1089 - 19208 + 2621 1102 2051 - 13445 + 1835 @@ -5835,67 +6001,67 @@ 1 8 - 21129 + 2883 8 16 - 21129 + 2883 16 23 - 21129 + 2621 - 24 - 31 - 21129 + 23 + 30 + 2621 - 32 - 37 - 21129 + 30 + 36 + 2621 - 37 - 50 - 19208 + 36 + 44 + 2621 - 50 - 60 - 19208 + 46 + 55 + 2621 - 60 - 68 - 19208 + 55 + 65 + 2883 - 68 - 80 - 19208 + 65 + 76 + 2621 - 81 - 101 - 19208 + 77 + 94 + 2621 - 101 - 121 - 19208 + 94 + 117 + 2621 - 126 - 158 - 19208 + 119 + 152 + 2621 - 159 + 153 393 - 7683 + 1572 @@ -5911,67 +6077,67 @@ 1 14 - 309257 + 42207 14 124 - 305416 + 41683 124 143 - 309257 + 42207 143 152 - 334228 + 45615 152 159 - 322703 + 44042 159 164 - 299653 + 40896 164 169 - 341912 + 46664 169 173 - 309257 + 41945 173 178 - 338070 + 46401 178 184 - 305416 + 41683 184 193 - 315020 + 42993 193 212 - 301574 + 41158 212 - 4769 - 153668 + 4929 + 20972 @@ -5987,67 +6153,67 @@ 1 7 - 324624 + 44304 7 66 - 318862 + 43518 66 74 - 320782 + 43780 74 80 - 355358 + 48499 80 83 - 339991 + 46401 83 85 - 268919 + 36702 85 87 - 343833 + 46926 87 89 - 355358 + 48499 89 91 - 266999 + 36439 91 94 - 345754 + 47188 94 99 - 324624 + 44304 99 130 - 301574 + 40896 - 131 - 4769 - 78755 + 130 + 4929 + 11010 @@ -6063,32 +6229,32 @@ 1 2 - 1000766 + 136583 2 3 - 1392620 + 190064 3 4 - 908564 + 124000 4 6 - 336149 + 45877 6 19 - 299653 + 40896 19 22 - 7683 + 1048 @@ -6104,62 +6270,62 @@ 1 5 - 309257 + 42207 5 17 - 284286 + 38799 17 19 - 232423 + 31721 19 20 - 280444 + 38274 20 21 - 420667 + 57412 21 22 - 407221 + 55577 22 23 - 482134 + 65801 23 24 - 437955 + 59771 24 25 - 334228 + 45353 25 26 - 259315 + 35653 26 29 - 363041 + 49547 29 39 - 134459 + 18351 @@ -6175,72 +6341,72 @@ 1 13 - 313099 + 42731 13 60 - 305416 + 41683 60 64 - 305416 + 41683 64 66 - 303495 + 41158 66 68 - 357279 + 49023 68 69 - 197848 + 27002 69 70 - 201689 + 27526 70 71 - 218977 + 29623 71 73 - 326545 + 44828 73 75 - 263157 + 35653 75 77 - 257394 + 35129 77 80 - 299653 + 40896 80 85 - 318862 + 43780 85 119 - 276603 + 37750 @@ -6256,57 +6422,57 @@ 1 2 - 205531 + 28050 2 3 - 90280 + 12321 3 5 - 71071 + 9699 5 13 - 71071 + 9699 13 53 - 67229 + 9175 53 - 138 - 67229 + 144 + 9175 - 142 - 346 - 67229 + 145 + 348 + 9175 357 967 - 67229 + 9175 1050 2386 - 67229 + 9175 2392 - 4902 - 67229 + 4931 + 9175 4949 5933 - 32654 + 4456 @@ -6322,57 +6488,57 @@ 1 2 - 213215 + 29099 2 3 - 86438 + 11797 3 5 - 74913 + 10224 5 13 - 71071 + 9699 13 42 - 67229 + 9175 42 77 - 67229 + 9175 77 102 - 69150 + 9175 102 - 114 - 67229 + 113 + 9175 114 139 - 67229 + 9175 139 - 169 - 69150 + 168 + 9175 - 173 - 4769 - 21129 + 168 + 4929 + 3408 @@ -6388,57 +6554,57 @@ 1 2 - 217056 + 29623 2 3 - 88359 + 12059 3 5 - 69150 + 9437 5 13 - 69150 + 9437 13 - 50 - 67229 + 51 + 9175 - 50 + 51 113 - 67229 + 9175 114 266 - 67229 + 9175 269 636 - 67229 + 9175 648 1197 - 67229 + 9175 1198 1635 - 69150 + 9437 1639 1722 - 24971 + 3408 @@ -6454,47 +6620,47 @@ 1 2 - 274682 + 37488 2 3 - 105647 + 14156 3 6 - 76834 + 10748 6 14 - 76834 + 10486 14 25 - 74913 + 10224 25 36 - 71071 + 9699 36 47 - 67229 + 9175 47 54 - 67229 + 9175 54 65 - 59546 + 8126 @@ -6510,57 +6676,57 @@ 1 2 - 217056 + 29623 2 3 - 86438 + 11797 3 5 - 69150 + 9437 5 13 - 69150 + 9437 13 - 51 - 67229 + 52 + 9175 - 51 + 52 112 - 67229 + 9175 112 262 - 67229 + 9175 262 630 - 67229 + 9175 637 1186 - 67229 + 9175 1197 1625 - 67229 + 9175 1632 1722 - 28812 + 3932 @@ -6570,15 +6736,15 @@ hasLocation - 340930835 + 53281114 locatableid - 340658074 + 53281114 id - 12195515 + 1717130 @@ -6592,12 +6758,7 @@ 1 2 - 340385312 - - - 2 - 3 - 272761 + 53281114 @@ -6613,57 +6774,62 @@ 1 2 - 2091812 + 294140 2 3 - 1333074 + 182199 3 - 4 - 772184 + 5 + 155983 - 4 - 6 - 1085283 + 5 + 7 + 126884 - 6 - 8 - 1062233 + 7 + 10 + 148905 - 8 - 11 - 1100650 + 10 + 13 + 142089 - 11 - 15 - 1048787 + 13 + 17 + 132651 - 15 - 21 - 964269 + 17 + 23 + 130030 - 21 - 32 - 916248 + 23 + 35 + 133175 - 32 + 35 64 - 920090 + 129505 64 - 9549 - 900881 + 396 + 128981 + + + 405 + 9847 + 12583 @@ -6673,23 +6839,23 @@ numlines - 303305105 + 41395164 element_id - 303305105 + 41395164 num_lines - 618515 + 84414 num_code - 612753 + 83628 num_comment - 1893964 + 258487 @@ -6703,7 +6869,7 @@ 1 2 - 303305105 + 41395164 @@ -6719,7 +6885,7 @@ 1 2 - 303305105 + 41395164 @@ -6735,7 +6901,7 @@ 1 2 - 303305105 + 41395164 @@ -6751,37 +6917,37 @@ 1 2 - 320782 + 43780 2 3 - 78755 + 10748 3 4 - 61467 + 8389 4 7 - 49942 + 6816 7 14 - 48021 + 6553 15 194 - 48021 + 6553 320 149659 - 11525 + 1572 @@ -6797,17 +6963,17 @@ 1 2 - 509026 + 69471 2 3 - 69150 + 9437 3 6 - 40337 + 5505 @@ -6823,27 +6989,27 @@ 1 2 - 380329 + 51907 2 3 - 97963 + 13370 3 4 - 51863 + 7078 4 6 - 53783 + 7340 6 987 - 34575 + 4718 @@ -6859,37 +7025,37 @@ 1 2 - 316941 + 43255 2 3 - 78755 + 10748 3 4 - 61467 + 8389 4 7 - 51863 + 7078 7 15 - 46100 + 6291 16 214 - 46100 + 6291 325 78746 - 11525 + 1572 @@ -6905,17 +7071,17 @@ 1 2 - 516710 + 70520 2 3 - 51863 + 7078 3 8 - 44179 + 6029 @@ -6931,27 +7097,27 @@ 1 2 - 370725 + 50596 2 3 - 101805 + 13894 3 4 - 53783 + 7340 4 6 - 46100 + 6291 6 987 - 40337 + 5505 @@ -6967,77 +7133,77 @@ 1 7 - 153668 + 20972 7 49 - 142143 + 19399 49 71 - 147905 + 20186 71 78 - 151747 + 20710 78 83 - 145985 + 19923 83 87 - 163272 + 22283 87 89 - 140222 + 19137 89 91 - 134459 + 18351 91 92 - 80675 + 11010 92 93 - 96042 + 13107 93 94 - 105647 + 14418 94 95 - 97963 + 13370 95 97 - 151747 + 20710 97 119 - 144064 + 19661 120 75134 - 38417 + 5243 @@ -7053,22 +7219,22 @@ 1 2 - 1550130 + 211560 2 3 - 165193 + 22545 3 7 - 145985 + 19923 7 120 - 32654 + 4456 @@ -7084,22 +7250,22 @@ 1 2 - 1550130 + 211560 2 3 - 165193 + 22545 3 7 - 145985 + 19923 7 122 - 32654 + 4456 @@ -7109,15 +7275,15 @@ files - 9158642 + 1291911 id - 9158642 + 1291911 name - 9158642 + 1291911 @@ -7131,7 +7297,7 @@ 1 2 - 9158642 + 1291911 @@ -7147,7 +7313,7 @@ 1 2 - 9158642 + 1291911 @@ -7157,15 +7323,15 @@ folders - 1415670 + 293711 id - 1415670 + 293711 name - 1415670 + 293711 @@ -7179,7 +7345,7 @@ 1 2 - 1415670 + 293711 @@ -7195,7 +7361,7 @@ 1 2 - 1415670 + 293711 @@ -7205,15 +7371,15 @@ containerparent - 10570471 + 1496393 parent - 1463692 + 212871 child - 10570471 + 1496393 @@ -7227,32 +7393,32 @@ 1 2 - 843255 + 125311 2 3 - 149826 + 18613 3 5 - 128697 + 18613 5 - 11 - 124855 + 10 + 18088 - 11 - 21 - 113330 + 10 + 20 + 15991 - 21 + 20 194 - 103726 + 16253 @@ -7268,7 +7434,7 @@ 1 2 - 10570471 + 1496393 @@ -7278,15 +7444,15 @@ cupackage - 7979236 + 1129635 id - 7979236 + 1129635 packageid - 576256 + 85463 @@ -7300,7 +7466,7 @@ 1 2 - 7979236 + 1129635 @@ -7316,52 +7482,57 @@ 1 2 - 121013 + 18351 2 3 - 80675 + 11797 3 4 - 42258 + 6029 4 - 6 - 49942 + 5 + 5505 - 6 + 5 + 7 + 4980 + + + 7 9 - 49942 + 6291 9 - 12 - 51863 + 11 + 6553 - 12 + 11 17 - 48021 + 7864 17 - 23 - 46100 + 26 + 6816 - 24 - 43 - 44179 + 26 + 53 + 6553 - 43 + 54 187 - 42258 + 4718 @@ -7692,23 +7863,23 @@ jarManifestEntries - 30201 + 46193 fileid - 61 + 29 entryName - 30129 + 46141 keyName - 27 + 59 value - 30163 + 46171 @@ -7722,72 +7893,22 @@ 1 2 - 4 + 7 - 4 - 10 - 3 + 264 + 265 + 7 - 10 - 12 - 4 + 1520 + 1521 + 7 - 12 - 31 - 4 - - - 65 - 82 - 4 - - - 123 - 164 - 4 - - - 178 - 240 - 4 - - - 253 - 294 - 4 - - - 307 - 357 - 4 - - - 361 - 395 - 4 - - - 433 - 461 - 4 - - - 591 - 662 - 4 - - - 957 - 2267 - 4 - - - 3647 - 3762 - 3 + 4400 + 4401 + 7 @@ -7796,238 +7917,6 @@ fileid keyName - - - 12 - - - 1 - 2 - 57 - - - 6 - 10 - 3 - - - - - - - fileid - value - - - 12 - - - 1 - 2 - 4 - - - 3 - 8 - 4 - - - 9 - 13 - 4 - - - 24 - 66 - 4 - - - 70 - 124 - 4 - - - 127 - 179 - 4 - - - 195 - 254 - 4 - - - 265 - 308 - 4 - - - 320 - 362 - 4 - - - 381 - 434 - 4 - - - 434 - 592 - 4 - - - 618 - 958 - 4 - - - 1671 - 3648 - 4 - - - 3761 - 3762 - 1 - - - - - - - entryName - fileid - - - 12 - - - 1 - 2 - 30113 - - - 2 - 26 - 16 - - - - - - - entryName - keyName - - - 12 - - - 1 - 2 - 30126 - - - 6 - 10 - 3 - - - - - - - entryName - value - - - 12 - - - 1 - 2 - 30125 - - - 3 - 26 - 4 - - - - - - - keyName - fileid - - - 12 - - - 1 - 2 - 21 - - - 2 - 3 - 3 - - - 3 - 4 - 1 - - - 32 - 33 - 1 - - - - - - - keyName - entryName - - - 12 - - - 1 - 2 - 21 - - - 2 - 3 - 1 - - - 11 - 12 - 1 - - - 369 - 370 - 1 - - - 19366 - 19367 - 1 - - - - - - - keyName - value 12 @@ -8037,20 +7926,167 @@ 2 22 + + 7 + 8 + 7 + + + + + + + fileid + value + + + 12 + + + 4 + 5 + 7 + + + 264 + 265 + 7 + + + 1520 + 1521 + 7 + + + 4400 + 4401 + 7 + + + + + + + entryName + fileid + + + 12 + + + 1 + 2 + 46133 + 2 3 - 1 + 7 + + + + + + + entryName + keyName + + + 12 + + + 1 + 2 + 46133 - 369 - 370 - 1 + 7 + 8 + 7 + + + + + + + entryName + value + + + 12 + + + 1 + 2 + 46126 - 19390 - 19391 - 1 + 2 + 5 + 14 + + + + + + + keyName + fileid + + + 12 + + + 1 + 2 + 52 + + + 3 + 4 + 7 + + + + + + + keyName + entryName + + + 12 + + + 1 + 2 + 52 + + + 6183 + 6184 + 7 + + + + + + + keyName + value + + + 12 + + + 1 + 2 + 52 + + + 6184 + 6185 + 7 @@ -8066,12 +8102,7 @@ 1 2 - 30162 - - - 2 - 3 - 1 + 46171 @@ -8087,12 +8118,7 @@ 1 2 - 30162 - - - 11 - 12 - 1 + 46171 @@ -8108,12 +8134,12 @@ 1 2 - 30155 + 46148 2 3 - 7 + 22 @@ -8123,15 +8149,15 @@ packages - 580098 + 121135 id - 580098 + 121135 nodeName - 580098 + 121135 @@ -8145,7 +8171,7 @@ 1 2 - 580098 + 121135 @@ -8161,7 +8187,7 @@ 1 2 - 580098 + 121135 @@ -8171,15 +8197,15 @@ primitives - 17287 + 5690 id - 17287 + 5690 nodeName - 17287 + 5690 @@ -8193,7 +8219,7 @@ 1 2 - 17287 + 5690 @@ -8209,7 +8235,7 @@ 1 2 - 17287 + 5690 @@ -8219,15 +8245,15 @@ modifiers - 26891 + 6259 id - 26891 + 6259 nodeName - 26891 + 6259 @@ -8241,7 +8267,7 @@ 1 2 - 26891 + 6259 @@ -8257,7 +8283,7 @@ 1 2 - 26891 + 6259 @@ -8267,34 +8293,34 @@ error_type - 1 + 22 id - 1 + 22 - classes - 12618104 + classes_or_interfaces + 22273131 id - 12618104 + 22273131 nodeName - 6732600 + 5754222 parentid - 455242 + 734 sourceid - 5253541 + 26258 @@ -8308,7 +8334,7 @@ 1 2 - 12618104 + 22273131 @@ -8324,7 +8350,7 @@ 1 2 - 12618104 + 22273131 @@ -8340,7 +8366,7 @@ 1 2 - 12618104 + 22273131 @@ -8356,17 +8382,27 @@ 1 2 - 5601216 + 3703195 2 3 - 726083 + 866201 3 - 204 - 405300 + 5 + 424184 + + + 5 + 12 + 451316 + + + 12 + 9655 + 309324 @@ -8382,17 +8418,12 @@ 1 2 - 5950812 + 5753464 2 - 3 - 731846 - - - 3 - 52 - 49942 + 29 + 757 @@ -8408,17 +8439,12 @@ 1 2 - 5921999 + 5753210 2 - 3 - 714558 - - - 3 - 160 - 96042 + 3091 + 1011 @@ -8434,220 +8460,240 @@ 1 2 - 94121 + 132 2 3 - 46100 + 40 3 - 4 - 30733 - - - 4 5 - 26891 + 63 5 - 6 - 24971 + 7 + 46 - 6 + 7 8 - 40337 + 57 8 - 12 - 32654 - - - 12 - 18 - 38417 - - - 18 - 23 - 34575 - - - 23 - 40 - 36496 - - - 40 - 76 - 34575 - - - 83 - 891 - 15366 - - - - - - - parentid - nodeName - - - 12 - - - 1 - 2 - 96042 - - - 2 - 3 - 46100 - - - 3 - 4 - 34575 - - - 4 - 5 - 28812 - - - 5 - 6 - 36496 - - - 6 - 9 - 40337 - - - 9 - 13 - 40337 - - - 13 - 18 - 26891 - - - 18 - 25 - 38417 - - - 26 - 41 - 36496 - - - 41 - 479 - 30733 - - - - - - - parentid - sourceid - - - 12 - - - 1 - 2 - 99884 - - - 2 - 3 - 57625 - - - 3 - 4 - 36496 - - - 4 - 5 - 32654 - - - 5 - 6 - 32654 - - - 6 - 8 - 34575 - - - 8 - 12 - 38417 - - - 12 - 18 - 32654 - - - 18 - 25 - 34575 - - - 25 - 47 - 34575 - - - 51 - 138 - 21129 - - - - - - - sourceid - id - - - 12 - - - 1 - 2 - 4694572 - - - 2 11 - 407221 + 63 11 - 426 - 151747 + 23 + 57 + + + 23 + 41 + 63 + + + 42 + 158 + 57 + + + 162 + 1034 + 57 + + + 1315 + 34752 + 57 + + + 36100 + 2058753 + 34 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 132 + + + 2 + 3 + 40 + + + 3 + 4 + 28 + + + 4 + 5 + 40 + + + 5 + 6 + 34 + + + 6 + 7 + 40 + + + 7 + 9 + 52 + + + 9 + 15 + 57 + + + 15 + 24 + 63 + + + 24 + 56 + 57 + + + 57 + 178 + 57 + + + 186 + 3066 + 57 + + + 3515 + 65688 + 57 + + + 298524 + 495903 + 11 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 150 + + + 2 + 3 + 80 + + + 3 + 4 + 34 + + + 4 + 5 + 63 + + + 5 + 7 + 40 + + + 7 + 9 + 63 + + + 9 + 11 + 63 + + + 12 + 15 + 46 + + + 16 + 23 + 57 + + + 25 + 41 + 57 + + + 47 + 113 + 57 + + + 113 + 2641 + 17 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 23281 + + + 2 + 15 + 1994 + + + 15 + 448199 + 982 @@ -8663,17 +8709,17 @@ 1 2 - 4694572 + 23281 2 - 6 - 426430 + 10 + 2005 - 6 - 224 - 132539 + 10 + 100263 + 971 @@ -8689,7 +8735,7 @@ 1 2 - 5253541 + 26258 @@ -8699,26 +8745,26 @@ file_class - 17287 + 7249 id - 17287 + 7249 class_object - 163272 + 22283 id - 163272 + 22283 instance - 163272 + 22283 @@ -8732,7 +8778,7 @@ 1 2 - 163272 + 22283 @@ -8748,7 +8794,7 @@ 1 2 - 163272 + 22283 @@ -8758,19 +8804,19 @@ type_companion_object - 307336 + 41945 id - 307336 + 41945 instance - 307336 + 41945 companion_object - 307336 + 41945 @@ -8784,7 +8830,7 @@ 1 2 - 307336 + 41945 @@ -8800,7 +8846,7 @@ 1 2 - 307336 + 41945 @@ -8816,7 +8862,7 @@ 1 2 - 307336 + 41945 @@ -8832,7 +8878,7 @@ 1 2 - 307336 + 41945 @@ -8848,7 +8894,7 @@ 1 2 - 307336 + 41945 @@ -8864,7 +8910,7 @@ 1 2 - 307336 + 41945 @@ -8874,15 +8920,15 @@ kt_nullable_types - 1920 + 262 id - 1920 + 262 classid - 1920 + 262 @@ -8896,7 +8942,7 @@ 1 2 - 1920 + 262 @@ -8912,7 +8958,7 @@ 1 2 - 1920 + 262 @@ -8922,15 +8968,15 @@ kt_notnull_types - 172391 + 156265 id - 172391 + 156265 classid - 172391 + 156265 @@ -8944,7 +8990,7 @@ 1 2 - 172391 + 156265 @@ -8960,7 +9006,7 @@ 1 2 - 172391 + 156265 @@ -8970,19 +9016,19 @@ kt_type_alias - 1821 + 707 id - 1821 + 707 name - 1821 + 583 kttypeid - 910 + 12 @@ -8996,7 +9042,7 @@ 1 2 - 1821 + 707 @@ -9012,7 +9058,7 @@ 1 2 - 1821 + 707 @@ -9028,7 +9074,12 @@ 1 2 - 1821 + 459 + + + 2 + 3 + 124 @@ -9044,7 +9095,7 @@ 1 2 - 1821 + 583 @@ -9058,9 +9109,9 @@ 12 - 2 - 3 - 910 + 57 + 58 + 12 @@ -9074,9 +9125,9 @@ 12 - 2 - 3 - 910 + 47 + 48 + 12 @@ -9084,6 +9135,17 @@ + + isInterface + 21473562 + + + id + 21473562 + + + + isRecord 417 @@ -9096,43 +9158,19 @@ - interfaces - 23200100 + fielddecls + 210035 id - 23200100 - - - nodeName - 8705320 + 210035 parentid - 430271 - - - sourceid - 2787162 + 24609 - - id - nodeName - - - 12 - - - 1 - 2 - 23200100 - - - - - id parentid @@ -9143,106 +9181,7 @@ 1 2 - 23200100 - - - - - - - id - sourceid - - - 12 - - - 1 - 2 - 23200100 - - - - - - - nodeName - id - - - 12 - - - 1 - 2 - 6834406 - - - 2 - 3 - 1079521 - - - 3 - 25 - 655011 - - - 25 - 345 - 136380 - - - - - - - nodeName - parentid - - - 12 - - - 1 - 2 - 7996524 - - - 2 - 4 - 695349 - - - 4 - 7 - 13445 - - - - - - - nodeName - sourceid - - - 12 - - - 1 - 2 - 7967711 - - - 2 - 4 - 718400 - - - 4 - 7 - 19208 + 210035 @@ -9258,335 +9197,52 @@ 1 2 - 113330 + 6180 2 3 - 55704 + 2975 3 4 - 48021 + 2769 4 - 5 - 26891 + 6 + 1694 - 5 - 8 - 36496 - - - 8 - 13 - 34575 - - - 13 - 18 - 34575 - - - 18 - 41 - 32654 - - - 42 - 182 - 32654 - - - 187 - 4152 - 15366 - - - - - - - parentid - nodeName - - - 12 - - - 1 - 2 - 113330 - - - 2 - 3 - 55704 - - - 3 - 4 - 48021 - - - 4 - 5 - 38417 - - - 5 + 6 7 - 24971 + 2563 7 - 10 - 32654 + 9 + 938 - 10 + 9 + 12 + 1922 + + + 12 15 - 36496 + 1877 15 - 28 - 32654 + 24 + 1854 - 30 - 94 - 32654 - - - 100 - 1213 - 15366 - - - - - - - parentid - sourceid - - - 12 - - - 1 - 2 - 140222 - - - 2 - 3 - 65309 - - - 3 - 4 - 44179 - - - 4 - 5 - 34575 - - - 5 - 7 - 28812 - - - 7 - 9 - 34575 - - - 9 - 14 - 34575 - - - 14 - 26 - 32654 - - - 26 - 160 - 15366 - - - - - - - sourceid - id - - - 12 - - - 1 - 2 - 2391465 - - - 2 - 11 - 213215 - - - 11 - 1565 - 182481 - - - - - - - sourceid - nodeName - - - 12 - - - 1 - 2 - 2391465 - - - 2 - 6 - 217056 - - - 6 - 492 - 178639 - - - - - - - sourceid - parentid - - - 12 - - - 1 - 2 - 2787162 - - - - - - - - - fielddecls - 199475 - - - id - 199475 - - - parentid - 25503 - - - - - id - parentid - - - 12 - - - 1 - 2 - 199475 - - - - - - - parentid - id - - - 12 - - - 1 - 2 - 4554 - - - 2 - 3 - 5465 - - - 3 - 4 - 1821 - - - 4 - 6 - 1821 - - - 6 - 7 - 2732 - - - 7 - 9 - 1821 - - - 9 - 10 - 910 - - - 10 - 11 - 1821 - - - 13 - 18 - 1821 - - - 19 - 20 - 1821 - - - 57 - 58 - 910 + 24 + 145 + 1831 @@ -9596,19 +9252,19 @@ fieldDeclaredIn - 199475 + 210035 fieldId - 199475 + 135178 fieldDeclId - 199475 + 210035 pos - 910 + 22 @@ -9622,7 +9278,17 @@ 1 2 - 199475 + 94498 + + + 2 + 3 + 6501 + + + 3 + 4 + 34177 @@ -9638,7 +9304,7 @@ 1 2 - 199475 + 135178 @@ -9654,7 +9320,7 @@ 1 2 - 199475 + 210035 @@ -9670,7 +9336,7 @@ 1 2 - 199475 + 210035 @@ -9684,9 +9350,9 @@ 12 - 219 - 220 - 910 + 5905 + 5906 + 22 @@ -9700,9 +9366,9 @@ 12 - 219 - 220 - 910 + 9175 + 9176 + 22 @@ -9712,27 +9378,27 @@ fields - 19350704 + 2886451 id - 19350704 + 2886451 nodeName - 13628474 + 2508459 typeid - 3038794 + 182623 parentid - 4089502 + 249278 sourceid - 19350704 + 2886451 @@ -9746,7 +9412,7 @@ 1 2 - 19350704 + 2886451 @@ -9762,7 +9428,7 @@ 1 2 - 19350704 + 2886451 @@ -9778,7 +9444,7 @@ 1 2 - 19350704 + 2886451 @@ -9794,7 +9460,7 @@ 1 2 - 19350704 + 2886451 @@ -9810,17 +9476,12 @@ 1 2 - 12016876 + 2356342 2 - 3 - 1123700 - - - 3 - 722 - 487897 + 302 + 152116 @@ -9836,17 +9497,12 @@ 1 2 - 12416414 + 2425714 2 - 5 - 1085283 - - - 5 - 160 - 126776 + 183 + 82744 @@ -9862,17 +9518,12 @@ 1 2 - 12016876 + 2356342 2 - 3 - 1123700 - - - 3 - 722 - 487897 + 302 + 152116 @@ -9888,17 +9539,12 @@ 1 2 - 12016876 + 2356342 2 - 3 - 1123700 - - - 3 - 722 - 487897 + 302 + 152116 @@ -9914,27 +9560,27 @@ 1 2 - 2059157 + 124952 2 3 - 320782 + 21104 3 4 - 213215 + 10447 4 8 - 245869 + 14835 8 - 2588 - 199769 + 9650 + 11283 @@ -9950,202 +9596,237 @@ 1 2 - 2120625 + 130385 2 3 - 299653 - - - 3 - 4 - 199769 - - - 4 - 9 - 255473 - - - 9 - 2016 - 163272 - - - - - - - typeid - parentid - - - 12 - - - 1 - 2 - 2706486 - - - 2 - 4 - 251632 - - - 4 - 1014 - 80675 - - - - - - - typeid - sourceid - - - 12 - - - 1 - 2 - 2059157 - - - 2 - 3 - 320782 - - - 3 - 4 - 213215 - - - 4 - 8 - 245869 - - - 8 - 2588 - 199769 - - - - - - - parentid - id - - - 12 - - - 1 - 2 - 2427962 - - - 2 - 3 - 478293 - - - 3 - 4 - 303495 - - - 4 - 6 - 338070 - - - 6 - 13 - 330387 - - - 13 - 1610 - 211294 - - - - - - - parentid - nodeName - - - 12 - - - 1 - 2 - 2427962 - - - 2 - 3 - 478293 - - - 3 - 4 - 303495 - - - 4 - 6 - 338070 - - - 6 - 13 - 330387 - - - 13 - 1610 - 211294 - - - - - - - parentid - typeid - - - 12 - - - 1 - 2 - 3031110 - - - 2 - 3 - 595465 + 17969 3 5 - 347674 + 16716 5 - 76 - 115251 + 20 + 13790 + + + 22 + 8913 + 3761 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 154205 + + + 2 + 3 + 18596 + + + 3 + 679 + 9820 + + + + + + + typeid + sourceid + + + 12 + + + 1 + 2 + 124952 + + + 2 + 3 + 21104 + + + 3 + 4 + 10447 + + + 4 + 8 + 14835 + + + 8 + 9650 + 11283 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 115132 + + + 2 + 3 + 25074 + + + 3 + 4 + 20477 + + + 4 + 5 + 15253 + + + 5 + 6 + 12328 + + + 6 + 8 + 18387 + + + 8 + 14 + 19641 + + + 14 + 93 + 18805 + + + 95 + 1772 + 4179 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 115132 + + + 2 + 3 + 25074 + + + 3 + 4 + 20477 + + + 4 + 5 + 15253 + + + 5 + 6 + 12328 + + + 6 + 8 + 18387 + + + 8 + 14 + 19641 + + + 14 + 93 + 18805 + + + 95 + 1772 + 4179 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 165280 + + + 2 + 3 + 39909 + + + 3 + 4 + 20895 + + + 4 + 7 + 18805 + + + 7 + 27 + 4387 @@ -10161,32 +9842,47 @@ 1 2 - 2427962 + 115132 2 3 - 478293 + 25074 3 4 - 303495 + 20477 4 + 5 + 15253 + + + 5 6 - 338070 + 12328 6 - 13 - 330387 + 8 + 18387 - 13 - 1610 - 211294 + 8 + 14 + 19641 + + + 14 + 93 + 18805 + + + 95 + 1772 + 4179 @@ -10202,7 +9898,7 @@ 1 2 - 19350704 + 2886451 @@ -10218,7 +9914,7 @@ 1 2 - 19350704 + 2886451 @@ -10234,7 +9930,7 @@ 1 2 - 19350704 + 2886451 @@ -10250,7 +9946,7 @@ 1 2 - 19350704 + 2886451 @@ -10260,15 +9956,15 @@ fieldsKotlinType - 19350704 + 2667261 id - 19350704 + 2667261 kttypeid - 1920 + 208 @@ -10282,7 +9978,7 @@ 1 2 - 19350704 + 2667261 @@ -10296,9 +9992,9 @@ 12 - 10074 - 10075 - 1920 + 12765 + 12766 + 208 @@ -10308,31 +10004,31 @@ constrs - 8006128 + 1103682 id - 8006128 + 1103682 nodeName - 4333451 + 597980 signature - 6803672 + 938261 typeid - 3841 + 524 parentid - 5639633 + 777558 sourceid - 5720309 + 788044 @@ -10346,7 +10042,7 @@ 1 2 - 8006128 + 1103682 @@ -10362,7 +10058,7 @@ 1 2 - 8006128 + 1103682 @@ -10378,7 +10074,7 @@ 1 2 - 8006128 + 1103682 @@ -10394,7 +10090,7 @@ 1 2 - 8006128 + 1103682 @@ -10410,7 +10106,7 @@ 1 2 - 8006128 + 1103682 @@ -10426,27 +10122,27 @@ 1 2 - 2623889 + 363874 2 3 - 1085283 + 145759 3 4 - 259315 + 38274 4 - 11 - 326545 + 12 + 45615 - 11 + 12 36 - 38417 + 4456 @@ -10462,22 +10158,22 @@ 1 2 - 2977327 + 412373 2 3 - 868226 + 116397 3 5 - 341912 + 49285 5 19 - 145985 + 19923 @@ -10493,7 +10189,7 @@ 1 2 - 4333451 + 597980 @@ -10509,17 +10205,17 @@ 1 2 - 3764878 + 520120 2 3 - 401458 + 54528 3 36 - 167114 + 23332 @@ -10535,22 +10231,22 @@ 1 2 - 2737220 + 379603 2 3 - 1083362 + 145497 3 5 - 353437 + 51120 5 32 - 159431 + 21759 @@ -10566,12 +10262,12 @@ 1 2 - 6302329 + 869575 2 36 - 501343 + 68685 @@ -10587,7 +10283,7 @@ 1 2 - 6803672 + 938261 @@ -10603,7 +10299,7 @@ 1 2 - 6803672 + 938261 @@ -10619,12 +10315,12 @@ 1 2 - 6302329 + 869575 2 36 - 501343 + 68685 @@ -10640,12 +10336,12 @@ 1 2 - 6461760 + 891597 2 23 - 341912 + 46664 @@ -10661,12 +10357,12 @@ 22 23 - 1920 + 262 - 4146 - 4147 - 1920 + 4188 + 4189 + 262 @@ -10682,12 +10378,12 @@ 1 2 - 1920 + 262 - 2255 - 2256 - 1920 + 2280 + 2281 + 262 @@ -10703,12 +10399,12 @@ 1 2 - 1920 + 262 - 3541 - 3542 - 1920 + 3578 + 3579 + 262 @@ -10724,12 +10420,12 @@ 22 23 - 1920 + 262 - 2914 - 2915 - 1920 + 2944 + 2945 + 262 @@ -10745,12 +10441,12 @@ 22 23 - 1920 + 262 - 2956 - 2957 - 1920 + 2984 + 2985 + 262 @@ -10766,22 +10462,22 @@ 1 2 - 4256617 + 588281 2 3 - 895118 + 120068 3 6 - 434113 + 61869 6 19 - 53783 + 7340 @@ -10797,7 +10493,7 @@ 1 2 - 5639633 + 777558 @@ -10813,22 +10509,22 @@ 1 2 - 4256617 + 588281 2 3 - 895118 + 120068 3 6 - 434113 + 61869 6 19 - 53783 + 7340 @@ -10844,7 +10540,7 @@ 1 2 - 5639633 + 777558 @@ -10860,22 +10556,22 @@ 1 2 - 4256617 + 588281 2 3 - 895118 + 120068 3 6 - 434113 + 61869 6 19 - 53783 + 7340 @@ -10891,12 +10587,12 @@ 1 2 - 5357267 + 737710 2 - 209 - 363041 + 219 + 50334 @@ -10912,12 +10608,12 @@ 1 2 - 5357267 + 737710 2 - 172 - 363041 + 178 + 50334 @@ -10933,12 +10629,12 @@ 1 2 - 5357267 + 737710 2 - 172 - 363041 + 178 + 50334 @@ -10954,7 +10650,7 @@ 1 2 - 5720309 + 788044 @@ -10970,12 +10666,12 @@ 1 2 - 5357267 + 737710 2 - 209 - 363041 + 219 + 50334 @@ -10985,15 +10681,15 @@ constrsKotlinType - 8006128 + 1103682 id - 8006128 + 1103682 kttypeid - 1920 + 262 @@ -11007,7 +10703,7 @@ 1 2 - 8006128 + 1103682 @@ -11021,9 +10717,9 @@ 12 - 4168 - 4169 - 1920 + 4210 + 4211 + 262 @@ -11033,31 +10729,31 @@ methods - 109719302 + 15113893 id - 109719302 + 15113893 nodeName - 22908130 + 3165025 signature - 33369112 + 4608463 typeid - 13338425 + 1843228 parentid - 12810189 + 1782931 sourceid - 67091663 + 9250220 @@ -11071,7 +10767,7 @@ 1 2 - 109719302 + 15113893 @@ -11087,7 +10783,7 @@ 1 2 - 109719302 + 15113893 @@ -11103,7 +10799,7 @@ 1 2 - 109719302 + 15113893 @@ -11119,7 +10815,7 @@ 1 2 - 109719302 + 15113893 @@ -11135,7 +10831,7 @@ 1 2 - 109719302 + 15113893 @@ -11151,32 +10847,32 @@ 1 2 - 13324979 + 1845587 2 3 - 4070294 + 561540 3 4 - 1573181 + 218114 4 7 - 2026503 + 277624 7 - 56 - 1719166 + 61 + 238038 - 57 + 61 1769 - 194006 + 24118 @@ -11192,17 +10888,17 @@ 1 2 - 19150935 + 2647264 2 3 - 2228193 + 306986 3 - 298 - 1529001 + 308 + 210774 @@ -11218,22 +10914,22 @@ 1 2 - 19179748 + 2651983 2 3 - 1872834 + 257176 3 25 - 1726849 + 238300 25 - 741 - 128697 + 752 + 17564 @@ -11249,27 +10945,27 @@ 1 2 - 14028012 + 1943110 2 3 - 3889733 + 536111 3 4 - 1502109 + 207628 4 7 - 1817129 + 249311 7 - 1099 - 1671144 + 1120 + 228863 @@ -11285,27 +10981,27 @@ 1 2 - 13743725 + 1905621 2 3 - 4283509 + 589067 3 4 - 1544368 + 213396 4 7 - 1857467 + 254292 7 - 800 - 1479059 + 811 + 202647 @@ -11321,27 +11017,27 @@ 1 2 - 22735253 + 3143266 2 3 - 5434102 + 751080 3 5 - 2635414 + 358893 5 - 157 - 2502875 + 152 + 345785 - 157 - 1096 - 61467 + 155 + 1117 + 9437 @@ -11357,7 +11053,7 @@ 1 2 - 33369112 + 4608463 @@ -11373,17 +11069,17 @@ 1 2 - 29957672 + 4140250 2 5 - 2650781 + 362301 5 - 739 - 760659 + 750 + 105911 @@ -11399,27 +11095,27 @@ 1 2 - 22741015 + 3144052 2 3 - 5432181 + 750818 3 5 - 2631572 + 358369 5 - 157 - 2502875 + 152 + 345785 - 157 - 1096 - 61467 + 155 + 1117 + 9437 @@ -11435,22 +11131,22 @@ 1 2 - 23365294 + 3232137 2 3 - 5656921 + 780704 3 6 - 2900492 + 397692 6 - 795 - 1446404 + 806 + 197928 @@ -11466,32 +11162,32 @@ 1 2 - 6603903 + 915453 2 3 - 2729536 + 377244 3 4 - 1208218 + 167256 4 6 - 1119859 + 153099 6 15 - 1019974 + 140254 15 - 10335 - 656932 + 10397 + 89919 @@ -11507,22 +11203,22 @@ 1 2 - 8714924 + 1203826 2 3 - 2620047 + 363612 3 6 - 1167880 + 160964 6 - 2888 - 835572 + 2934 + 114824 @@ -11538,22 +11234,22 @@ 1 2 - 8565097 + 1183115 2 3 - 2602760 + 361514 3 6 - 1210139 + 165945 6 - 4142 - 960428 + 4201 + 132651 @@ -11569,27 +11265,27 @@ 1 2 - 7714158 + 1068028 2 3 - 2869759 + 396119 3 4 - 1108333 + 153886 4 8 - 1069916 + 146283 8 - 2865 - 576256 + 2901 + 78909 @@ -11605,32 +11301,32 @@ 1 2 - 7166714 + 992265 2 3 - 2524004 + 349717 3 4 - 1096808 + 151789 4 6 - 1094888 + 149167 6 16 - 1016132 + 140254 16 - 6435 - 439876 + 6502 + 60034 @@ -11646,52 +11342,52 @@ 1 2 - 3630418 + 511993 2 3 - 1456008 + 206055 3 4 - 1164038 + 160964 4 5 - 735687 + 100930 5 7 - 1021895 + 139992 7 10 - 1106413 + 153099 10 13 - 1146751 + 159915 13 21 - 1181326 + 162013 21 40 - 1021895 + 140778 40 319 - 345754 + 47188 @@ -11707,52 +11403,52 @@ 1 2 - 3678439 + 518547 2 3 - 1457929 + 206317 3 4 - 1231268 + 170140 4 5 - 791392 + 108533 5 7 - 960428 + 131865 7 10 - 1183247 + 163324 10 13 - 1102571 + 153886 13 18 - 849018 + 116397 18 - 26 - 968111 + 27 + 136846 - 26 + 27 290 - 587781 + 77074 @@ -11768,52 +11464,52 @@ 1 2 - 3630418 + 511993 2 3 - 1456008 + 206055 3 4 - 1164038 + 160964 4 5 - 735687 + 100930 5 7 - 1021895 + 139992 7 10 - 1106413 + 153099 10 13 - 1146751 + 159915 13 21 - 1181326 + 162013 21 40 - 1021895 + 140778 40 319 - 345754 + 47188 @@ -11829,52 +11525,52 @@ 1 2 - 4348818 + 611613 2 3 - 1757583 + 246690 3 4 - 1436800 + 198453 4 5 - 922010 + 126621 5 6 - 743371 + 102503 6 7 - 564731 + 77074 7 8 - 879752 + 122951 8 11 - 1160197 + 160178 11 - 31 - 964269 + 35 + 133962 - 33 + 37 78 - 32654 + 2883 @@ -11890,52 +11586,52 @@ 1 2 - 3630418 + 511993 2 3 - 1456008 + 206055 3 4 - 1164038 + 160964 4 5 - 735687 + 100930 5 7 - 1021895 + 139992 7 10 - 1106413 + 153099 10 13 - 1146751 + 159915 13 21 - 1181326 + 162013 21 40 - 1021895 + 140778 40 319 - 345754 + 47188 @@ -11951,17 +11647,17 @@ 1 2 - 61836200 + 8524569 2 50 - 5032643 + 695241 52 - 286 - 222819 + 296 + 30410 @@ -11977,7 +11673,7 @@ 1 2 - 67091663 + 9250220 @@ -11993,12 +11689,12 @@ 1 2 - 66767038 + 9204343 2 - 284 - 324624 + 294 + 45877 @@ -12014,12 +11710,12 @@ 1 2 - 65030584 + 8968401 2 - 209 - 2061078 + 219 + 281819 @@ -12035,17 +11731,17 @@ 1 2 - 61836200 + 8524569 2 50 - 5032643 + 695241 52 - 286 - 222819 + 296 + 30410 @@ -12055,15 +11751,15 @@ methodsKotlinType - 109719302 + 15113893 id - 109719302 + 15113893 kttypeid - 1920 + 262 @@ -12077,7 +11773,7 @@ 1 2 - 109719302 + 15113893 @@ -12091,9 +11787,9 @@ 12 - 57120 - 57121 - 1920 + 57652 + 57653 + 262 @@ -12103,27 +11799,27 @@ params - 120852585 + 16587479 id - 120852585 + 16587479 typeid - 12833239 + 1772707 pos - 42258 + 5767 parentid - 65007534 + 8942448 sourceid - 73639861 + 10111931 @@ -12137,7 +11833,7 @@ 1 2 - 120852585 + 16587479 @@ -12153,7 +11849,7 @@ 1 2 - 120852585 + 16587479 @@ -12169,7 +11865,7 @@ 1 2 - 120852585 + 16587479 @@ -12185,7 +11881,7 @@ 1 2 - 120852585 + 16587479 @@ -12201,37 +11897,37 @@ 1 2 - 6763334 + 935901 2 3 - 1945827 + 269759 3 4 - 948902 + 130816 4 6 - 1148671 + 158080 6 12 - 1018053 + 138943 12 326 - 966190 + 133438 343 - 6738 - 42258 + 6748 + 5767 @@ -12247,22 +11943,22 @@ 1 2 - 10436011 + 1442651 2 3 - 1342678 + 185345 3 - 8 - 964269 + 9 + 136321 - 8 + 9 17 - 90280 + 8389 @@ -12278,32 +11974,32 @@ 1 2 - 7005362 + 968933 2 3 - 1895885 + 262943 3 4 - 975794 + 134486 4 6 - 1087204 + 149691 6 13 - 1008449 + 137894 13 - 4326 - 860543 + 4336 + 118757 @@ -12319,32 +12015,32 @@ 1 2 - 7216656 + 998032 2 3 - 1788317 + 248787 3 4 - 996924 + 136846 4 6 - 1117938 + 153362 6 13 - 1002686 + 137894 13 5757 - 710716 + 97784 @@ -12360,57 +12056,57 @@ 1 2 - 3841 + 524 50 53 - 3841 + 524 104 106 - 3841 + 524 157 165 - 3841 + 524 214 231 - 3841 + 524 291 315 - 3841 + 524 485 606 - 3841 + 524 804 1067 - 3841 + 524 1445 2015 - 3841 + 524 - 3084 - 5199 - 3841 + 3087 + 5218 + 524 - 12689 - 33844 - 3841 + 12756 + 34112 + 524 @@ -12426,57 +12122,57 @@ 1 2 - 3841 + 524 2 5 - 3841 + 524 6 7 - 3841 + 524 11 14 - 3841 + 524 15 20 - 3841 + 524 27 37 - 3841 + 524 57 75 - 3841 + 524 97 153 - 3841 + 524 201 289 - 3841 + 524 - 403 - 777 - 3841 + 406 + 789 + 524 - 1979 - 5089 - 3841 + 1997 + 5152 + 524 @@ -12492,57 +12188,57 @@ 1 2 - 3841 + 524 50 53 - 3841 + 524 104 106 - 3841 + 524 157 165 - 3841 + 524 214 231 - 3841 + 524 291 315 - 3841 + 524 485 606 - 3841 + 524 804 1067 - 3841 + 524 1445 2015 - 3841 + 524 - 3084 - 5199 - 3841 + 3087 + 5218 + 524 - 12689 - 33844 - 3841 + 12756 + 34112 + 524 @@ -12558,57 +12254,57 @@ 1 2 - 3841 + 524 2 5 - 3841 + 524 6 8 - 3841 + 524 11 15 - 3841 + 524 16 29 - 3841 + 524 39 63 - 3841 + 524 101 144 - 3841 + 524 210 386 - 3841 + 524 628 1069 - 3841 + 524 - 1955 - 3748 - 3841 + 1958 + 3765 + 524 - 8555 - 21355 - 3841 + 8596 + 21529 + 524 @@ -12624,27 +12320,27 @@ 1 2 - 40633790 + 5598369 2 3 - 14389133 + 1976404 3 4 - 4060689 + 558395 4 10 - 4992305 + 682133 10 23 - 931615 + 127146 @@ -12660,17 +12356,17 @@ 1 2 - 45326442 + 6239868 2 3 - 14805959 + 2032767 3 23 - 4875132 + 669811 @@ -12686,27 +12382,27 @@ 1 2 - 40633790 + 5598369 2 3 - 14389133 + 1976404 3 4 - 4060689 + 558395 4 10 - 4992305 + 682133 10 23 - 931615 + 127146 @@ -12722,27 +12418,27 @@ 1 2 - 40633790 + 5598369 2 3 - 14389133 + 1976404 3 4 - 4060689 + 558395 4 10 - 4992305 + 682133 10 23 - 931615 + 127146 @@ -12758,12 +12454,12 @@ 1 2 - 68584168 + 9415117 2 - 286 - 5055693 + 296 + 696814 @@ -12779,12 +12475,12 @@ 1 2 - 71932220 + 9877563 2 - 286 - 1707641 + 296 + 234368 @@ -12800,7 +12496,7 @@ 1 2 - 73639861 + 10111931 @@ -12816,12 +12512,12 @@ 1 2 - 68584168 + 9415117 2 - 286 - 5055693 + 296 + 696814 @@ -12831,15 +12527,15 @@ paramsKotlinType - 120852585 + 16587479 id - 120852585 + 16587479 kttypeid - 1920 + 262 @@ -12853,7 +12549,7 @@ 1 2 - 120852585 + 16587479 @@ -12867,9 +12563,9 @@ 12 - 62916 - 62917 - 1920 + 63273 + 63274 + 262 @@ -12879,15 +12575,15 @@ paramName - 15639610 + 2140514 id - 15639610 + 2140514 nodeName - 2335761 + 319307 @@ -12901,7 +12597,7 @@ 1 2 - 15639610 + 2140514 @@ -12917,37 +12613,37 @@ 1 2 - 998845 + 136321 2 3 - 451401 + 61869 3 4 - 249711 + 34342 4 5 - 170956 + 23332 5 8 - 182481 + 24904 8 - 18 - 176718 + 19 + 24118 - 18 - 769 - 105647 + 19 + 770 + 14418 @@ -12957,11 +12653,11 @@ isVarargsParam - 945061 + 813764 param - 945061 + 813764 @@ -13184,11 +12880,11 @@ isAnnotType - 29260 + 35103 interfaceid - 29260 + 35103 @@ -13472,49 +13168,49 @@ isEnumType - 397617 + 56888 classid - 397617 + 56888 isEnumConst - 3081053 + 435967 fieldid - 3081053 + 435967 typeVars - 6288883 + 864332 id - 6288883 + 864332 nodeName - 86438 + 11797 pos - 7683 + 1048 kind - 1920 + 262 parentid - 4444861 + 612137 @@ -13528,7 +13224,7 @@ 1 2 - 6288883 + 864332 @@ -13544,7 +13240,7 @@ 1 2 - 6288883 + 864332 @@ -13560,7 +13256,7 @@ 1 2 - 6288883 + 864332 @@ -13576,7 +13272,7 @@ 1 2 - 6288883 + 864332 @@ -13592,47 +13288,47 @@ 1 2 - 21129 + 2883 2 3 - 11525 + 1572 3 4 - 9604 + 1310 4 7 - 7683 + 1048 7 10 - 7683 + 1048 10 28 - 7683 + 1048 36 - 69 - 7683 + 70 + 1048 71 412 - 7683 + 1048 - 603 - 710 - 5762 + 605 + 724 + 786 @@ -13648,22 +13344,22 @@ 1 2 - 51863 + 7078 2 3 - 23050 + 3145 3 4 - 9604 + 1310 4 5 - 1920 + 262 @@ -13679,7 +13375,7 @@ 1 2 - 86438 + 11797 @@ -13695,47 +13391,47 @@ 1 2 - 21129 + 2883 2 3 - 11525 + 1572 3 4 - 9604 + 1310 4 7 - 7683 + 1048 7 10 - 7683 + 1048 10 28 - 7683 + 1048 36 - 69 - 7683 + 70 + 1048 71 412 - 7683 + 1048 - 603 - 710 - 5762 + 605 + 724 + 786 @@ -13751,22 +13447,22 @@ 6 7 - 1920 + 262 89 90 - 1920 + 262 - 865 - 866 - 1920 + 867 + 868 + 262 - 2314 - 2315 - 1920 + 2335 + 2336 + 262 @@ -13782,22 +13478,22 @@ 2 3 - 1920 + 262 13 14 - 1920 + 262 21 22 - 1920 + 262 34 35 - 1920 + 262 @@ -13813,7 +13509,7 @@ 1 2 - 7683 + 1048 @@ -13829,22 +13525,22 @@ 6 7 - 1920 + 262 89 90 - 1920 + 262 - 865 - 866 - 1920 + 867 + 868 + 262 - 2314 - 2315 - 1920 + 2335 + 2336 + 262 @@ -13858,9 +13554,9 @@ 12 - 3274 - 3275 - 1920 + 3297 + 3298 + 262 @@ -13876,7 +13572,7 @@ 45 46 - 1920 + 262 @@ -13892,7 +13588,7 @@ 4 5 - 1920 + 262 @@ -13906,9 +13602,9 @@ 12 - 2314 - 2315 - 1920 + 2335 + 2336 + 262 @@ -13924,17 +13620,17 @@ 1 2 - 2783320 + 384846 2 3 - 1490584 + 203958 3 5 - 170956 + 23332 @@ -13950,17 +13646,17 @@ 1 2 - 2783320 + 384846 2 3 - 1490584 + 203958 3 5 - 170956 + 23332 @@ -13976,17 +13672,17 @@ 1 2 - 2783320 + 384846 2 3 - 1490584 + 203958 3 5 - 170956 + 23332 @@ -14002,7 +13698,7 @@ 1 2 - 4444861 + 612137 @@ -14012,19 +13708,19 @@ wildcards - 3338447 + 458250 id - 3338447 + 458250 nodeName - 533998 + 74976 kind - 3841 + 524 @@ -14038,7 +13734,7 @@ 1 2 - 3338447 + 458250 @@ -14054,7 +13750,7 @@ 1 2 - 3338447 + 458250 @@ -14070,22 +13766,22 @@ 1 2 - 397617 + 56363 2 3 - 55704 + 7340 3 7 - 44179 + 6029 7 170 - 36496 + 5243 @@ -14101,7 +13797,7 @@ 1 2 - 533998 + 74976 @@ -14115,14 +13811,14 @@ 12 - 791 - 792 - 1920 + 795 + 796 + 262 - 947 - 948 - 1920 + 953 + 954 + 262 @@ -14136,14 +13832,14 @@ 12 - 91 - 92 - 1920 + 94 + 95 + 262 - 187 - 188 - 1920 + 192 + 193 + 262 @@ -14153,23 +13849,23 @@ typeBounds - 4229725 + 581989 id - 4229725 + 581989 typeid - 2852471 + 392449 pos - 1920 + 262 parentid - 4229725 + 581989 @@ -14183,7 +13879,7 @@ 1 2 - 4229725 + 581989 @@ -14199,7 +13895,7 @@ 1 2 - 4229725 + 581989 @@ -14215,7 +13911,7 @@ 1 2 - 4229725 + 581989 @@ -14231,17 +13927,17 @@ 1 2 - 2091812 + 288635 2 3 - 695349 + 94900 3 52 - 65309 + 8913 @@ -14257,7 +13953,7 @@ 1 2 - 2852471 + 392449 @@ -14273,17 +13969,17 @@ 1 2 - 2091812 + 288635 2 3 - 695349 + 94900 3 52 - 65309 + 8913 @@ -14297,9 +13993,9 @@ 12 - 2202 - 2203 - 1920 + 2220 + 2221 + 262 @@ -14313,9 +14009,9 @@ 12 - 1485 - 1486 - 1920 + 1497 + 1498 + 262 @@ -14329,9 +14025,9 @@ 12 - 2202 - 2203 - 1920 + 2220 + 2221 + 262 @@ -14347,7 +14043,7 @@ 1 2 - 4229725 + 581989 @@ -14363,7 +14059,7 @@ 1 2 - 4229725 + 581989 @@ -14379,7 +14075,7 @@ 1 2 - 4229725 + 581989 @@ -14685,37 +14381,37 @@ isParameterized - 27045654 + 22244248 memberid - 27045654 + 22244248 isRaw - 731846 + 100406 memberid - 731846 + 100406 erasure - 27777500 + 22246872 memberid - 27777500 + 22246872 erasureid - 954665 + 2976 @@ -14729,7 +14425,7 @@ 1 2 - 27777500 + 22246872 @@ -14745,62 +14441,52 @@ 1 2 - 142143 + 184 2 3 - 138301 + 456 3 - 4 - 86438 - - - 4 5 - 57625 + 260 5 6 - 65309 + 734 6 - 8 - 69150 + 9 + 236 - 8 - 10 - 61467 + 9 + 23 + 254 - 10 - 15 - 72992 + 23 + 98 + 225 - 15 - 22 - 76834 + 101 + 288 + 225 - 22 - 44 - 74913 + 345 + 2541 + 225 - 46 - 124 - 72992 - - - 169 - 1564 - 36496 + 2940 + 448198 + 173 @@ -14810,15 +14496,15 @@ isAnonymClass - 174213 + 157916 classid - 174213 + 157916 parent - 174213 + 157916 @@ -14832,7 +14518,7 @@ 1 2 - 174213 + 157916 @@ -14848,7 +14534,7 @@ 1 2 - 174213 + 157916 @@ -14858,15 +14544,15 @@ isLocalClassOrInterface - 3841 + 3533 typeid - 3841 + 3533 parent - 3841 + 3533 @@ -14880,7 +14566,7 @@ 1 2 - 3841 + 3533 @@ -14896,7 +14582,7 @@ 1 2 - 3841 + 3533 @@ -14917,15 +14603,15 @@ lambdaKind - 167982 + 152268 exprId - 167982 + 152268 bodyKind - 13 + 12 @@ -14939,7 +14625,7 @@ 1 2 - 167982 + 152268 @@ -14955,7 +14641,7 @@ 12267 12268 - 13 + 12 @@ -14965,27 +14651,27 @@ arrays - 1375332 + 190588 id - 1375332 + 190588 nodeName - 831730 + 115349 elementtypeid - 1365728 + 189277 dimension - 3841 + 524 componenttypeid - 1375332 + 190588 @@ -14999,7 +14685,7 @@ 1 2 - 1375332 + 190588 @@ -15015,7 +14701,7 @@ 1 2 - 1375332 + 190588 @@ -15031,7 +14717,7 @@ 1 2 - 1375332 + 190588 @@ -15047,7 +14733,7 @@ 1 2 - 1375332 + 190588 @@ -15063,17 +14749,17 @@ 1 2 - 664616 + 92279 2 3 - 140222 + 19137 3 87 - 26891 + 3932 @@ -15089,17 +14775,17 @@ 1 2 - 664616 + 92279 2 3 - 140222 + 19137 3 87 - 26891 + 3932 @@ -15115,7 +14801,7 @@ 1 2 - 831730 + 115349 @@ -15131,17 +14817,17 @@ 1 2 - 664616 + 92279 2 3 - 140222 + 19137 3 87 - 26891 + 3932 @@ -15157,12 +14843,12 @@ 1 2 - 1356124 + 187966 2 3 - 9604 + 1310 @@ -15178,12 +14864,12 @@ 1 2 - 1356124 + 187966 2 3 - 9604 + 1310 @@ -15199,12 +14885,12 @@ 1 2 - 1356124 + 187966 2 3 - 9604 + 1310 @@ -15220,12 +14906,12 @@ 1 2 - 1356124 + 187966 2 3 - 9604 + 1310 @@ -15241,12 +14927,12 @@ 5 6 - 1920 + 262 - 711 - 712 - 1920 + 722 + 723 + 262 @@ -15262,12 +14948,12 @@ 5 6 - 1920 + 262 - 428 - 429 - 1920 + 435 + 436 + 262 @@ -15283,12 +14969,12 @@ 5 6 - 1920 + 262 - 711 - 712 - 1920 + 722 + 723 + 262 @@ -15304,12 +14990,12 @@ 5 6 - 1920 + 262 - 711 - 712 - 1920 + 722 + 723 + 262 @@ -15325,7 +15011,7 @@ 1 2 - 1375332 + 190588 @@ -15341,7 +15027,7 @@ 1 2 - 1375332 + 190588 @@ -15357,7 +15043,7 @@ 1 2 - 1375332 + 190588 @@ -15373,7 +15059,7 @@ 1 2 - 1375332 + 190588 @@ -15383,15 +15069,15 @@ enclInReftype - 4051085 + 564162 child - 4051085 + 564162 parent - 1125621 + 156245 @@ -15405,7 +15091,7 @@ 1 2 - 4051085 + 564162 @@ -15421,32 +15107,32 @@ 1 2 - 666537 + 92803 2 3 - 176718 + 24642 3 4 - 86438 + 11797 4 - 6 - 82596 + 7 + 14418 - 6 - 17 - 84517 + 7 + 55 + 11797 - 17 + 55 265 - 28812 + 786 @@ -15456,15 +15142,15 @@ extendsReftype - 34389087 + 27274828 id1 - 33104034 + 22257941 id2 - 13251986 + 17181115 @@ -15478,12 +15164,12 @@ 1 2 - 32118635 + 20991189 2 - 10 - 985399 + 6 + 1266751 @@ -15499,17 +15185,17 @@ 1 2 - 12030322 + 13982285 2 - 5 - 1023816 + 3 + 1947557 - 5 - 8715 - 197848 + 3 + 937651 + 1251272 @@ -15519,15 +15205,15 @@ implInterface - 14423708 + 3052687 id1 - 8255839 + 757298 id2 - 4487119 + 2275569 @@ -15541,27 +15227,37 @@ 1 2 - 4223962 + 210035 2 3 - 2829421 + 50057 3 4 - 276603 + 67415 4 5 - 920090 + 62041 5 + 6 + 19333 + + + 6 7 - 5762 + 305943 + + + 7 + 10 + 42471 @@ -15577,17 +15273,12 @@ 1 2 - 4003064 + 2200149 2 - 4 - 366883 - - - 4 - 2275 - 117172 + 63705 + 75420 @@ -15597,15 +15288,15 @@ permits - 129 + 132 id1 - 31 + 30 id2 - 129 + 132 @@ -15619,12 +15310,12 @@ 1 2 - 2 + 3 2 3 - 8 + 3 3 @@ -15634,27 +15325,17 @@ 4 5 - 2 - - - 5 - 6 - 2 - - - 6 - 8 - 2 + 10 8 9 - 2 + 3 - 9 + 10 11 - 2 + 3 @@ -15670,7 +15351,7 @@ 1 2 - 129 + 132 @@ -15680,15 +15361,15 @@ hasModifier - 270713939 + 48527772 id1 - 180180147 + 24369293 id2 - 26891 + 63 @@ -15702,17 +15383,17 @@ 1 2 - 90230296 + 356153 2 3 - 89365911 + 23867801 3 4 - 583940 + 145338 @@ -15726,74 +15407,59 @@ 12 - 4 - 5 - 1920 + 22 + 23 + 5 - 14 - 15 - 1920 + 27 + 28 + 5 - 20 - 21 - 1920 + 100 + 101 + 5 - 21 - 22 - 1920 + 262 + 263 + 5 - 34 - 35 - 1920 + 712 + 713 + 5 - 50 - 51 - 1920 + 1374 + 1375 + 5 - 109 - 110 - 1920 + 11041 + 11042 + 5 - 219 - 220 - 1920 + 63640 + 63641 + 5 - 3864 - 3865 - 1920 + 242567 + 242568 + 5 - 7193 - 7194 - 1920 + 3864462 + 3864463 + 5 - 9195 - 9196 - 1920 - - - 14706 - 14707 - 1920 - - - 18810 - 18811 - 1920 - - - 86695 - 86696 - 1920 + 4211558 + 4211559 + 5 @@ -15803,23 +15469,23 @@ imports - 368550 + 441072 id - 368550 + 441072 holder - 58078 + 52468 name - 8794 + 4282 kind - 663 + 29 @@ -15833,7 +15499,7 @@ 1 2 - 368550 + 441072 @@ -15849,7 +15515,7 @@ 1 2 - 368550 + 441072 @@ -15865,7 +15531,7 @@ 1 2 - 368550 + 441072 @@ -15881,120 +15547,120 @@ 1 2 - 28375 + 20638 2 3 - 9292 + 8976 3 4 - 5475 + 4991 4 - 6 - 4646 + 5 + 3335 - 6 - 15 - 4480 - - - 15 - 54 - 4480 - - - 64 - 98 - 1327 - - - - - - - holder - name - - - 12 - - - 1 - 2 - 54593 - - - 2 + 5 7 - 3484 - - - - - - - holder - kind - - - 12 - - - 1 - 2 - 55091 - - - 2 - 3 - 2986 - - - - - - - name - id - - - 12 - - - 1 - 2 - 4148 - - - 2 - 3 - 1825 - - - 3 - 4 - 829 - - - 4 - 7 - 663 + 4096 7 - 26 - 663 + 12 + 4305 - 30 - 1962 - 663 + 12 + 32 + 3984 + + + 32 + 1529 + 2141 + + + + + + + holder + name + + + 12 + + + 1 + 2 + 50871 + + + 2 + 54 + 1596 + + + + + + + holder + kind + + + 12 + + + 1 + 2 + 51200 + + + 2 + 4 + 1268 + + + + + + + name + id + + + 12 + + + 1 + 2 + 2469 + + + 2 + 3 + 962 + + + 3 + 4 + 358 + + + 4 + 7 + 328 + + + 7 + 57945 + 164 @@ -16010,17 +15676,12 @@ 1 2 - 7301 + 4163 2 - 3 - 1161 - - - 3 - 337 - 331 + 6945 + 119 @@ -16036,12 +15697,12 @@ 1 2 - 8628 + 4275 3 4 - 165 + 7 @@ -16055,24 +15716,24 @@ 12 - 1 - 2 - 165 + 15 + 16 + 7 - 6 - 7 - 165 + 68 + 69 + 7 - 260 - 261 - 165 + 1170 + 1171 + 7 - 1954 - 1955 - 165 + 57861 + 57862 + 7 @@ -16086,24 +15747,24 @@ 12 - 1 - 2 - 165 + 10 + 11 + 7 - 3 - 4 - 165 + 25 + 26 + 7 - 31 - 32 - 165 + 257 + 258 + 7 - 333 - 334 - 165 + 6915 + 6916 + 7 @@ -16119,12 +15780,12 @@ 1 2 - 497 + 22 - 52 - 53 - 165 + 573 + 574 + 7 @@ -17973,7 +17634,7 @@ kttypeid - 10930 + 156277 @@ -18003,17 +17664,12 @@ 1 2 - 8197 + 152777 2 - 3 - 1821 - - - 8123 - 8124 - 910 + 584083 + 3500 @@ -18292,22 +17948,22 @@ when_if - 74334 + 56072 id - 74334 + 56072 when_branch_else - 76075 + 70057 id - 76075 + 70057 @@ -18352,12 +18008,12 @@ 1 2 - 162993 + 162995 2 3 - 33137 + 33136 3 @@ -18450,15 +18106,15 @@ propertyRefGetBinding - 8876 + 8437 id - 8876 + 8437 getter - 5366 + 5101 @@ -18472,7 +18128,7 @@ 1 2 - 8876 + 8437 @@ -18488,17 +18144,17 @@ 1 2 - 1951 + 1855 2 3 - 3328 + 3164 3 6 - 86 + 82 @@ -18556,15 +18212,15 @@ propertyRefSetBinding - 2600 + 2226 id - 2600 + 2226 setter - 1300 + 1094 @@ -18578,7 +18234,7 @@ 1 2 - 2600 + 2226 @@ -18591,10 +18247,20 @@ 12 + + 1 + 2 + 32 + 2 3 - 1300 + 994 + + + 3 + 5 + 67 @@ -19053,15 +18719,15 @@ localvarsKotlinType - 240107 + 149454 id - 240107 + 149454 kttypeid - 1920 + 2 @@ -19075,7 +18741,7 @@ 1 2 - 240107 + 149454 @@ -19089,9 +18755,9 @@ 12 - 125 - 126 - 1920 + 59940 + 59941 + 2 @@ -19340,11 +19006,11 @@ isOpen - 1 + 13 id - 1 + 13 @@ -19502,15 +19168,15 @@ requires - 1991 + 3190 id - 1991 + 3190 target - 995 + 377 @@ -19524,7 +19190,7 @@ 1 2 - 1991 + 3190 @@ -19540,17 +19206,52 @@ 1 2 - 663 + 33 2 3 - 165 + 40 + + + 3 + 4 + 23 + + + 4 + 5 + 23 + + + 5 + 6 + 33 6 - 7 - 165 + 9 + 10 + + + 9 + 10 + 142 + + + 10 + 11 + 30 + + + 11 + 29 + 30 + + + 56 + 73 + 6 @@ -19571,11 +19272,11 @@ isStatic - 1 + 33 id - 1 + 33 @@ -20991,15 +20692,15 @@ xmlEncoding - 1129463 + 154148 id - 1129463 + 154148 encoding - 1920 + 262 @@ -21013,7 +20714,7 @@ 1 2 - 1129463 + 154148 @@ -21029,7 +20730,7 @@ 588 589 - 1920 + 262 @@ -21387,27 +21088,27 @@ xmlElements - 150282022 + 20510401 id - 150282022 + 20510401 name - 476372 + 65015 parentid - 3876287 + 529033 idx - 1703799 + 232533 fileid - 1129463 + 154148 @@ -21421,7 +21122,7 @@ 1 2 - 150282022 + 20510401 @@ -21437,7 +21138,7 @@ 1 2 - 150282022 + 20510401 @@ -21453,7 +21154,7 @@ 1 2 - 150282022 + 20510401 @@ -21469,7 +21170,7 @@ 1 2 - 150282022 + 20510401 @@ -21485,57 +21186,57 @@ 1 2 - 149826 + 20448 2 3 - 57625 + 7864 3 4 - 23050 + 3145 4 6 - 42258 + 5767 6 8 - 34575 + 4718 8 9 - 17287 + 2359 9 10 - 32654 + 4456 10 18 - 40337 + 5505 18 48 - 36496 + 4980 52 250 - 36496 + 4980 342 73380 - 5762 + 786 @@ -21551,52 +21252,52 @@ 1 2 - 174797 + 23856 2 3 - 65309 + 8913 3 4 - 24971 + 3408 4 5 - 21129 + 2883 5 6 - 26891 + 3670 6 8 - 40337 + 5505 8 10 - 40337 + 5505 10 21 - 38417 + 5243 22 128 - 36496 + 4980 130 229 - 7683 + 1048 @@ -21612,37 +21313,37 @@ 1 2 - 263157 + 35915 2 3 - 69150 + 9437 3 4 - 34575 + 4718 4 6 - 28812 + 3932 6 9 - 28812 + 3932 9 38 - 36496 + 4980 45 888 - 15366 + 2097 @@ -21658,42 +21359,42 @@ 1 2 - 259315 + 35391 2 3 - 51863 + 7078 3 4 - 24971 + 3408 4 5 - 19208 + 2621 5 7 - 42258 + 5767 7 16 - 36496 + 4980 17 114 - 38417 + 5243 118 131 - 3841 + 524 @@ -21709,32 +21410,32 @@ 1 2 - 2358811 + 321929 2 3 - 605069 + 82579 3 4 - 251632 + 34342 4 8 - 301574 + 41158 8 777 - 316941 + 43255 777 888 - 42258 + 5767 @@ -21750,17 +21451,17 @@ 1 2 - 3200146 + 436754 2 3 - 411063 + 56101 3 17 - 265078 + 36177 @@ -21776,32 +21477,32 @@ 1 2 - 2358811 + 321929 2 3 - 605069 + 82579 3 4 - 251632 + 34342 4 8 - 301574 + 41158 8 777 - 316941 + 43255 777 888 - 42258 + 5767 @@ -21817,7 +21518,7 @@ 1 2 - 3876287 + 529033 @@ -21833,67 +21534,67 @@ 2 8 - 144064 + 19661 9 76 - 136380 + 18613 76 82 - 128697 + 17564 82 89 - 122934 + 16778 89 92 - 111409 + 15205 92 95 - 134459 + 18351 95 97 - 149826 + 20448 97 98 - 211294 + 28837 98 99 - 130618 + 17826 99 104 - 155589 + 21234 104 106 - 130618 + 17826 106 159 - 128697 + 17564 162 2019 - 19208 + 2621 @@ -21909,22 +21610,22 @@ 1 2 - 1381095 + 188491 2 5 - 126776 + 17302 5 9 - 145985 + 19923 9 150 - 49942 + 6816 @@ -21940,67 +21641,67 @@ 2 8 - 144064 + 19661 9 76 - 136380 + 18613 76 82 - 128697 + 17564 82 89 - 122934 + 16778 89 92 - 111409 + 15205 92 95 - 134459 + 18351 95 97 - 149826 + 20448 97 98 - 211294 + 28837 98 99 - 130618 + 17826 99 104 - 155589 + 21234 104 106 - 130618 + 17826 106 159 - 128697 + 17564 162 2019 - 19208 + 2621 @@ -22016,67 +21717,67 @@ 2 8 - 144064 + 19661 9 76 - 136380 + 18613 76 82 - 128697 + 17564 82 89 - 122934 + 16778 89 92 - 111409 + 15205 92 95 - 134459 + 18351 95 97 - 149826 + 20448 97 98 - 211294 + 28837 98 99 - 130618 + 17826 99 104 - 155589 + 21234 104 106 - 130618 + 17826 106 139 - 128697 + 17564 141 589 - 19208 + 2621 @@ -22092,57 +21793,57 @@ 1 2 - 82596 + 11272 2 3 - 190164 + 25953 3 4 - 249711 + 34080 4 5 - 105647 + 14418 5 7 - 84517 + 11534 7 10 - 94121 + 12845 10 31 - 88359 + 12059 35 694 - 86438 + 11797 738 776 - 28812 + 3932 777 779 - 92201 + 12583 788 889 - 26891 + 3670 @@ -22158,37 +21859,37 @@ 1 2 - 82596 + 11272 2 3 - 562810 + 76812 3 4 - 195927 + 26740 4 5 - 92201 + 12583 5 6 - 86438 + 11797 6 9 - 92201 + 12583 9 69 - 17287 + 2359 @@ -22204,27 +21905,27 @@ 1 2 - 82596 + 11272 2 3 - 800997 + 109319 3 4 - 80675 + 11010 4 6 - 82596 + 11272 6 165 - 82596 + 11272 @@ -22240,42 +21941,42 @@ 1 2 - 286207 + 39061 2 3 - 309257 + 42207 3 4 - 124855 + 17040 4 7 - 94121 + 12845 7 17 - 94121 + 12845 18 763 - 86438 + 11797 764 777 - 92201 + 12583 777 888 - 42258 + 5767 @@ -22285,31 +21986,31 @@ xmlAttrs - 182798274 + 24948200 id - 182798274 + 24948200 elementid - 149002731 + 20335805 name - 722241 + 98571 value - 11548187 + 1576089 idx - 44179 + 6029 fileid - 1127542 + 153886 @@ -22323,7 +22024,7 @@ 1 2 - 182798274 + 24948200 @@ -22339,7 +22040,7 @@ 1 2 - 182798274 + 24948200 @@ -22355,7 +22056,7 @@ 1 2 - 182798274 + 24948200 @@ -22371,7 +22072,7 @@ 1 2 - 182798274 + 24948200 @@ -22387,7 +22088,7 @@ 1 2 - 182798274 + 24948200 @@ -22403,17 +22104,17 @@ 1 2 - 136351973 + 18609237 2 6 - 11204353 + 1529163 6 24 - 1446404 + 197404 @@ -22429,17 +22130,17 @@ 1 2 - 136351973 + 18609237 2 6 - 11223562 + 1531785 6 23 - 1427196 + 194782 @@ -22455,17 +22156,17 @@ 1 2 - 136426886 + 18619461 2 6 - 11279267 + 1539387 6 21 - 1296577 + 176956 @@ -22481,17 +22182,17 @@ 1 2 - 136351973 + 18609237 2 6 - 11204353 + 1529163 6 24 - 1446404 + 197404 @@ -22507,7 +22208,7 @@ 1 2 - 149002731 + 20335805 @@ -22523,62 +22224,62 @@ 1 2 - 149826 + 20448 2 3 - 78755 + 10748 3 4 - 44179 + 6029 4 5 - 24971 + 3408 5 6 - 42258 + 5767 6 8 - 51863 + 7078 8 11 - 59546 + 8126 11 22 - 55704 + 7602 23 38 - 57625 + 7864 38 79 - 57625 + 7864 81 168 - 55704 + 7602 168 74700 - 44179 + 6029 @@ -22594,62 +22295,62 @@ 1 2 - 149826 + 20448 2 3 - 78755 + 10748 3 4 - 44179 + 6029 4 5 - 24971 + 3408 5 6 - 42258 + 5767 6 8 - 51863 + 7078 8 11 - 65309 + 8913 11 25 - 61467 + 8389 25 39 - 59546 + 8126 43 91 - 57625 + 7864 91 227 - 55704 + 7602 227 74700 - 30733 + 4194 @@ -22665,42 +22366,42 @@ 1 2 - 303495 + 41420 2 3 - 113330 + 15467 3 4 - 48021 + 6553 4 5 - 51863 + 7078 5 9 - 59546 + 8126 9 21 - 55704 + 7602 22 64 - 59546 + 8126 68 2100 - 30733 + 4194 @@ -22716,37 +22417,37 @@ 1 2 - 284286 + 38799 2 3 - 134459 + 18351 3 4 - 69150 + 9437 4 5 - 76834 + 10486 5 7 - 46100 + 6291 7 10 - 57625 + 7864 10 21 - 53783 + 7340 @@ -22762,52 +22463,52 @@ 1 2 - 251632 + 34342 2 3 - 74913 + 10224 3 4 - 38417 + 5243 4 5 - 34575 + 4718 5 6 - 53783 + 7340 6 9 - 59546 + 8126 9 17 - 63388 + 8651 17 34 - 55704 + 7602 36 91 - 55704 + 7602 91 223 - 34575 + 4718 @@ -22823,37 +22524,37 @@ 1 2 - 6308091 + 860924 2 3 - 1707641 + 233057 3 5 - 885514 + 120854 5 31 - 870147 + 118757 31 91 - 908564 + 124000 91 1111 - 866306 + 118232 3397 3398 - 1920 + 262 @@ -22869,32 +22570,32 @@ 1 2 - 6434868 + 878227 2 3 - 1626965 + 222047 3 5 - 897039 + 122427 5 33 - 910485 + 124262 33 93 - 891277 + 121640 93 3398 - 787551 + 107484 @@ -22910,17 +22611,17 @@ 1 2 - 10480191 + 1430330 2 4 - 929694 + 126884 4 53 - 138301 + 18875 @@ -22936,17 +22637,17 @@ 1 2 - 9563942 + 1305281 2 3 - 1396462 + 190588 3 20 - 587781 + 80220 @@ -22962,32 +22663,32 @@ 1 2 - 7433713 + 1014548 2 3 - 1252398 + 170926 3 10 - 897039 + 122427 10 83 - 877831 + 119805 83 99 - 881672 + 120330 99 182 - 205531 + 28050 @@ -23003,62 +22704,62 @@ 1 6 - 3841 + 524 12 14 - 3841 + 524 17 26 - 3841 + 524 39 56 - 3841 + 524 83 110 - 3841 + 524 153 232 - 3841 + 524 316 400 - 3841 + 524 468 545 - 3841 + 524 626 754 - 3841 + 524 951 1491 - 3841 + 524 4718 6587 - 3841 + 524 77571 77572 - 1920 + 262 @@ -23074,62 +22775,62 @@ 1 6 - 3841 + 524 12 14 - 3841 + 524 17 26 - 3841 + 524 39 56 - 3841 + 524 83 110 - 3841 + 524 153 232 - 3841 + 524 316 400 - 3841 + 524 468 545 - 3841 + 524 626 754 - 3841 + 524 951 1491 - 3841 + 524 4718 6587 - 3841 + 524 77571 77572 - 1920 + 262 @@ -23145,62 +22846,62 @@ 1 4 - 3841 + 524 7 10 - 3841 + 524 11 17 - 3841 + 524 18 23 - 3841 + 524 26 38 - 3841 + 524 39 49 - 3841 + 524 57 67 - 3841 + 524 72 79 - 3841 + 524 95 101 - 3841 + 524 105 106 - 3841 + 524 106 132 - 3841 + 524 140 141 - 1920 + 262 @@ -23216,62 +22917,62 @@ 1 5 - 3841 + 524 7 10 - 3841 + 524 11 18 - 3841 + 524 22 32 - 3841 + 524 46 63 - 3841 + 524 85 119 - 3841 + 524 142 185 - 3841 + 524 212 228 - 3841 + 524 253 275 - 3841 + 524 307 423 - 3841 + 524 580 1324 - 3841 + 524 3579 3580 - 1920 + 262 @@ -23287,62 +22988,62 @@ 1 6 - 3841 + 524 7 8 - 3841 + 524 10 19 - 3841 + 524 23 36 - 3841 + 524 45 59 - 3841 + 524 73 97 - 3841 + 524 115 131 - 3841 + 524 140 148 - 3841 + 524 168 181 - 3841 + 524 248 363 - 3841 + 524 473 530 - 3841 + 524 587 588 - 1920 + 262 @@ -23358,72 +23059,72 @@ 1 3 - 84517 + 11534 3 5 - 86438 + 11797 5 6 - 51863 + 7078 6 7 - 86438 + 11797 7 8 - 72992 + 9961 8 10 - 82596 + 11272 10 15 - 92201 + 12583 15 27 - 86438 + 11797 27 41 - 86438 + 11797 41 65 - 86438 + 11797 65 157 - 92201 + 12583 162 817 - 86438 + 11797 818 832 - 94121 + 12845 832 1187 - 38417 + 5243 @@ -23439,52 +23140,52 @@ 1 2 - 128697 + 17564 2 3 - 265078 + 36177 3 4 - 159431 + 21759 4 5 - 109488 + 14942 5 8 - 101805 + 13894 8 14 - 86438 + 11797 14 295 - 86438 + 11797 330 775 - 71071 + 9699 776 778 - 92201 + 12583 787 888 - 26891 + 3670 @@ -23500,62 +23201,62 @@ 1 2 - 71071 + 9699 2 3 - 92201 + 12583 3 4 - 71071 + 9699 4 5 - 94121 + 12845 5 6 - 170956 + 23332 6 7 - 161351 + 22021 7 8 - 71071 + 9699 8 12 - 86438 + 11797 12 18 - 97963 + 13370 18 24 - 96042 + 13107 24 37 - 88359 + 12059 37 55 - 26891 + 3670 @@ -23571,67 +23272,67 @@ 1 3 - 97963 + 13370 3 4 - 55704 + 7602 4 5 - 103726 + 14156 5 6 - 124855 + 17040 6 8 - 88359 + 12059 8 12 - 99884 + 13632 12 19 - 86438 + 11797 19 27 - 97963 + 13370 27 41 - 86438 + 11797 42 170 - 86438 + 11797 205 780 - 80675 + 11010 781 783 - 92201 + 12583 791 893 - 26891 + 3670 @@ -23647,47 +23348,47 @@ 1 2 - 111409 + 15205 2 3 - 107567 + 14680 3 4 - 213215 + 29099 4 5 - 218977 + 29885 5 6 - 130618 + 17826 6 10 - 96042 + 13107 10 12 - 65309 + 8913 12 15 - 97963 + 13370 15 24 - 86438 + 11797 @@ -23697,23 +23398,23 @@ xmlNs - 1811367 + 247214 id - 11525 + 1572 prefixName - 13445 + 1835 URI - 11525 + 1572 fileid - 1054550 + 143924 @@ -23727,12 +23428,12 @@ 1 2 - 9604 + 1310 2 3 - 1920 + 262 @@ -23748,7 +23449,7 @@ 1 2 - 11525 + 1572 @@ -23764,32 +23465,32 @@ 2 3 - 1920 + 262 20 21 - 1920 + 262 88 89 - 1920 + 262 167 168 - 1920 + 262 213 214 - 1920 + 262 453 454 - 1920 + 262 @@ -23805,7 +23506,7 @@ 1 2 - 13445 + 1835 @@ -23821,7 +23522,7 @@ 1 2 - 13445 + 1835 @@ -23837,37 +23538,37 @@ 1 2 - 1920 + 262 2 3 - 1920 + 262 20 21 - 1920 + 262 88 89 - 1920 + 262 166 167 - 1920 + 262 213 214 - 1920 + 262 453 454 - 1920 + 262 @@ -23883,7 +23584,7 @@ 1 2 - 11525 + 1572 @@ -23899,12 +23600,12 @@ 1 2 - 9604 + 1310 2 3 - 1920 + 262 @@ -23920,32 +23621,32 @@ 2 3 - 1920 + 262 20 21 - 1920 + 262 88 89 - 1920 + 262 167 168 - 1920 + 262 213 214 - 1920 + 262 453 454 - 1920 + 262 @@ -23961,17 +23662,17 @@ 1 2 - 470609 + 64228 2 3 - 411063 + 56101 3 4 - 172877 + 23594 @@ -23987,17 +23688,17 @@ 1 2 - 470609 + 64228 2 3 - 411063 + 56101 3 4 - 172877 + 23594 @@ -24013,17 +23714,17 @@ 1 2 - 470609 + 64228 2 3 - 411063 + 56101 3 4 - 172877 + 23594 @@ -24033,19 +23734,19 @@ xmlHasNs - 36540446 + 4987018 elementId - 36540446 + 4987018 nsId - 11525 + 1572 fileid - 1048787 + 143137 @@ -24059,7 +23760,7 @@ 1 2 - 36540446 + 4987018 @@ -24075,7 +23776,7 @@ 1 2 - 36540446 + 4987018 @@ -24091,32 +23792,32 @@ 13 14 - 1920 + 262 84 85 - 1920 + 262 2426 2427 - 1920 + 262 2733 2734 - 1920 + 262 3704 3705 - 1920 + 262 10063 10064 - 1920 + 262 @@ -24132,32 +23833,32 @@ 2 3 - 1920 + 262 20 21 - 1920 + 262 86 87 - 1920 + 262 164 165 - 1920 + 262 209 210 - 1920 + 262 453 454 - 1920 + 262 @@ -24173,77 +23874,77 @@ 1 3 - 63388 + 8651 3 5 - 88359 + 12059 5 6 - 48021 + 6553 6 7 - 92201 + 12583 7 8 - 69150 + 9437 8 10 - 86438 + 11797 10 15 - 92201 + 12583 15 25 - 78755 + 10748 25 36 - 80675 + 11010 36 49 - 82596 + 11272 49 54 - 21129 + 2883 54 55 - 82596 + 11272 55 81 - 80675 + 11010 81 298 - 78755 + 10748 298 833 - 3841 + 524 @@ -24259,17 +23960,17 @@ 1 2 - 472530 + 64490 2 3 - 407221 + 55577 3 4 - 169035 + 23069 @@ -24279,23 +23980,23 @@ xmlComments - 151257816 + 20643577 id - 151257816 + 20643577 text - 2387624 + 325861 parentid - 1185168 + 161751 fileid - 1108333 + 151264 @@ -24309,7 +24010,7 @@ 1 2 - 151257816 + 20643577 @@ -24325,7 +24026,7 @@ 1 2 - 151257816 + 20643577 @@ -24341,7 +24042,7 @@ 1 2 - 151257816 + 20643577 @@ -24357,67 +24058,67 @@ 1 2 - 328466 + 44828 2 7 - 195927 + 26740 7 32 - 197848 + 27002 32 61 - 180560 + 24642 61 76 - 180560 + 24642 76 84 - 192085 + 26215 84 90 - 176718 + 24118 90 94 - 157510 + 21496 94 95 - 84517 + 11534 95 96 - 142143 + 19399 96 98 - 197848 + 27002 98 100 - 178639 + 24380 100 460 - 174797 + 23856 @@ -24433,67 +24134,67 @@ 1 2 - 332308 + 45353 2 6 - 190164 + 25953 6 32 - 201689 + 27526 32 61 - 182481 + 24904 61 75 - 186323 + 25429 75 84 - 209373 + 28575 84 90 - 172877 + 23594 90 94 - 169035 + 23069 94 95 - 94121 + 12845 95 96 - 145985 + 19923 96 98 - 201689 + 27526 98 100 - 190164 + 25953 100 460 - 111409 + 15205 @@ -24509,67 +24210,67 @@ 1 2 - 347674 + 47450 2 7 - 188243 + 25691 7 32 - 188243 + 25691 32 61 - 182481 + 24904 61 75 - 186323 + 25429 75 84 - 209373 + 28575 84 90 - 172877 + 23594 90 94 - 169035 + 23069 94 95 - 94121 + 12845 95 96 - 145985 + 19923 96 98 - 201689 + 27526 98 100 - 190164 + 25953 100 460 - 111409 + 15205 @@ -24585,22 +24286,22 @@ 1 2 - 943140 + 128719 2 724 - 90280 + 12321 726 830 - 109488 + 14942 831 941 - 42258 + 5767 @@ -24616,27 +24317,27 @@ 1 2 - 943140 + 128719 2 697 - 90280 + 12321 697 795 - 48021 + 6553 795 827 - 90280 + 12321 838 899 - 13445 + 1835 @@ -24652,7 +24353,7 @@ 1 2 - 1185168 + 161751 @@ -24668,27 +24369,27 @@ 1 2 - 847097 + 115611 2 549 - 84517 + 11534 579 829 - 57625 + 7864 829 832 - 92201 + 12583 834 941 - 26891 + 3670 @@ -24704,27 +24405,27 @@ 1 2 - 847097 + 115611 2 536 - 84517 + 11534 560 795 - 72992 + 9961 795 812 - 84517 + 11534 819 899 - 19208 + 2621 @@ -24740,12 +24441,12 @@ 1 2 - 1052629 + 143662 2 6 - 55704 + 7602 @@ -24755,31 +24456,31 @@ xmlChars - 142938589 + 19508174 id - 142938589 + 19508174 text - 109773086 + 14981766 parentid - 142938589 + 19508174 idx - 1920 + 262 isCDATA - 3841 + 524 fileid - 249711 + 34080 @@ -24793,7 +24494,7 @@ 1 2 - 142938589 + 19508174 @@ -24809,7 +24510,7 @@ 1 2 - 142938589 + 19508174 @@ -24825,7 +24526,7 @@ 1 2 - 142938589 + 19508174 @@ -24841,7 +24542,7 @@ 1 2 - 142938589 + 19508174 @@ -24857,7 +24558,7 @@ 1 2 - 142938589 + 19508174 @@ -24873,17 +24574,17 @@ 1 2 - 93927944 + 12819230 2 3 - 9865517 + 1346439 3 128 - 5979625 + 816095 @@ -24899,17 +24600,17 @@ 1 2 - 93927944 + 12819230 2 3 - 9865517 + 1346439 3 128 - 5979625 + 816095 @@ -24925,7 +24626,7 @@ 1 2 - 109773086 + 14981766 @@ -24941,7 +24642,7 @@ 1 2 - 109773086 + 14981766 @@ -24957,12 +24658,12 @@ 1 2 - 105030493 + 14334499 2 76 - 4742593 + 647266 @@ -24978,7 +24679,7 @@ 1 2 - 142938589 + 19508174 @@ -24994,7 +24695,7 @@ 1 2 - 142938589 + 19508174 @@ -25010,7 +24711,7 @@ 1 2 - 142938589 + 19508174 @@ -25026,7 +24727,7 @@ 1 2 - 142938589 + 19508174 @@ -25042,7 +24743,7 @@ 1 2 - 142938589 + 19508174 @@ -25058,7 +24759,7 @@ 74414 74415 - 1920 + 262 @@ -25074,7 +24775,7 @@ 57148 57149 - 1920 + 262 @@ -25090,7 +24791,7 @@ 74414 74415 - 1920 + 262 @@ -25106,7 +24807,7 @@ 2 3 - 1920 + 262 @@ -25122,7 +24823,7 @@ 130 131 - 1920 + 262 @@ -25138,12 +24839,12 @@ 518 519 - 1920 + 262 73896 73897 - 1920 + 262 @@ -25159,12 +24860,12 @@ 492 493 - 1920 + 262 56656 56657 - 1920 + 262 @@ -25180,12 +24881,12 @@ 518 519 - 1920 + 262 73896 73897 - 1920 + 262 @@ -25201,7 +24902,7 @@ 1 2 - 3841 + 524 @@ -25217,12 +24918,12 @@ 98 99 - 1920 + 262 130 131 - 1920 + 262 @@ -25238,57 +24939,57 @@ 1 2 - 21129 + 2883 2 23 - 19208 + 2621 24 243 - 19208 + 2621 294 566 - 19208 + 2621 610 686 - 19208 + 2621 691 764 - 19208 + 2621 765 775 - 19208 + 2621 775 776 - 5762 + 786 776 777 - 69150 + 9437 777 803 - 19208 + 2621 807 888 - 19208 + 2621 @@ -25304,67 +25005,67 @@ 1 2 - 21129 + 2883 2 21 - 19208 + 2621 22 188 - 19208 + 2621 208 492 - 19208 + 2621 525 589 - 19208 + 2621 590 638 - 19208 + 2621 639 651 - 19208 + 2621 652 656 - 17287 + 2359 656 659 - 23050 + 3145 659 663 - 21129 + 2883 663 667 - 19208 + 2621 667 701 - 19208 + 2621 702 744 - 13445 + 1835 @@ -25380,57 +25081,57 @@ 1 2 - 21129 + 2883 2 23 - 19208 + 2621 24 243 - 19208 + 2621 294 566 - 19208 + 2621 610 686 - 19208 + 2621 691 764 - 19208 + 2621 765 775 - 19208 + 2621 775 776 - 5762 + 786 776 777 - 69150 + 9437 777 803 - 19208 + 2621 807 888 - 19208 + 2621 @@ -25446,7 +25147,7 @@ 1 2 - 249711 + 34080 @@ -25462,12 +25163,12 @@ 1 2 - 61467 + 8389 2 3 - 188243 + 25691 @@ -25477,15 +25178,15 @@ xmllocations - 630217533 + 86011718 xmlElement - 628417691 + 85766076 location - 590551854 + 80598169 @@ -25499,12 +25200,12 @@ 1 2 - 628406166 + 85764503 2 454 - 11525 + 1572 @@ -25520,12 +25221,12 @@ 1 2 - 577165407 + 78771195 2 25 - 13386446 + 1826974 @@ -25766,19 +25467,19 @@ ktComments - 188243 + 74439 id - 188243 + 74439 kind - 5762 + 37 text - 136380 + 51562 @@ -25792,7 +25493,7 @@ 1 2 - 188243 + 74439 @@ -25808,7 +25509,7 @@ 1 2 - 188243 + 74439 @@ -25822,19 +25523,19 @@ 12 - 16 - 17 - 1920 + 1196 + 1197 + 12 - 22 - 23 - 1920 + 1284 + 1285 + 12 - 60 - 61 - 1920 + 3517 + 3518 + 12 @@ -25848,19 +25549,19 @@ 12 - 1 - 2 - 1920 + 17 + 18 + 12 - 16 - 17 - 1920 + 1073 + 1074 + 12 - 54 - 55 - 1920 + 3064 + 3065 + 12 @@ -25876,12 +25577,17 @@ 1 2 - 130618 + 46101 - 4 - 23 - 5762 + 2 + 3 + 4232 + + + 3 + 572 + 1228 @@ -25897,7 +25603,7 @@ 1 2 - 136380 + 51562 @@ -25907,19 +25613,19 @@ ktCommentSections - 52611 + 47690 id - 52611 + 47690 comment - 48161 + 43655 content - 44765 + 40577 @@ -25933,7 +25639,7 @@ 1 2 - 52611 + 47690 @@ -25949,7 +25655,7 @@ 1 2 - 52611 + 47690 @@ -25965,12 +25671,12 @@ 1 2 - 46367 + 42029 2 18 - 1793 + 1626 @@ -25986,12 +25692,12 @@ 1 2 - 46367 + 42029 2 18 - 1793 + 1626 @@ -26007,17 +25713,17 @@ 1 2 - 39616 + 35910 2 3 - 4313 + 3910 3 63 - 835 + 757 @@ -26033,17 +25739,17 @@ 1 2 - 39712 + 35997 2 3 - 4231 + 3835 3 56 - 821 + 744 @@ -26053,15 +25759,15 @@ ktCommentSectionNames - 4450 + 4034 id - 4450 + 4034 name - 13 + 12 @@ -26075,7 +25781,7 @@ 1 2 - 4450 + 4034 @@ -26091,7 +25797,7 @@ 325 326 - 13 + 12 @@ -26101,15 +25807,15 @@ ktCommentSectionSubjectNames - 4450 + 4034 id - 4450 + 4034 subjectname - 2916 + 2643 @@ -26123,7 +25829,7 @@ 1 2 - 4450 + 4034 @@ -26139,22 +25845,22 @@ 1 2 - 2218 + 2010 2 3 - 438 + 397 3 9 - 219 + 198 10 16 - 41 + 37 @@ -26164,15 +25870,15 @@ ktCommentOwners - 75329 + 68171 id - 47914 + 43432 owner - 73508 + 66520 @@ -26186,22 +25892,22 @@ 1 2 - 30838 + 28065 2 3 - 10872 + 9744 3 4 - 4025 + 3649 4 6 - 2177 + 1973 @@ -26217,12 +25923,12 @@ 1 2 - 71701 + 64881 2 4 - 1807 + 1638 @@ -26232,19 +25938,19 @@ ktExtensionFunctions - 1206297 + 166732 id - 1206297 + 166732 typeid - 97963 + 13632 kttypeid - 1920 + 262 @@ -26258,7 +25964,7 @@ 1 2 - 1206297 + 166732 @@ -26274,7 +25980,7 @@ 1 2 - 1206297 + 166732 @@ -26290,37 +25996,37 @@ 1 2 - 55704 + 7864 2 3 - 5762 + 524 3 4 - 3841 + 786 5 6 - 13445 + 1310 - 7 - 16 - 7683 + 6 + 13 + 1048 - 20 - 87 - 7683 + 13 + 30 + 1048 - 109 + 35 227 - 3841 + 1048 @@ -26336,7 +26042,7 @@ 1 2 - 97963 + 13632 @@ -26350,9 +26056,9 @@ 12 - 628 - 629 - 1920 + 636 + 637 + 262 @@ -26366,9 +26072,9 @@ 12 - 51 - 52 - 1920 + 52 + 53 + 262 @@ -26378,15 +26084,15 @@ ktProperties - 21895839 + 2989117 id - 21895839 + 2989117 nodeName - 13542035 + 1848733 @@ -26400,7 +26106,7 @@ 1 2 - 21895839 + 2989117 @@ -26416,17 +26122,17 @@ 1 2 - 11824790 + 1614626 2 4 - 1142909 + 155721 4 352 - 574335 + 78385 @@ -26436,15 +26142,15 @@ ktPropertyGetters - 5985387 + 816357 id - 5985387 + 816357 getter - 5985387 + 816357 @@ -26458,7 +26164,7 @@ 1 2 - 5985387 + 816357 @@ -26474,7 +26180,7 @@ 1 2 - 5985387 + 816357 @@ -26484,15 +26190,15 @@ ktPropertySetters - 366883 + 53073 id - 366883 + 53073 setter - 366883 + 53073 @@ -26506,7 +26212,7 @@ 1 2 - 366883 + 53073 @@ -26522,7 +26228,7 @@ 1 2 - 366883 + 53073 @@ -26532,15 +26238,15 @@ ktPropertyBackingFields - 14423708 + 2459964 id - 14423708 + 2459964 backingField - 14423708 + 2459964 @@ -26554,7 +26260,7 @@ 1 2 - 14423708 + 2459964 @@ -26570,7 +26276,7 @@ 1 2 - 14423708 + 2459964 @@ -26580,15 +26286,15 @@ ktSyntheticBody - 9108 + 1497 id - 9108 + 1497 kind - 1821 + 124 @@ -26602,7 +26308,7 @@ 1 2 - 9108 + 1497 @@ -26616,9 +26322,9 @@ 12 - 5 - 6 - 1821 + 12 + 13 + 124 @@ -26628,37 +26334,37 @@ ktLocalFunction - 3841 + 1573 id - 3841 + 1573 ktInitializerAssignment - 199475 + 69820 id - 199475 + 69820 ktPropertyDelegates - 5201 + 4944 id - 5201 + 4944 variableId - 5201 + 4944 @@ -26672,7 +26378,7 @@ 1 2 - 5201 + 4944 @@ -26688,7 +26394,7 @@ 1 2 - 5201 + 4944 @@ -26698,15 +26404,15 @@ compiler_generated - 1467534 + 268390 id - 1467534 + 268390 kind - 13445 + 148 @@ -26720,7 +26426,7 @@ 1 2 - 1467534 + 268390 @@ -26734,39 +26440,59 @@ 12 - 1 - 2 - 1920 + 61 + 62 + 12 - 8 - 9 - 1920 + 84 + 85 + 24 - 38 - 39 - 1920 + 94 + 95 + 12 - 81 - 82 - 1920 + 143 + 144 + 12 - 85 - 86 - 1920 + 186 + 187 + 12 - 236 - 237 - 1920 + 203 + 204 + 12 - 315 - 316 - 1920 + 737 + 738 + 12 + + + 1028 + 1029 + 12 + + + 1275 + 1276 + 12 + + + 5140 + 5141 + 12 + + + 12589 + 12590 + 12 @@ -26776,15 +26502,15 @@ ktFunctionOriginalNames - 1586627 + 216279 id - 1586627 + 216279 name - 186323 + 25167 @@ -26798,7 +26524,7 @@ 1 2 - 1586627 + 216279 @@ -26814,22 +26540,22 @@ 1 2 - 147905 + 19923 2 4 - 13445 + 1835 6 16 - 15366 + 2097 22 339 - 9604 + 1310 @@ -26839,11 +26565,11 @@ ktDataClasses - 113330 + 15467 id - 113330 + 15467 diff --git a/java/ql/lib/ext/java.net.model.yml b/java/ql/lib/ext/java.net.model.yml index 2c153b37a05..1ee1c96347f 100644 --- a/java/ql/lib/ext/java.net.model.yml +++ b/java/ql/lib/ext/java.net.model.yml @@ -23,8 +23,10 @@ extensions: data: - ["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"] + - ["java.net", "URI", False, "toASCIIString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.net", "URI", False, "toString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.net", "URI", False, "toURL", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["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", "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 129bf048b96..db51d2f6686 100644 --- a/java/ql/lib/ext/java.nio.file.model.yml +++ b/java/ql/lib/ext/java.nio.file.model.yml @@ -3,13 +3,14 @@ extensions: pack: codeql/java-all extensible: sinkModel data: + - ["java.nio.file", "Files", False, "copy", "", "", "Argument[0]", "read-file", "manual"] - ["java.nio.file", "Files", False, "copy", "", "", "Argument[1]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createDirectories", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createDirectory", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createFile", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createLink", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createSymbolicLink", "", "", "Argument[0]", "create-file", "manual"] - - ["java.nio.file", "Files", False, "createTempDirectory", "", "", "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, "move", "", "", "Argument[1]", "create-file", "manual"] - ["java.nio.file", "Files", False, "newBufferedWriter", "", "", "Argument[0]", "create-file", "manual"] diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 48043d91fb2..fb4ea6dca37 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.5.3-dev +version: 0.5.4-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll index 256b831a8ad..8b53254893b 100644 --- a/java/ql/lib/semmle/code/Location.qll +++ b/java/ql/lib/semmle/code/Location.qll @@ -10,9 +10,7 @@ private import semmle.code.SMAP /** Holds if element `e` has name `name`. */ predicate hasName(Element e, string name) { - classes(e, name, _, _) - or - interfaces(e, name, _, _) + classes_or_interfaces(e, name, _, _) or primitives(e, name) or diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index e14b1d1c981..00c9648c9a4 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -397,14 +397,21 @@ private predicate potentialInterfaceImplementationWithSignature(string sig, RefT not t.isAbstract() } -pragma[nomagic] -private predicate implementsInterfaceMethod(SrcMethod impl, SrcMethod m) { - exists(RefType t, Interface i, Method minst, Method implinst | - m = minst.getSourceDeclaration() and +pragma[noinline] +private predicate isInterfaceSourceImplementation(Method minst, RefType t) { + exists(Interface i | i = minst.getDeclaringType() and t.extendsOrImplements+(i) and - t.isSourceDeclaration() and + t.isSourceDeclaration() + ) +} + +pragma[nomagic] +private predicate implementsInterfaceMethod(SrcMethod impl, SrcMethod m) { + exists(RefType t, Method minst, Method implinst | + isInterfaceSourceImplementation(minst, t) and potentialInterfaceImplementationWithSignature(minst.getSignature(), t, implinst) and + m = minst.getSourceDeclaration() and impl = implinst.getSourceDeclaration() ) } @@ -542,7 +549,7 @@ class Method extends Callable, @method { /** A method that is the same as its source declaration. */ class SrcMethod extends Method { - SrcMethod() { methods(_, _, _, _, _, this) } + SrcMethod() { methods(this, _, _, _, _, this) } /** * All the methods that could possibly be called when this method diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index eff61ed0fde..dbaaefeb645 100644 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -385,10 +385,7 @@ class Array extends RefType, @array { */ class RefType extends Type, Annotatable, Modifiable, @reftype { /** Gets the package in which this type is declared. */ - Package getPackage() { - classes(this, _, result, _) or - interfaces(this, _, result, _) - } + Package getPackage() { classes_or_interfaces(this, _, result, _) } /** Gets the type in which this reference type is enclosed, if any. */ RefType getEnclosingType() { enclInReftype(this, result) } @@ -416,7 +413,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype { /** * Gets a direct or indirect supertype of this type. - * This does not including itself, unless this type is part of a cycle + * This does not include itself, unless this type is part of a cycle * in the type hierarchy. */ RefType getAStrictAncestor() { result = this.getASupertype().getAnAncestor() } @@ -685,12 +682,12 @@ class SrcRefType extends RefType { } /** A class declaration. */ -class Class extends ClassOrInterface, @class { +class Class extends ClassOrInterface { + Class() { not isInterface(this) } + /** Holds if this class is an anonymous class. */ predicate isAnonymous() { isAnonymClass(this.getSourceDeclaration(), _) } - override RefType getSourceDeclaration() { classes(this, _, _, result) } - /** * Gets an annotation that applies to this class. * @@ -742,10 +739,10 @@ class Record extends Class { } /** An intersection type. */ -class IntersectionType extends RefType, @class { +class IntersectionType extends RefType, @classorinterface { IntersectionType() { exists(string shortname | - classes(this, shortname, _, _) and + classes_or_interfaces(this, shortname, _, _) and shortname.matches("% & ...") ) } @@ -842,7 +839,7 @@ class LocalClass extends LocalClassOrInterface, NestedClass { class TopLevelType extends RefType { TopLevelType() { not enclInReftype(this, _) and - (this instanceof Class or this instanceof Interface) + this instanceof ClassOrInterface } } @@ -940,8 +937,8 @@ class InnerClass extends NestedClass { } /** An interface. */ -class Interface extends ClassOrInterface, @interface { - override RefType getSourceDeclaration() { interfaces(this, _, _, result) } +class Interface extends ClassOrInterface { + Interface() { isInterface(this) } override predicate isAbstract() { // JLS 9.1.1.1: "Every interface is implicitly abstract" @@ -953,6 +950,8 @@ class Interface extends ClassOrInterface, @interface { /** A class or interface. */ class ClassOrInterface extends RefType, @classorinterface { + override RefType getSourceDeclaration() { classes_or_interfaces(this, _, _, result) } + /** Holds if this class or interface is local. */ predicate isLocal() { isLocalClassOrInterface(this.getSourceDeclaration(), _) } diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index dd486ee5990..5bcd07be9b0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -261,9 +261,9 @@ module ModelValidation { [ "open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath", "groovy", "xss", "ognl-injection", "intent-start", "pending-intent-sent", - "url-open-stream", "url-redirect", "create-file", "write-file", "set-hostname-verifier", - "header-splitting", "information-leak", "xslt", "jexl", "bean-validation", "ssti", - "fragment-injection" + "url-open-stream", "url-redirect", "create-file", "read-file", "write-file", + "set-hostname-verifier", "header-splitting", "information-leak", "xslt", "jexl", + "bean-validation", "ssti", "fragment-injection" ] and not kind.matches("regex-use%") and not kind.matches("qltest%") and diff --git a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll index 1c76f554020..8bac5eefd6b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll @@ -681,9 +681,14 @@ private predicate unionTypeFlow0(TypeFlowNode n, RefType t, boolean exact) { private predicate unionTypeFlow(TypeFlowNode n, RefType t, boolean exact) { unionTypeFlow0(n, t, exact) and // filter impossible union parts: - if exact = true - then t.getErasure().(RefType).getASourceSupertype*() = getTypeBound(n).getErasure() - else haveIntersection(getTypeBound(n), t) + exists(RefType tErased, RefType boundErased | + pragma[only_bind_into](tErased) = t.getErasure() and + pragma[only_bind_into](boundErased) = getTypeBound(n).getErasure() + | + if exact = true + then tErased.getASourceSupertype*() = boundErased + else erasedHaveIntersection(tErased, boundErased) + ) } /** diff --git a/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll b/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll index 46bcc3a2201..6c92f7298d9 100644 --- a/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll +++ b/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll @@ -22,6 +22,17 @@ module MkUnification + + + @javacompilation + 8628 + + + @kotlincompilation + 7683 + + + @diagnostic + 61632 + + + @externalDataElement + 1 + + + @duplication + 1 + + + @similarity + 1 + + + @file + 9158642 + + + @folder + 1415670 + + + @location_default + 602747369 + + + @package + 580098 + + + @primitive + 17287 + + + @modifier + 26891 + + + @errortype + 1 + + + @class + 12618104 + + + @kt_nullable_type + 1920 + + + @kt_notnull_type + 172391 + + + @kt_type_alias + 1821 + + + @interface + 23200100 + + + @fielddecl + 199475 + + + @field + 19350704 + + + @constructor + 8006128 + + + @method + 109719302 + + + @param + 120852585 + + + @exception + 1232644 + + + @typevariable + 6288883 + + + @wildcard + 3338447 + + + @typebound + 4229725 + + + @array + 1375332 + + + @import + 368550 + + + @block + 756817 + + + @ifstmt + 188285 + + + @forstmt + 52504 + + + @enhancedforstmt + 18520 + + + @whilestmt + 13266 + + + @dostmt + 2405 + + + @trystmt + 58624 + + + @switchstmt + 10546 + + + @synchronizedstmt + 18206 + + + @returnstmt + 532846 + + + @throwstmt + 35917 + + + @breakstmt + 35329 + + + @continuestmt + 3211 + + + @emptystmt + 1561 + + + @exprstmt + 942102 + + + @assertstmt + 10815 + + + @localvariabledeclstmt + 318689 + + + @localtypedeclstmt + 3841 + + + @constructorinvocationstmt + 9165 + + + @superconstructorinvocationstmt + 201354 + + + @case + 107945 + + + @catchclause + 55201 + + + @labeledstmt + 2342 + + + @yieldstmt + 36 + + + @errorstmt + 1 + + + @whenbranch + 225101 + + + @arrayaccess + 409681 + + + @arraycreationexpr + 69247 + + + @arrayinit + 405405 + + + @assignexpr + 465407 + + + @assignaddexpr + 17016 + + + @assignsubexpr + 3505 + + + @assignmulexpr + 2153 + + + @assigndivexpr + 1071 + + + @assignandexpr + 3971 + + + @assignorexpr + 14528 + + + @booleanliteral + 589912 + + + @integerliteral + 1151458 + + + @longliteral + 185904 + + + @floatingpointliteral + 2824996 + + + @doubleliteral + 486619 + + + @characterliteral + 40016 + + + @stringliteral + 1262818 + + + @nullliteral + 434113 + + + @mulexpr + 204580 + + + @divexpr + 36264 + + + @remexpr + 3904 + + + @addexpr + 176986 + + + @subexpr + 84385 + + + @lshiftexpr + 8736 + + + @rshiftexpr + 4206 + + + @urshiftexpr + 5463 + + + @andbitexpr + 110212 + + + @orbitexpr + 12590 + + + @xorbitexpr + 1925 + + + @andlogicalexpr + 36742 + + + @orlogicalexpr + 31150 + + + @ltexpr + 66249 + + + @gtexpr + 17203 + + + @leexpr + 10529 + + + @geexpr + 13411 + + + @eqexpr + 128429 + + + @neexpr + 60975 + + + @postincexpr + 29632 + + + @postdecexpr + 11683 + + + @preincexpr + 23714 + + + @predecexpr + 3781 + + + @minusexpr + 744386 + + + @plusexpr + 53007 + + + @bitnotexpr + 8186 + + + @lognotexpr + 40111 + + + @castexpr + 93187 + + + @newexpr + 252083 + + + @conditionalexpr + 16047 + + + @instanceofexpr + 29542 + + + @localvariabledeclexpr + 385272 + + + @typeliteral + 144350 + + + @thisaccess + 756915 + + + @superaccess + 99884 + + + @varaccess + 2434277 + + + @methodaccess + 1512385 + + + @unannotatedtypeaccess + 2608638 + + + @arraytypeaccess + 120727 + + + @wildcardtypeaccess + 64091 + + + @declannotation + 6740832 + + + @assignremexpr + 47 + + + @assignxorexpr + 1102 + + + @assignlshiftexpr + 916 + + + @assignrshiftexpr + 1404 + + + @assignurshiftexpr + 431 + + + @parexpr + 1 + + + @packageaccess + 1 + + + @uniontypeaccess + 917 + + + @lambdaexpr + 167982 + + + @memberref + 23859 + + + @annotatedtypeaccess + 1281 + + + @typeannotation + 1281 + + + @intersectiontypeaccess + 25 + + + @switchexpr + 591 + + + @errorexpr + 1 + + + @whenexpr + 152111 + + + @getclassexpr + 1920 + + + @safecastexpr + 6402 + + + @implicitcastexpr + 30316 + + + @implicitnotnullexpr + 216630 + + + @implicitcoerciontounitexpr + 81396 + + + @notinstanceofexpr + 17306 + + + @stmtexpr + 55704 + + + @stringtemplateexpr + 59546 + + + @notnullexpr + 18820 + + + @unsafecoerceexpr + 1 + + + @valueeqexpr + 93060 + + + @valueneexpr + 95639 + + + @propertyref + 8878 + + + @localvar + 385272 + + + @module + 7965 + + + @requires + 1991 + + + @exports + 35013 + + + @opens + 165 + + + @uses + 10786 + + + @provides + 2323 + + + @javadoc + 985091 + + + @javadocTag + 335808 + + + @javadocText + 2502848 + + + @xmldtd + 569 + + + @xmlelement + 150282022 + + + @xmlattribute + 182798274 + + + @xmlnamespace + 11525 + + + @xmlcomment + 151257816 + + + @xmlcharacters + 142938589 + + + @config + 1 + + + @configName + 1 + + + @configValue + 1 + + + @ktcomment + 188243 + + + @ktcommentsection + 52611 + + + @kt_property + 21895839 + + + + + compilations + 8628 + + + id + 8628 + + + kind + 165 + + + cwd + 165 + + + name + 8628 + + + + + id + kind + + + 12 + + + 1 + 2 + 8628 + + + + + + + id + cwd + + + 12 + + + 1 + 2 + 8628 + + + + + + + id + name + + + 12 + + + 1 + 2 + 8628 + + + + + + + kind + id + + + 12 + + + 52 + 53 + 165 + + + + + + + kind + cwd + + + 12 + + + 1 + 2 + 165 + + + + + + + kind + name + + + 12 + + + 52 + 53 + 165 + + + + + + + cwd + id + + + 12 + + + 52 + 53 + 165 + + + + + + + cwd + kind + + + 12 + + + 1 + 2 + 165 + + + + + + + cwd + name + + + 12 + + + 52 + 53 + 165 + + + + + + + name + id + + + 12 + + + 1 + 2 + 8628 + + + + + + + name + kind + + + 12 + + + 1 + 2 + 8628 + + + + + + + name + cwd + + + 12 + + + 1 + 2 + 8628 + + + + + + + + + compilation_started + 7683 + + + id + 7683 + + + + + + compilation_info + 15366 + + + id + 7683 + + + info_key + 3841 + + + info_value + 3841 + + + + + id + info_key + + + 12 + + + 2 + 3 + 7683 + + + + + + + id + info_value + + + 12 + + + 2 + 3 + 7683 + + + + + + + info_key + id + + + 12 + + + 4 + 5 + 3841 + + + + + + + info_key + info_value + + + 12 + + + 1 + 2 + 3841 + + + + + + + info_value + id + + + 12 + + + 4 + 5 + 3841 + + + + + + + info_value + info_key + + + 12 + + + 1 + 2 + 3841 + + + + + + + + + compilation_args + 169035 + + + id + 7683 + + + num + 48021 + + + arg + 90280 + + + + + id + num + + + 12 + + + 20 + 21 + 3841 + + + 23 + 24 + 1920 + + + 25 + 26 + 1920 + + + + + + + id + arg + + + 12 + + + 20 + 21 + 3841 + + + 23 + 24 + 1920 + + + 25 + 26 + 1920 + + + + + + + num + id + + + 12 + + + 1 + 2 + 3841 + + + 2 + 3 + 5762 + + + 4 + 5 + 38417 + + + + + + + num + arg + + + 12 + + + 1 + 2 + 9604 + + + 2 + 3 + 17287 + + + 3 + 4 + 11525 + + + 4 + 5 + 9604 + + + + + + + arg + id + + + 12 + + + 1 + 2 + 61467 + + + 2 + 3 + 3841 + + + 4 + 5 + 24971 + + + + + + + arg + num + + + 12 + + + 1 + 2 + 67229 + + + 2 + 3 + 19208 + + + 3 + 4 + 3841 + + + + + + + + + compilation_compiling_files + 59495 + + + id + 2275 + + + num + 17556 + + + file + 49742 + + + + + id + num + + + 12 + + + 1 + 2 + 325 + + + 2 + 3 + 650 + + + 35 + 36 + 650 + + + 54 + 55 + 650 + + + + + + + id + file + + + 12 + + + 1 + 2 + 325 + + + 2 + 3 + 650 + + + 35 + 36 + 650 + + + 54 + 55 + 650 + + + + + + + num + id + + + 12 + + + 2 + 3 + 6177 + + + 4 + 5 + 10728 + + + 6 + 8 + 650 + + + + + + + num + file + + + 12 + + + 2 + 3 + 6177 + + + 3 + 4 + 9753 + + + 4 + 8 + 1625 + + + + + + + file + id + + + 12 + + + 1 + 2 + 39989 + + + 2 + 3 + 9753 + + + + + + + file + num + + + 12 + + + 1 + 2 + 49742 + + + + + + + + + compilation_compiling_files_completed + 59495 + + + id + 2275 + + + num + 17556 + + + result + 325 + + + + + id + num + + + 12 + + + 1 + 2 + 325 + + + 2 + 3 + 650 + + + 35 + 36 + 650 + + + 54 + 55 + 650 + + + + + + + id + result + + + 12 + + + 1 + 2 + 2275 + + + + + + + num + id + + + 12 + + + 2 + 3 + 6177 + + + 4 + 5 + 10728 + + + 6 + 8 + 650 + + + + + + + num + result + + + 12 + + + 1 + 2 + 17556 + + + + + + + result + id + + + 12 + + + 7 + 8 + 325 + + + + + + + result + num + + + 12 + + + 54 + 55 + 325 + + + + + + + + + compilation_time + 196471 + + + id + 8628 + + + num + 5144 + + + kind + 663 + + + seconds + 89772 + + + + + id + num + + + 12 + + + 1 + 2 + 331 + + + 2 + 3 + 1659 + + + 3 + 4 + 1161 + + + 4 + 5 + 2157 + + + 5 + 6 + 663 + + + 6 + 7 + 497 + + + 7 + 8 + 497 + + + 8 + 12 + 663 + + + 13 + 16 + 663 + + + 20 + 32 + 331 + + + + + + + id + kind + + + 12 + + + 4 + 5 + 8628 + + + + + + + id + seconds + + + 12 + + + 2 + 3 + 331 + + + 4 + 5 + 1659 + + + 6 + 7 + 1161 + + + 8 + 9 + 2157 + + + 10 + 11 + 663 + + + 12 + 13 + 497 + + + 14 + 15 + 497 + + + 16 + 23 + 663 + + + 26 + 31 + 663 + + + 40 + 63 + 331 + + + + + + + num + id + + + 12 + + + 1 + 2 + 1825 + + + 2 + 3 + 829 + + + 3 + 5 + 331 + + + 6 + 7 + 331 + + + 7 + 8 + 331 + + + 8 + 11 + 331 + + + 13 + 17 + 331 + + + 20 + 34 + 331 + + + 40 + 51 + 331 + + + 52 + 53 + 165 + + + + + + + num + kind + + + 12 + + + 4 + 5 + 5144 + + + + + + + num + seconds + + + 12 + + + 3 + 4 + 1825 + + + 5 + 6 + 829 + + + 7 + 10 + 331 + + + 13 + 14 + 331 + + + 15 + 16 + 331 + + + 17 + 22 + 331 + + + 27 + 34 + 331 + + + 41 + 54 + 331 + + + 67 + 82 + 331 + + + 101 + 102 + 165 + + + + + + + kind + id + + + 12 + + + 52 + 53 + 663 + + + + + + + kind + num + + + 12 + + + 31 + 32 + 663 + + + + + + + kind + seconds + + + 12 + + + 1 + 2 + 331 + + + 245 + 246 + 165 + + + 296 + 297 + 165 + + + + + + + seconds + id + + + 12 + + + 1 + 2 + 89606 + + + 52 + 53 + 165 + + + + + + + seconds + num + + + 12 + + + 1 + 2 + 89606 + + + 31 + 32 + 165 + + + + + + + seconds + kind + + + 12 + + + 1 + 2 + 89606 + + + 3 + 4 + 165 + + + + + + + + + diagnostic_for + 61632 + + + diagnostic + 61632 + + + compilation + 574 + + + file_number + 14797 + + + file_number_diagnostic_number + 2154 + + + + + diagnostic + compilation + + + 12 + + + 1 + 2 + 61632 + + + + + + + diagnostic + file_number + + + 12 + + + 1 + 2 + 61632 + + + + + + + diagnostic + file_number_diagnostic_number + + + 12 + + + 1 + 2 + 61632 + + + + + + + compilation + diagnostic + + + 12 + + + 14 + 15 + 143 + + + 28 + 29 + 143 + + + 123 + 124 + 143 + + + 264 + 265 + 143 + + + + + + + compilation + file_number + + + 12 + + + 7 + 8 + 143 + + + 14 + 15 + 143 + + + 45 + 46 + 143 + + + 103 + 104 + 143 + + + + + + + compilation + file_number_diagnostic_number + + + 12 + + + 2 + 3 + 287 + + + 14 + 15 + 143 + + + 15 + 16 + 143 + + + + + + + file_number + diagnostic + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 6464 + + + 3 + 4 + 718 + + + 4 + 5 + 3160 + + + 5 + 6 + 1292 + + + 6 + 8 + 1149 + + + 8 + 11 + 1292 + + + 12 + 21 + 574 + + + + + + + file_number + compilation + + + 12 + + + 1 + 2 + 8332 + + + 2 + 3 + 4453 + + + 3 + 4 + 1005 + + + 4 + 5 + 1005 + + + + + + + file_number + file_number_diagnostic_number + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 10056 + + + 3 + 4 + 2011 + + + 4 + 5 + 1005 + + + 5 + 8 + 1149 + + + 10 + 16 + 430 + + + + + + + file_number_diagnostic_number + diagnostic + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 574 + + + 3 + 4 + 430 + + + 5 + 6 + 143 + + + 7 + 8 + 143 + + + 11 + 12 + 143 + + + 18 + 19 + 143 + + + 33 + 34 + 143 + + + 168 + 169 + 143 + + + 169 + 170 + 143 + + + + + + + file_number_diagnostic_number + compilation + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 1723 + + + 4 + 5 + 287 + + + + + + + file_number_diagnostic_number + file_number + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 574 + + + 3 + 4 + 430 + + + 5 + 6 + 143 + + + 7 + 8 + 143 + + + 11 + 12 + 143 + + + 18 + 19 + 143 + + + 32 + 33 + 143 + + + 102 + 103 + 143 + + + 103 + 104 + 143 + + + + + + + + + compilation_compiler_times + 7683 + + + id + 7683 + + + cpu_seconds + 1920 + + + elapsed_seconds + 7683 + + + + + id + cpu_seconds + + + 12 + + + 1 + 2 + 7683 + + + + + + + id + elapsed_seconds + + + 12 + + + 1 + 2 + 7683 + + + + + + + cpu_seconds + id + + + 12 + + + 4 + 5 + 1920 + + + + + + + cpu_seconds + elapsed_seconds + + + 12 + + + 4 + 5 + 1920 + + + + + + + elapsed_seconds + id + + + 12 + + + 1 + 2 + 7683 + + + + + + + elapsed_seconds + cpu_seconds + + + 12 + + + 1 + 2 + 7683 + + + + + + + + + compilation_finished + 8628 + + + id + 8628 + + + cpu_seconds + 165 + + + elapsed_seconds + 8628 + + + result + 165 + + + + + id + cpu_seconds + + + 12 + + + 1 + 2 + 8628 + + + + + + + id + elapsed_seconds + + + 12 + + + 1 + 2 + 8628 + + + + + + + id + result + + + 12 + + + 1 + 2 + 8628 + + + + + + + cpu_seconds + id + + + 12 + + + 52 + 53 + 165 + + + + + + + cpu_seconds + elapsed_seconds + + + 12 + + + 52 + 53 + 165 + + + + + + + cpu_seconds + result + + + 12 + + + 1 + 2 + 165 + + + + + + + elapsed_seconds + id + + + 12 + + + 1 + 2 + 8628 + + + + + + + elapsed_seconds + cpu_seconds + + + 12 + + + 1 + 2 + 8628 + + + + + + + elapsed_seconds + result + + + 12 + + + 1 + 2 + 8628 + + + + + + + result + id + + + 12 + + + 52 + 53 + 165 + + + + + + + result + cpu_seconds + + + 12 + + + 1 + 2 + 165 + + + + + + + result + elapsed_seconds + + + 12 + + + 52 + 53 + 165 + + + + + + + + + diagnostics + 61632 + + + id + 61632 + + + generated_by + 143 + + + severity + 143 + + + error_tag + 143 + + + error_message + 1580 + + + full_error_message + 40944 + + + location + 143 + + + + + id + generated_by + + + 12 + + + 1 + 2 + 61632 + + + + + + + id + severity + + + 12 + + + 1 + 2 + 61632 + + + + + + + id + error_tag + + + 12 + + + 1 + 2 + 61632 + + + + + + + id + error_message + + + 12 + + + 1 + 2 + 61632 + + + + + + + id + full_error_message + + + 12 + + + 1 + 2 + 61632 + + + + + + + id + location + + + 12 + + + 1 + 2 + 61632 + + + + + + + generated_by + id + + + 12 + + + 429 + 430 + 143 + + + + + + + generated_by + severity + + + 12 + + + 1 + 2 + 143 + + + + + + + generated_by + error_tag + + + 12 + + + 1 + 2 + 143 + + + + + + + generated_by + error_message + + + 12 + + + 11 + 12 + 143 + + + + + + + generated_by + full_error_message + + + 12 + + + 285 + 286 + 143 + + + + + + + generated_by + location + + + 12 + + + 1 + 2 + 143 + + + + + + + severity + id + + + 12 + + + 429 + 430 + 143 + + + + + + + severity + generated_by + + + 12 + + + 1 + 2 + 143 + + + + + + + severity + error_tag + + + 12 + + + 1 + 2 + 143 + + + + + + + severity + error_message + + + 12 + + + 11 + 12 + 143 + + + + + + + severity + full_error_message + + + 12 + + + 285 + 286 + 143 + + + + + + + severity + location + + + 12 + + + 1 + 2 + 143 + + + + + + + error_tag + id + + + 12 + + + 429 + 430 + 143 + + + + + + + error_tag + generated_by + + + 12 + + + 1 + 2 + 143 + + + + + + + error_tag + severity + + + 12 + + + 1 + 2 + 143 + + + + + + + error_tag + error_message + + + 12 + + + 11 + 12 + 143 + + + + + + + error_tag + full_error_message + + + 12 + + + 285 + 286 + 143 + + + + + + + error_tag + location + + + 12 + + + 1 + 2 + 143 + + + + + + + error_message + id + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 143 + + + 3 + 4 + 143 + + + 6 + 7 + 143 + + + 9 + 10 + 143 + + + 12 + 13 + 287 + + + 24 + 25 + 143 + + + 28 + 29 + 143 + + + 166 + 167 + 287 + + + + + + + error_message + generated_by + + + 12 + + + 1 + 2 + 1580 + + + + + + + error_message + severity + + + 12 + + + 1 + 2 + 1580 + + + + + + + error_message + error_tag + + + 12 + + + 1 + 2 + 1580 + + + + + + + error_message + full_error_message + + + 12 + + + 1 + 2 + 143 + + + 2 + 3 + 143 + + + 3 + 4 + 143 + + + 6 + 7 + 143 + + + 9 + 10 + 143 + + + 12 + 13 + 287 + + + 22 + 23 + 143 + + + 24 + 25 + 143 + + + 28 + 29 + 143 + + + 166 + 167 + 143 + + + + + + + error_message + location + + + 12 + + + 1 + 2 + 1580 + + + + + + + full_error_message + id + + + 12 + + + 1 + 2 + 38358 + + + 2 + 25 + 2585 + + + + + + + full_error_message + generated_by + + + 12 + + + 1 + 2 + 40944 + + + + + + + full_error_message + severity + + + 12 + + + 1 + 2 + 40944 + + + + + + + full_error_message + error_tag + + + 12 + + + 1 + 2 + 40944 + + + + + + + full_error_message + error_message + + + 12 + + + 1 + 2 + 40944 + + + + + + + full_error_message + location + + + 12 + + + 1 + 2 + 40944 + + + + + + + location + id + + + 12 + + + 429 + 430 + 143 + + + + + + + location + generated_by + + + 12 + + + 1 + 2 + 143 + + + + + + + location + severity + + + 12 + + + 1 + 2 + 143 + + + + + + + location + error_tag + + + 12 + + + 1 + 2 + 143 + + + + + + + location + error_message + + + 12 + + + 11 + 12 + 143 + + + + + + + location + full_error_message + + + 12 + + + 285 + 286 + 143 + + + + + + + + + externalData + 1 + + + id + 1 + + + path + 1 + + + column + 1 + + + value + 1 + + + + + id + path + + + 12 + + + + + + id + column + + + 12 + + + + + + id + value + + + 12 + + + + + + path + id + + + 12 + + + + + + path + column + + + 12 + + + + + + path + value + + + 12 + + + + + + column + id + + + 12 + + + + + + column + path + + + 12 + + + + + + column + value + + + 12 + + + + + + value + id + + + 12 + + + + + + value + path + + + 12 + + + + + + value + column + + + 12 + + + + + + + + snapshotDate + 1 + + + snapshotDate + 1 + + + + + + sourceLocationPrefix + 1920 + + + prefix + 1920 + + + + + + duplicateCode + 1 + + + id + 1 + + + relativePath + 1 + + + equivClass + 1 + + + + + id + relativePath + + + 12 + + + 1 + 2 + 1 + + + + + + + id + equivClass + + + 12 + + + 1 + 2 + 1 + + + + + + + relativePath + id + + + 12 + + + + + + relativePath + equivClass + + + 12 + + + + + + equivClass + id + + + 12 + + + + + + equivClass + relativePath + + + 12 + + + + + + + + similarCode + 1 + + + id + 1 + + + relativePath + 1 + + + equivClass + 1 + + + + + id + relativePath + + + 12 + + + 1 + 2 + 1 + + + + + + + id + equivClass + + + 12 + + + 1 + 2 + 1 + + + + + + + relativePath + id + + + 12 + + + + + + relativePath + equivClass + + + 12 + + + + + + equivClass + id + + + 12 + + + + + + equivClass + relativePath + + + 12 + + + + + + + + tokens + 1 + + + id + 1 + + + offset + 1 + + + beginLine + 1 + + + beginColumn + 1 + + + endLine + 1 + + + endColumn + 1 + + + + + id + offset + + + 12 + + + + + + id + beginLine + + + 12 + + + + + + id + beginColumn + + + 12 + + + + + + id + endLine + + + 12 + + + + + + id + endColumn + + + 12 + + + + + + offset + id + + + 12 + + + + + + offset + beginLine + + + 12 + + + + + + offset + beginColumn + + + 12 + + + + + + offset + endLine + + + 12 + + + + + + offset + endColumn + + + 12 + + + + + + beginLine + id + + + 12 + + + + + + beginLine + offset + + + 12 + + + + + + beginLine + beginColumn + + + 12 + + + + + + beginLine + endLine + + + 12 + + + + + + beginLine + endColumn + + + 12 + + + + + + beginColumn + id + + + 12 + + + + + + beginColumn + offset + + + 12 + + + + + + beginColumn + beginLine + + + 12 + + + + + + beginColumn + endLine + + + 12 + + + + + + beginColumn + endColumn + + + 12 + + + + + + endLine + id + + + 12 + + + + + + endLine + offset + + + 12 + + + + + + endLine + beginLine + + + 12 + + + + + + endLine + beginColumn + + + 12 + + + + + + endLine + endColumn + + + 12 + + + + + + endColumn + id + + + 12 + + + + + + endColumn + offset + + + 12 + + + + + + endColumn + beginLine + + + 12 + + + + + + endColumn + beginColumn + + + 12 + + + + + + endColumn + endLine + + + 12 + + + + + + + + smap_header + 1 + + + outputFileId + 1 + + + outputFilename + 1 + + + defaultStratum + 1 + + + + + outputFileId + outputFilename + + + 12 + + + + + + outputFileId + defaultStratum + + + 12 + + + + + + outputFilename + outputFileId + + + 12 + + + + + + outputFilename + defaultStratum + + + 12 + + + + + + defaultStratum + outputFileId + + + 12 + + + + + + defaultStratum + outputFilename + + + 12 + + + + + + + + smap_files + 1 + + + outputFileId + 1 + + + stratum + 1 + + + inputFileNum + 1 + + + inputFileName + 1 + + + inputFileId + 1 + + + + + outputFileId + stratum + + + 12 + + + + + + outputFileId + inputFileNum + + + 12 + + + + + + outputFileId + inputFileName + + + 12 + + + + + + outputFileId + inputFileId + + + 12 + + + + + + stratum + outputFileId + + + 12 + + + + + + stratum + inputFileNum + + + 12 + + + + + + stratum + inputFileName + + + 12 + + + + + + stratum + inputFileId + + + 12 + + + + + + inputFileNum + outputFileId + + + 12 + + + + + + inputFileNum + stratum + + + 12 + + + + + + inputFileNum + inputFileName + + + 12 + + + + + + inputFileNum + inputFileId + + + 12 + + + + + + inputFileName + outputFileId + + + 12 + + + + + + inputFileName + stratum + + + 12 + + + + + + inputFileName + inputFileNum + + + 12 + + + + + + inputFileName + inputFileId + + + 12 + + + + + + inputFileId + outputFileId + + + 12 + + + + + + inputFileId + stratum + + + 12 + + + + + + inputFileId + inputFileNum + + + 12 + + + + + + inputFileId + inputFileName + + + 12 + + + + + + + + smap_lines + 1 + + + outputFileId + 1 + + + stratum + 1 + + + inputFileNum + 1 + + + inputStartLine + 1 + + + inputLineCount + 1 + + + outputStartLine + 1 + + + outputLineIncrement + 1 + + + + + outputFileId + stratum + + + 12 + + + + + + outputFileId + inputFileNum + + + 12 + + + + + + outputFileId + inputStartLine + + + 12 + + + + + + outputFileId + inputLineCount + + + 12 + + + + + + outputFileId + outputStartLine + + + 12 + + + + + + outputFileId + outputLineIncrement + + + 12 + + + + + + stratum + outputFileId + + + 12 + + + + + + stratum + inputFileNum + + + 12 + + + + + + stratum + inputStartLine + + + 12 + + + + + + stratum + inputLineCount + + + 12 + + + + + + stratum + outputStartLine + + + 12 + + + + + + stratum + outputLineIncrement + + + 12 + + + + + + inputFileNum + outputFileId + + + 12 + + + + + + inputFileNum + stratum + + + 12 + + + + + + inputFileNum + inputStartLine + + + 12 + + + + + + inputFileNum + inputLineCount + + + 12 + + + + + + inputFileNum + outputStartLine + + + 12 + + + + + + inputFileNum + outputLineIncrement + + + 12 + + + + + + inputStartLine + outputFileId + + + 12 + + + + + + inputStartLine + stratum + + + 12 + + + + + + inputStartLine + inputFileNum + + + 12 + + + + + + inputStartLine + inputLineCount + + + 12 + + + + + + inputStartLine + outputStartLine + + + 12 + + + + + + inputStartLine + outputLineIncrement + + + 12 + + + + + + inputLineCount + outputFileId + + + 12 + + + + + + inputLineCount + stratum + + + 12 + + + + + + inputLineCount + inputFileNum + + + 12 + + + + + + inputLineCount + inputStartLine + + + 12 + + + + + + inputLineCount + outputStartLine + + + 12 + + + + + + inputLineCount + outputLineIncrement + + + 12 + + + + + + outputStartLine + outputFileId + + + 12 + + + + + + outputStartLine + stratum + + + 12 + + + + + + outputStartLine + inputFileNum + + + 12 + + + + + + outputStartLine + inputStartLine + + + 12 + + + + + + outputStartLine + inputLineCount + + + 12 + + + + + + outputStartLine + outputLineIncrement + + + 12 + + + + + + outputLineIncrement + outputFileId + + + 12 + + + + + + outputLineIncrement + stratum + + + 12 + + + + + + outputLineIncrement + inputFileNum + + + 12 + + + + + + outputLineIncrement + inputStartLine + + + 12 + + + + + + outputLineIncrement + inputLineCount + + + 12 + + + + + + outputLineIncrement + outputStartLine + + + 12 + + + + + + + + locations_default + 602747369 + + + id + 602747369 + + + file + 9158642 + + + beginLine + 3943517 + + + beginColumn + 247790 + + + endLine + 3945438 + + + endColumn + 873989 + + + + + id + file + + + 12 + + + 1 + 2 + 602747369 + + + + + + + id + beginLine + + + 12 + + + 1 + 2 + 602747369 + + + + + + + id + beginColumn + + + 12 + + + 1 + 2 + 602747369 + + + + + + + id + endLine + + + 12 + + + 1 + 2 + 602747369 + + + + + + + id + endColumn + + + 12 + + + 1 + 2 + 602747369 + + + + + + + file + id + + + 12 + + + 1 + 2 + 7986919 + + + 2 + 11 + 714558 + + + 11 + 3605 + 457163 + + + + + + + file + beginLine + + + 12 + + + 1 + 2 + 7986919 + + + 2 + 9 + 712637 + + + 9 + 1830 + 459084 + + + + + + + file + beginColumn + + + 12 + + + 1 + 2 + 7986919 + + + 2 + 5 + 776025 + + + 5 + 105 + 395696 + + + + + + + file + endLine + + + 12 + + + 1 + 2 + 7986919 + + + 2 + 10 + 693429 + + + 10 + 1834 + 478293 + + + + + + + file + endColumn + + + 12 + + + 1 + 2 + 7986919 + + + 2 + 9 + 695349 + + + 9 + 205 + 476372 + + + + + + + beginLine + id + + + 12 + + + 1 + 14 + 313099 + + + 14 + 125 + 301574 + + + 125 + 142 + 307336 + + + 142 + 152 + 316941 + + + 152 + 159 + 359200 + + + 159 + 164 + 272761 + + + 164 + 169 + 343833 + + + 169 + 173 + 299653 + + + 173 + 178 + 332308 + + + 178 + 184 + 347674 + + + 184 + 193 + 316941 + + + 193 + 211 + 297732 + + + 211 + 4769 + 134459 + + + + + + + beginLine + file + + + 12 + + + 1 + 7 + 322703 + + + 7 + 65 + 299653 + + + 65 + 73 + 307336 + + + 73 + 78 + 295811 + + + 78 + 81 + 265078 + + + 81 + 84 + 357279 + + + 84 + 86 + 299653 + + + 86 + 87 + 188243 + + + 87 + 89 + 357279 + + + 89 + 91 + 259315 + + + 91 + 94 + 324624 + + + 94 + 99 + 328466 + + + 99 + 141 + 295811 + + + 141 + 4769 + 42258 + + + + + + + beginLine + beginColumn + + + 12 + + + 1 + 5 + 313099 + + + 5 + 17 + 280444 + + + 17 + 19 + 251632 + + + 19 + 20 + 309257 + + + 20 + 21 + 403379 + + + 21 + 22 + 420667 + + + 22 + 23 + 476372 + + + 23 + 24 + 457163 + + + 24 + 25 + 339991 + + + 25 + 26 + 213215 + + + 26 + 29 + 361120 + + + 29 + 40 + 117172 + + + + + + + beginLine + endLine + + + 12 + + + 1 + 2 + 1273527 + + + 2 + 3 + 1265844 + + + 3 + 4 + 674220 + + + 4 + 5 + 299653 + + + 5 + 11 + 307336 + + + 11 + 97 + 122934 + + + + + + + beginLine + endColumn + + + 12 + + + 1 + 13 + 309257 + + + 13 + 60 + 307336 + + + 60 + 64 + 311178 + + + 64 + 66 + 311178 + + + 66 + 68 + 353437 + + + 68 + 69 + 194006 + + + 69 + 70 + 217056 + + + 70 + 72 + 359200 + + + 72 + 74 + 322703 + + + 74 + 76 + 245869 + + + 76 + 79 + 330387 + + + 79 + 83 + 295811 + + + 83 + 91 + 316941 + + + 91 + 103 + 69150 + + + + + + + beginColumn + id + + + 12 + + + 1 + 11 + 21129 + + + 15 + 24 + 21129 + + + 28 + 57 + 19208 + + + 57 + 79 + 19208 + + + 87 + 119 + 19208 + + + 130 + 177 + 19208 + + + 195 + 269 + 19208 + + + 270 + 436 + 19208 + + + 443 + 835 + 19208 + + + 844 + 1367 + 19208 + + + 1419 + 2155 + 19208 + + + 2252 + 2517 + 19208 + + + 2521 + 226452 + 13445 + + + + + + + beginColumn + file + + + 12 + + + 1 + 9 + 17287 + + + 9 + 11 + 21129 + + + 11 + 15 + 15366 + + + 15 + 19 + 21129 + + + 23 + 68 + 19208 + + + 69 + 78 + 19208 + + + 79 + 100 + 13445 + + + 100 + 104 + 21129 + + + 104 + 109 + 19208 + + + 109 + 112 + 13445 + + + 112 + 115 + 19208 + + + 115 + 117 + 19208 + + + 117 + 123 + 19208 + + + 145 + 4769 + 9604 + + + + + + + beginColumn + beginLine + + + 12 + + + 1 + 10 + 21129 + + + 10 + 22 + 21129 + + + 23 + 39 + 19208 + + + 41 + 58 + 19208 + + + 58 + 84 + 19208 + + + 84 + 106 + 19208 + + + 108 + 166 + 19208 + + + 167 + 225 + 19208 + + + 230 + 376 + 19208 + + + 381 + 647 + 19208 + + + 657 + 941 + 19208 + + + 941 + 1090 + 19208 + + + 1102 + 2051 + 13445 + + + + + + + beginColumn + endLine + + + 12 + + + 1 + 10 + 21129 + + + 10 + 22 + 21129 + + + 23 + 39 + 19208 + + + 41 + 59 + 19208 + + + 59 + 86 + 19208 + + + 86 + 109 + 19208 + + + 114 + 168 + 19208 + + + 170 + 224 + 19208 + + + 229 + 379 + 19208 + + + 382 + 647 + 19208 + + + 658 + 941 + 19208 + + + 941 + 1089 + 19208 + + + 1102 + 2051 + 13445 + + + + + + + beginColumn + endColumn + + + 12 + + + 1 + 8 + 21129 + + + 8 + 16 + 21129 + + + 16 + 23 + 21129 + + + 24 + 31 + 21129 + + + 32 + 37 + 21129 + + + 37 + 50 + 19208 + + + 50 + 60 + 19208 + + + 60 + 68 + 19208 + + + 68 + 80 + 19208 + + + 81 + 101 + 19208 + + + 101 + 121 + 19208 + + + 126 + 158 + 19208 + + + 159 + 393 + 7683 + + + + + + + endLine + id + + + 12 + + + 1 + 14 + 309257 + + + 14 + 124 + 305416 + + + 124 + 143 + 309257 + + + 143 + 152 + 334228 + + + 152 + 159 + 322703 + + + 159 + 164 + 299653 + + + 164 + 169 + 341912 + + + 169 + 173 + 309257 + + + 173 + 178 + 338070 + + + 178 + 184 + 305416 + + + 184 + 193 + 315020 + + + 193 + 212 + 301574 + + + 212 + 4769 + 153668 + + + + + + + endLine + file + + + 12 + + + 1 + 7 + 324624 + + + 7 + 66 + 318862 + + + 66 + 74 + 320782 + + + 74 + 80 + 355358 + + + 80 + 83 + 339991 + + + 83 + 85 + 268919 + + + 85 + 87 + 343833 + + + 87 + 89 + 355358 + + + 89 + 91 + 266999 + + + 91 + 94 + 345754 + + + 94 + 99 + 324624 + + + 99 + 130 + 301574 + + + 131 + 4769 + 78755 + + + + + + + endLine + beginLine + + + 12 + + + 1 + 2 + 1000766 + + + 2 + 3 + 1392620 + + + 3 + 4 + 908564 + + + 4 + 6 + 336149 + + + 6 + 19 + 299653 + + + 19 + 22 + 7683 + + + + + + + endLine + beginColumn + + + 12 + + + 1 + 5 + 309257 + + + 5 + 17 + 284286 + + + 17 + 19 + 232423 + + + 19 + 20 + 280444 + + + 20 + 21 + 420667 + + + 21 + 22 + 407221 + + + 22 + 23 + 482134 + + + 23 + 24 + 437955 + + + 24 + 25 + 334228 + + + 25 + 26 + 259315 + + + 26 + 29 + 363041 + + + 29 + 39 + 134459 + + + + + + + endLine + endColumn + + + 12 + + + 1 + 13 + 313099 + + + 13 + 60 + 305416 + + + 60 + 64 + 305416 + + + 64 + 66 + 303495 + + + 66 + 68 + 357279 + + + 68 + 69 + 197848 + + + 69 + 70 + 201689 + + + 70 + 71 + 218977 + + + 71 + 73 + 326545 + + + 73 + 75 + 263157 + + + 75 + 77 + 257394 + + + 77 + 80 + 299653 + + + 80 + 85 + 318862 + + + 85 + 119 + 276603 + + + + + + + endColumn + id + + + 12 + + + 1 + 2 + 205531 + + + 2 + 3 + 90280 + + + 3 + 5 + 71071 + + + 5 + 13 + 71071 + + + 13 + 53 + 67229 + + + 53 + 138 + 67229 + + + 142 + 346 + 67229 + + + 357 + 967 + 67229 + + + 1050 + 2386 + 67229 + + + 2392 + 4902 + 67229 + + + 4949 + 5933 + 32654 + + + + + + + endColumn + file + + + 12 + + + 1 + 2 + 213215 + + + 2 + 3 + 86438 + + + 3 + 5 + 74913 + + + 5 + 13 + 71071 + + + 13 + 42 + 67229 + + + 42 + 77 + 67229 + + + 77 + 102 + 69150 + + + 102 + 114 + 67229 + + + 114 + 139 + 67229 + + + 139 + 169 + 69150 + + + 173 + 4769 + 21129 + + + + + + + endColumn + beginLine + + + 12 + + + 1 + 2 + 217056 + + + 2 + 3 + 88359 + + + 3 + 5 + 69150 + + + 5 + 13 + 69150 + + + 13 + 50 + 67229 + + + 50 + 113 + 67229 + + + 114 + 266 + 67229 + + + 269 + 636 + 67229 + + + 648 + 1197 + 67229 + + + 1198 + 1635 + 69150 + + + 1639 + 1722 + 24971 + + + + + + + endColumn + beginColumn + + + 12 + + + 1 + 2 + 274682 + + + 2 + 3 + 105647 + + + 3 + 6 + 76834 + + + 6 + 14 + 76834 + + + 14 + 25 + 74913 + + + 25 + 36 + 71071 + + + 36 + 47 + 67229 + + + 47 + 54 + 67229 + + + 54 + 65 + 59546 + + + + + + + endColumn + endLine + + + 12 + + + 1 + 2 + 217056 + + + 2 + 3 + 86438 + + + 3 + 5 + 69150 + + + 5 + 13 + 69150 + + + 13 + 51 + 67229 + + + 51 + 112 + 67229 + + + 112 + 262 + 67229 + + + 262 + 630 + 67229 + + + 637 + 1186 + 67229 + + + 1197 + 1625 + 67229 + + + 1632 + 1722 + 28812 + + + + + + + + + hasLocation + 340930835 + + + locatableid + 340658074 + + + id + 12195515 + + + + + locatableid + id + + + 12 + + + 1 + 2 + 340385312 + + + 2 + 3 + 272761 + + + + + + + id + locatableid + + + 12 + + + 1 + 2 + 2091812 + + + 2 + 3 + 1333074 + + + 3 + 4 + 772184 + + + 4 + 6 + 1085283 + + + 6 + 8 + 1062233 + + + 8 + 11 + 1100650 + + + 11 + 15 + 1048787 + + + 15 + 21 + 964269 + + + 21 + 32 + 916248 + + + 32 + 64 + 920090 + + + 64 + 9549 + 900881 + + + + + + + + + numlines + 303305105 + + + element_id + 303305105 + + + num_lines + 618515 + + + num_code + 612753 + + + num_comment + 1893964 + + + + + element_id + num_lines + + + 12 + + + 1 + 2 + 303305105 + + + + + + + element_id + num_code + + + 12 + + + 1 + 2 + 303305105 + + + + + + + element_id + num_comment + + + 12 + + + 1 + 2 + 303305105 + + + + + + + num_lines + element_id + + + 12 + + + 1 + 2 + 320782 + + + 2 + 3 + 78755 + + + 3 + 4 + 61467 + + + 4 + 7 + 49942 + + + 7 + 14 + 48021 + + + 15 + 194 + 48021 + + + 320 + 149659 + 11525 + + + + + + + num_lines + num_code + + + 12 + + + 1 + 2 + 509026 + + + 2 + 3 + 69150 + + + 3 + 6 + 40337 + + + + + + + num_lines + num_comment + + + 12 + + + 1 + 2 + 380329 + + + 2 + 3 + 97963 + + + 3 + 4 + 51863 + + + 4 + 6 + 53783 + + + 6 + 987 + 34575 + + + + + + + num_code + element_id + + + 12 + + + 1 + 2 + 316941 + + + 2 + 3 + 78755 + + + 3 + 4 + 61467 + + + 4 + 7 + 51863 + + + 7 + 15 + 46100 + + + 16 + 214 + 46100 + + + 325 + 78746 + 11525 + + + + + + + num_code + num_lines + + + 12 + + + 1 + 2 + 516710 + + + 2 + 3 + 51863 + + + 3 + 8 + 44179 + + + + + + + num_code + num_comment + + + 12 + + + 1 + 2 + 370725 + + + 2 + 3 + 101805 + + + 3 + 4 + 53783 + + + 4 + 6 + 46100 + + + 6 + 987 + 40337 + + + + + + + num_comment + element_id + + + 12 + + + 1 + 7 + 153668 + + + 7 + 49 + 142143 + + + 49 + 71 + 147905 + + + 71 + 78 + 151747 + + + 78 + 83 + 145985 + + + 83 + 87 + 163272 + + + 87 + 89 + 140222 + + + 89 + 91 + 134459 + + + 91 + 92 + 80675 + + + 92 + 93 + 96042 + + + 93 + 94 + 105647 + + + 94 + 95 + 97963 + + + 95 + 97 + 151747 + + + 97 + 119 + 144064 + + + 120 + 75134 + 38417 + + + + + + + num_comment + num_lines + + + 12 + + + 1 + 2 + 1550130 + + + 2 + 3 + 165193 + + + 3 + 7 + 145985 + + + 7 + 120 + 32654 + + + + + + + num_comment + num_code + + + 12 + + + 1 + 2 + 1550130 + + + 2 + 3 + 165193 + + + 3 + 7 + 145985 + + + 7 + 122 + 32654 + + + + + + + + + files + 9158642 + + + id + 9158642 + + + name + 9158642 + + + + + id + name + + + 12 + + + 1 + 2 + 9158642 + + + + + + + name + id + + + 12 + + + 1 + 2 + 9158642 + + + + + + + + + folders + 1415670 + + + id + 1415670 + + + name + 1415670 + + + + + id + name + + + 12 + + + 1 + 2 + 1415670 + + + + + + + name + id + + + 12 + + + 1 + 2 + 1415670 + + + + + + + + + containerparent + 10570471 + + + parent + 1463692 + + + child + 10570471 + + + + + parent + child + + + 12 + + + 1 + 2 + 843255 + + + 2 + 3 + 149826 + + + 3 + 5 + 128697 + + + 5 + 11 + 124855 + + + 11 + 21 + 113330 + + + 21 + 194 + 103726 + + + + + + + child + parent + + + 12 + + + 1 + 2 + 10570471 + + + + + + + + + cupackage + 7979236 + + + id + 7979236 + + + packageid + 576256 + + + + + id + packageid + + + 12 + + + 1 + 2 + 7979236 + + + + + + + packageid + id + + + 12 + + + 1 + 2 + 121013 + + + 2 + 3 + 80675 + + + 3 + 4 + 42258 + + + 4 + 6 + 49942 + + + 6 + 9 + 49942 + + + 9 + 12 + 51863 + + + 12 + 17 + 48021 + + + 17 + 23 + 46100 + + + 24 + 43 + 44179 + + + 43 + 187 + 42258 + + + + + + + + + jarManifestMain + 172742 + + + fileid + 13275 + + + keyName + 12611 + + + value + 89772 + + + + + fileid + keyName + + + 12 + + + 1 + 4 + 995 + + + 5 + 6 + 2323 + + + 6 + 7 + 2157 + + + 9 + 13 + 1161 + + + 13 + 15 + 1161 + + + 15 + 17 + 829 + + + 17 + 18 + 829 + + + 19 + 21 + 829 + + + 21 + 24 + 1161 + + + 24 + 27 + 1161 + + + 28 + 35 + 663 + + + + + + + fileid + value + + + 12 + + + 1 + 4 + 995 + + + 5 + 6 + 2489 + + + 6 + 7 + 1991 + + + 8 + 10 + 663 + + + 10 + 12 + 995 + + + 12 + 13 + 663 + + + 14 + 15 + 995 + + + 15 + 17 + 1161 + + + 17 + 18 + 829 + + + 18 + 20 + 1161 + + + 21 + 24 + 1161 + + + 29 + 30 + 165 + + + + + + + keyName + fileid + + + 12 + + + 1 + 2 + 5144 + + + 2 + 3 + 829 + + + 3 + 4 + 829 + + + 5 + 8 + 995 + + + 10 + 20 + 995 + + + 24 + 28 + 829 + + + 28 + 31 + 995 + + + 32 + 38 + 995 + + + 39 + 81 + 995 + + + + + + + keyName + value + + + 12 + + + 1 + 2 + 5807 + + + 2 + 3 + 995 + + + 3 + 5 + 995 + + + 5 + 8 + 995 + + + 10 + 16 + 1161 + + + 17 + 26 + 1161 + + + 27 + 36 + 995 + + + 37 + 53 + 497 + + + + + + + value + fileid + + + 12 + + + 1 + 2 + 75999 + + + 2 + 3 + 4480 + + + 3 + 6 + 6969 + + + 6 + 81 + 2323 + + + + + + + value + keyName + + + 12 + + + 1 + 2 + 75668 + + + 2 + 3 + 8794 + + + 3 + 6 + 5310 + + + + + + + + + jarManifestEntries + 30201 + + + fileid + 61 + + + entryName + 30129 + + + keyName + 27 + + + value + 30163 + + + + + fileid + entryName + + + 12 + + + 1 + 2 + 4 + + + 4 + 10 + 3 + + + 10 + 12 + 4 + + + 12 + 31 + 4 + + + 65 + 82 + 4 + + + 123 + 164 + 4 + + + 178 + 240 + 4 + + + 253 + 294 + 4 + + + 307 + 357 + 4 + + + 361 + 395 + 4 + + + 433 + 461 + 4 + + + 591 + 662 + 4 + + + 957 + 2267 + 4 + + + 3647 + 3762 + 3 + + + + + + + fileid + keyName + + + 12 + + + 1 + 2 + 57 + + + 6 + 10 + 3 + + + + + + + fileid + value + + + 12 + + + 1 + 2 + 4 + + + 3 + 8 + 4 + + + 9 + 13 + 4 + + + 24 + 66 + 4 + + + 70 + 124 + 4 + + + 127 + 179 + 4 + + + 195 + 254 + 4 + + + 265 + 308 + 4 + + + 320 + 362 + 4 + + + 381 + 434 + 4 + + + 434 + 592 + 4 + + + 618 + 958 + 4 + + + 1671 + 3648 + 4 + + + 3761 + 3762 + 1 + + + + + + + entryName + fileid + + + 12 + + + 1 + 2 + 30113 + + + 2 + 26 + 16 + + + + + + + entryName + keyName + + + 12 + + + 1 + 2 + 30126 + + + 6 + 10 + 3 + + + + + + + entryName + value + + + 12 + + + 1 + 2 + 30125 + + + 3 + 26 + 4 + + + + + + + keyName + fileid + + + 12 + + + 1 + 2 + 21 + + + 2 + 3 + 3 + + + 3 + 4 + 1 + + + 32 + 33 + 1 + + + + + + + keyName + entryName + + + 12 + + + 1 + 2 + 21 + + + 2 + 3 + 1 + + + 11 + 12 + 1 + + + 369 + 370 + 1 + + + 19366 + 19367 + 1 + + + + + + + keyName + value + + + 12 + + + 1 + 2 + 22 + + + 2 + 3 + 1 + + + 369 + 370 + 1 + + + 19390 + 19391 + 1 + + + + + + + value + fileid + + + 12 + + + 1 + 2 + 30162 + + + 2 + 3 + 1 + + + + + + + value + entryName + + + 12 + + + 1 + 2 + 30162 + + + 11 + 12 + 1 + + + + + + + value + keyName + + + 12 + + + 1 + 2 + 30155 + + + 2 + 3 + 7 + + + + + + + + + packages + 580098 + + + id + 580098 + + + nodeName + 580098 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 580098 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 580098 + + + + + + + + + primitives + 17287 + + + id + 17287 + + + nodeName + 17287 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 17287 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 17287 + + + + + + + + + modifiers + 26891 + + + id + 26891 + + + nodeName + 26891 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 26891 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 26891 + + + + + + + + + error_type + 1 + + + id + 1 + + + + + + classes + 12618104 + + + id + 12618104 + + + nodeName + 6732600 + + + parentid + 455242 + + + sourceid + 5253541 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 12618104 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 12618104 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 12618104 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 5601216 + + + 2 + 3 + 726083 + + + 3 + 204 + 405300 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 5950812 + + + 2 + 3 + 731846 + + + 3 + 52 + 49942 + + + + + + + nodeName + sourceid + + + 12 + + + 1 + 2 + 5921999 + + + 2 + 3 + 714558 + + + 3 + 160 + 96042 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 94121 + + + 2 + 3 + 46100 + + + 3 + 4 + 30733 + + + 4 + 5 + 26891 + + + 5 + 6 + 24971 + + + 6 + 8 + 40337 + + + 8 + 12 + 32654 + + + 12 + 18 + 38417 + + + 18 + 23 + 34575 + + + 23 + 40 + 36496 + + + 40 + 76 + 34575 + + + 83 + 891 + 15366 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 96042 + + + 2 + 3 + 46100 + + + 3 + 4 + 34575 + + + 4 + 5 + 28812 + + + 5 + 6 + 36496 + + + 6 + 9 + 40337 + + + 9 + 13 + 40337 + + + 13 + 18 + 26891 + + + 18 + 25 + 38417 + + + 26 + 41 + 36496 + + + 41 + 479 + 30733 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 99884 + + + 2 + 3 + 57625 + + + 3 + 4 + 36496 + + + 4 + 5 + 32654 + + + 5 + 6 + 32654 + + + 6 + 8 + 34575 + + + 8 + 12 + 38417 + + + 12 + 18 + 32654 + + + 18 + 25 + 34575 + + + 25 + 47 + 34575 + + + 51 + 138 + 21129 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 4694572 + + + 2 + 11 + 407221 + + + 11 + 426 + 151747 + + + + + + + sourceid + nodeName + + + 12 + + + 1 + 2 + 4694572 + + + 2 + 6 + 426430 + + + 6 + 224 + 132539 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 5253541 + + + + + + + + + file_class + 17287 + + + id + 17287 + + + + + + class_object + 163272 + + + id + 163272 + + + instance + 163272 + + + + + id + instance + + + 12 + + + 1 + 2 + 163272 + + + + + + + instance + id + + + 12 + + + 1 + 2 + 163272 + + + + + + + + + type_companion_object + 307336 + + + id + 307336 + + + instance + 307336 + + + companion_object + 307336 + + + + + id + instance + + + 12 + + + 1 + 2 + 307336 + + + + + + + id + companion_object + + + 12 + + + 1 + 2 + 307336 + + + + + + + instance + id + + + 12 + + + 1 + 2 + 307336 + + + + + + + instance + companion_object + + + 12 + + + 1 + 2 + 307336 + + + + + + + companion_object + id + + + 12 + + + 1 + 2 + 307336 + + + + + + + companion_object + instance + + + 12 + + + 1 + 2 + 307336 + + + + + + + + + kt_nullable_types + 1920 + + + id + 1920 + + + classid + 1920 + + + + + id + classid + + + 12 + + + 1 + 2 + 1920 + + + + + + + classid + id + + + 12 + + + 1 + 2 + 1920 + + + + + + + + + kt_notnull_types + 172391 + + + id + 172391 + + + classid + 172391 + + + + + id + classid + + + 12 + + + 1 + 2 + 172391 + + + + + + + classid + id + + + 12 + + + 1 + 2 + 172391 + + + + + + + + + kt_type_alias + 1821 + + + id + 1821 + + + name + 1821 + + + kttypeid + 910 + + + + + id + name + + + 12 + + + 1 + 2 + 1821 + + + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 1821 + + + + + + + name + id + + + 12 + + + 1 + 2 + 1821 + + + + + + + name + kttypeid + + + 12 + + + 1 + 2 + 1821 + + + + + + + kttypeid + id + + + 12 + + + 2 + 3 + 910 + + + + + + + kttypeid + name + + + 12 + + + 2 + 3 + 910 + + + + + + + + + isRecord + 417 + + + id + 417 + + + + + + interfaces + 23200100 + + + id + 23200100 + + + nodeName + 8705320 + + + parentid + 430271 + + + sourceid + 2787162 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 23200100 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 23200100 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 23200100 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 6834406 + + + 2 + 3 + 1079521 + + + 3 + 25 + 655011 + + + 25 + 345 + 136380 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 7996524 + + + 2 + 4 + 695349 + + + 4 + 7 + 13445 + + + + + + + nodeName + sourceid + + + 12 + + + 1 + 2 + 7967711 + + + 2 + 4 + 718400 + + + 4 + 7 + 19208 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 113330 + + + 2 + 3 + 55704 + + + 3 + 4 + 48021 + + + 4 + 5 + 26891 + + + 5 + 8 + 36496 + + + 8 + 13 + 34575 + + + 13 + 18 + 34575 + + + 18 + 41 + 32654 + + + 42 + 182 + 32654 + + + 187 + 4152 + 15366 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 113330 + + + 2 + 3 + 55704 + + + 3 + 4 + 48021 + + + 4 + 5 + 38417 + + + 5 + 7 + 24971 + + + 7 + 10 + 32654 + + + 10 + 15 + 36496 + + + 15 + 28 + 32654 + + + 30 + 94 + 32654 + + + 100 + 1213 + 15366 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 140222 + + + 2 + 3 + 65309 + + + 3 + 4 + 44179 + + + 4 + 5 + 34575 + + + 5 + 7 + 28812 + + + 7 + 9 + 34575 + + + 9 + 14 + 34575 + + + 14 + 26 + 32654 + + + 26 + 160 + 15366 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 2391465 + + + 2 + 11 + 213215 + + + 11 + 1565 + 182481 + + + + + + + sourceid + nodeName + + + 12 + + + 1 + 2 + 2391465 + + + 2 + 6 + 217056 + + + 6 + 492 + 178639 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 2787162 + + + + + + + + + fielddecls + 199475 + + + id + 199475 + + + parentid + 25503 + + + + + id + parentid + + + 12 + + + 1 + 2 + 199475 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 4554 + + + 2 + 3 + 5465 + + + 3 + 4 + 1821 + + + 4 + 6 + 1821 + + + 6 + 7 + 2732 + + + 7 + 9 + 1821 + + + 9 + 10 + 910 + + + 10 + 11 + 1821 + + + 13 + 18 + 1821 + + + 19 + 20 + 1821 + + + 57 + 58 + 910 + + + + + + + + + fieldDeclaredIn + 199475 + + + fieldId + 199475 + + + fieldDeclId + 199475 + + + pos + 910 + + + + + fieldId + fieldDeclId + + + 12 + + + 1 + 2 + 199475 + + + + + + + fieldId + pos + + + 12 + + + 1 + 2 + 199475 + + + + + + + fieldDeclId + fieldId + + + 12 + + + 1 + 2 + 199475 + + + + + + + fieldDeclId + pos + + + 12 + + + 1 + 2 + 199475 + + + + + + + pos + fieldId + + + 12 + + + 219 + 220 + 910 + + + + + + + pos + fieldDeclId + + + 12 + + + 219 + 220 + 910 + + + + + + + + + fields + 19350704 + + + id + 19350704 + + + nodeName + 13628474 + + + typeid + 3038794 + + + parentid + 4089502 + + + sourceid + 19350704 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 19350704 + + + + + + + id + typeid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 12016876 + + + 2 + 3 + 1123700 + + + 3 + 722 + 487897 + + + + + + + nodeName + typeid + + + 12 + + + 1 + 2 + 12416414 + + + 2 + 5 + 1085283 + + + 5 + 160 + 126776 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 12016876 + + + 2 + 3 + 1123700 + + + 3 + 722 + 487897 + + + + + + + nodeName + sourceid + + + 12 + + + 1 + 2 + 12016876 + + + 2 + 3 + 1123700 + + + 3 + 722 + 487897 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 2059157 + + + 2 + 3 + 320782 + + + 3 + 4 + 213215 + + + 4 + 8 + 245869 + + + 8 + 2588 + 199769 + + + + + + + typeid + nodeName + + + 12 + + + 1 + 2 + 2120625 + + + 2 + 3 + 299653 + + + 3 + 4 + 199769 + + + 4 + 9 + 255473 + + + 9 + 2016 + 163272 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 2706486 + + + 2 + 4 + 251632 + + + 4 + 1014 + 80675 + + + + + + + typeid + sourceid + + + 12 + + + 1 + 2 + 2059157 + + + 2 + 3 + 320782 + + + 3 + 4 + 213215 + + + 4 + 8 + 245869 + + + 8 + 2588 + 199769 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 2427962 + + + 2 + 3 + 478293 + + + 3 + 4 + 303495 + + + 4 + 6 + 338070 + + + 6 + 13 + 330387 + + + 13 + 1610 + 211294 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 2427962 + + + 2 + 3 + 478293 + + + 3 + 4 + 303495 + + + 4 + 6 + 338070 + + + 6 + 13 + 330387 + + + 13 + 1610 + 211294 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 3031110 + + + 2 + 3 + 595465 + + + 3 + 5 + 347674 + + + 5 + 76 + 115251 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 2427962 + + + 2 + 3 + 478293 + + + 3 + 4 + 303495 + + + 4 + 6 + 338070 + + + 6 + 13 + 330387 + + + 13 + 1610 + 211294 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 19350704 + + + + + + + sourceid + nodeName + + + 12 + + + 1 + 2 + 19350704 + + + + + + + sourceid + typeid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + + + fieldsKotlinType + 19350704 + + + id + 19350704 + + + kttypeid + 1920 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 19350704 + + + + + + + kttypeid + id + + + 12 + + + 10074 + 10075 + 1920 + + + + + + + + + constrs + 8006128 + + + id + 8006128 + + + nodeName + 4333451 + + + signature + 6803672 + + + typeid + 3841 + + + parentid + 5639633 + + + sourceid + 5720309 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 8006128 + + + + + + + id + signature + + + 12 + + + 1 + 2 + 8006128 + + + + + + + id + typeid + + + 12 + + + 1 + 2 + 8006128 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 8006128 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 8006128 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 2623889 + + + 2 + 3 + 1085283 + + + 3 + 4 + 259315 + + + 4 + 11 + 326545 + + + 11 + 36 + 38417 + + + + + + + nodeName + signature + + + 12 + + + 1 + 2 + 2977327 + + + 2 + 3 + 868226 + + + 3 + 5 + 341912 + + + 5 + 19 + 145985 + + + + + + + nodeName + typeid + + + 12 + + + 1 + 2 + 4333451 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 3764878 + + + 2 + 3 + 401458 + + + 3 + 36 + 167114 + + + + + + + nodeName + sourceid + + + 12 + + + 1 + 2 + 2737220 + + + 2 + 3 + 1083362 + + + 3 + 5 + 353437 + + + 5 + 32 + 159431 + + + + + + + signature + id + + + 12 + + + 1 + 2 + 6302329 + + + 2 + 36 + 501343 + + + + + + + signature + nodeName + + + 12 + + + 1 + 2 + 6803672 + + + + + + + signature + typeid + + + 12 + + + 1 + 2 + 6803672 + + + + + + + signature + parentid + + + 12 + + + 1 + 2 + 6302329 + + + 2 + 36 + 501343 + + + + + + + signature + sourceid + + + 12 + + + 1 + 2 + 6461760 + + + 2 + 23 + 341912 + + + + + + + typeid + id + + + 12 + + + 22 + 23 + 1920 + + + 4146 + 4147 + 1920 + + + + + + + typeid + nodeName + + + 12 + + + 1 + 2 + 1920 + + + 2255 + 2256 + 1920 + + + + + + + typeid + signature + + + 12 + + + 1 + 2 + 1920 + + + 3541 + 3542 + 1920 + + + + + + + typeid + parentid + + + 12 + + + 22 + 23 + 1920 + + + 2914 + 2915 + 1920 + + + + + + + typeid + sourceid + + + 12 + + + 22 + 23 + 1920 + + + 2956 + 2957 + 1920 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 4256617 + + + 2 + 3 + 895118 + + + 3 + 6 + 434113 + + + 6 + 19 + 53783 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 5639633 + + + + + + + parentid + signature + + + 12 + + + 1 + 2 + 4256617 + + + 2 + 3 + 895118 + + + 3 + 6 + 434113 + + + 6 + 19 + 53783 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 5639633 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 4256617 + + + 2 + 3 + 895118 + + + 3 + 6 + 434113 + + + 6 + 19 + 53783 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 5357267 + + + 2 + 209 + 363041 + + + + + + + sourceid + nodeName + + + 12 + + + 1 + 2 + 5357267 + + + 2 + 172 + 363041 + + + + + + + sourceid + signature + + + 12 + + + 1 + 2 + 5357267 + + + 2 + 172 + 363041 + + + + + + + sourceid + typeid + + + 12 + + + 1 + 2 + 5720309 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 5357267 + + + 2 + 209 + 363041 + + + + + + + + + constrsKotlinType + 8006128 + + + id + 8006128 + + + kttypeid + 1920 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 8006128 + + + + + + + kttypeid + id + + + 12 + + + 4168 + 4169 + 1920 + + + + + + + + + methods + 109719302 + + + id + 109719302 + + + nodeName + 22908130 + + + signature + 33369112 + + + typeid + 13338425 + + + parentid + 12810189 + + + sourceid + 67091663 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 109719302 + + + + + + + id + signature + + + 12 + + + 1 + 2 + 109719302 + + + + + + + id + typeid + + + 12 + + + 1 + 2 + 109719302 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 109719302 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 109719302 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 13324979 + + + 2 + 3 + 4070294 + + + 3 + 4 + 1573181 + + + 4 + 7 + 2026503 + + + 7 + 56 + 1719166 + + + 57 + 1769 + 194006 + + + + + + + nodeName + signature + + + 12 + + + 1 + 2 + 19150935 + + + 2 + 3 + 2228193 + + + 3 + 298 + 1529001 + + + + + + + nodeName + typeid + + + 12 + + + 1 + 2 + 19179748 + + + 2 + 3 + 1872834 + + + 3 + 25 + 1726849 + + + 25 + 741 + 128697 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 14028012 + + + 2 + 3 + 3889733 + + + 3 + 4 + 1502109 + + + 4 + 7 + 1817129 + + + 7 + 1099 + 1671144 + + + + + + + nodeName + sourceid + + + 12 + + + 1 + 2 + 13743725 + + + 2 + 3 + 4283509 + + + 3 + 4 + 1544368 + + + 4 + 7 + 1857467 + + + 7 + 800 + 1479059 + + + + + + + signature + id + + + 12 + + + 1 + 2 + 22735253 + + + 2 + 3 + 5434102 + + + 3 + 5 + 2635414 + + + 5 + 157 + 2502875 + + + 157 + 1096 + 61467 + + + + + + + signature + nodeName + + + 12 + + + 1 + 2 + 33369112 + + + + + + + signature + typeid + + + 12 + + + 1 + 2 + 29957672 + + + 2 + 5 + 2650781 + + + 5 + 739 + 760659 + + + + + + + signature + parentid + + + 12 + + + 1 + 2 + 22741015 + + + 2 + 3 + 5432181 + + + 3 + 5 + 2631572 + + + 5 + 157 + 2502875 + + + 157 + 1096 + 61467 + + + + + + + signature + sourceid + + + 12 + + + 1 + 2 + 23365294 + + + 2 + 3 + 5656921 + + + 3 + 6 + 2900492 + + + 6 + 795 + 1446404 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 6603903 + + + 2 + 3 + 2729536 + + + 3 + 4 + 1208218 + + + 4 + 6 + 1119859 + + + 6 + 15 + 1019974 + + + 15 + 10335 + 656932 + + + + + + + typeid + nodeName + + + 12 + + + 1 + 2 + 8714924 + + + 2 + 3 + 2620047 + + + 3 + 6 + 1167880 + + + 6 + 2888 + 835572 + + + + + + + typeid + signature + + + 12 + + + 1 + 2 + 8565097 + + + 2 + 3 + 2602760 + + + 3 + 6 + 1210139 + + + 6 + 4142 + 960428 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 7714158 + + + 2 + 3 + 2869759 + + + 3 + 4 + 1108333 + + + 4 + 8 + 1069916 + + + 8 + 2865 + 576256 + + + + + + + typeid + sourceid + + + 12 + + + 1 + 2 + 7166714 + + + 2 + 3 + 2524004 + + + 3 + 4 + 1096808 + + + 4 + 6 + 1094888 + + + 6 + 16 + 1016132 + + + 16 + 6435 + 439876 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 3630418 + + + 2 + 3 + 1456008 + + + 3 + 4 + 1164038 + + + 4 + 5 + 735687 + + + 5 + 7 + 1021895 + + + 7 + 10 + 1106413 + + + 10 + 13 + 1146751 + + + 13 + 21 + 1181326 + + + 21 + 40 + 1021895 + + + 40 + 319 + 345754 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 3678439 + + + 2 + 3 + 1457929 + + + 3 + 4 + 1231268 + + + 4 + 5 + 791392 + + + 5 + 7 + 960428 + + + 7 + 10 + 1183247 + + + 10 + 13 + 1102571 + + + 13 + 18 + 849018 + + + 18 + 26 + 968111 + + + 26 + 290 + 587781 + + + + + + + parentid + signature + + + 12 + + + 1 + 2 + 3630418 + + + 2 + 3 + 1456008 + + + 3 + 4 + 1164038 + + + 4 + 5 + 735687 + + + 5 + 7 + 1021895 + + + 7 + 10 + 1106413 + + + 10 + 13 + 1146751 + + + 13 + 21 + 1181326 + + + 21 + 40 + 1021895 + + + 40 + 319 + 345754 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 4348818 + + + 2 + 3 + 1757583 + + + 3 + 4 + 1436800 + + + 4 + 5 + 922010 + + + 5 + 6 + 743371 + + + 6 + 7 + 564731 + + + 7 + 8 + 879752 + + + 8 + 11 + 1160197 + + + 11 + 31 + 964269 + + + 33 + 78 + 32654 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 3630418 + + + 2 + 3 + 1456008 + + + 3 + 4 + 1164038 + + + 4 + 5 + 735687 + + + 5 + 7 + 1021895 + + + 7 + 10 + 1106413 + + + 10 + 13 + 1146751 + + + 13 + 21 + 1181326 + + + 21 + 40 + 1021895 + + + 40 + 319 + 345754 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 61836200 + + + 2 + 50 + 5032643 + + + 52 + 286 + 222819 + + + + + + + sourceid + nodeName + + + 12 + + + 1 + 2 + 67091663 + + + + + + + sourceid + signature + + + 12 + + + 1 + 2 + 66767038 + + + 2 + 284 + 324624 + + + + + + + sourceid + typeid + + + 12 + + + 1 + 2 + 65030584 + + + 2 + 209 + 2061078 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 61836200 + + + 2 + 50 + 5032643 + + + 52 + 286 + 222819 + + + + + + + + + methodsKotlinType + 109719302 + + + id + 109719302 + + + kttypeid + 1920 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 109719302 + + + + + + + kttypeid + id + + + 12 + + + 57120 + 57121 + 1920 + + + + + + + + + params + 120852585 + + + id + 120852585 + + + typeid + 12833239 + + + pos + 42258 + + + parentid + 65007534 + + + sourceid + 73639861 + + + + + id + typeid + + + 12 + + + 1 + 2 + 120852585 + + + + + + + id + pos + + + 12 + + + 1 + 2 + 120852585 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 120852585 + + + + + + + id + sourceid + + + 12 + + + 1 + 2 + 120852585 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 6763334 + + + 2 + 3 + 1945827 + + + 3 + 4 + 948902 + + + 4 + 6 + 1148671 + + + 6 + 12 + 1018053 + + + 12 + 326 + 966190 + + + 343 + 6738 + 42258 + + + + + + + typeid + pos + + + 12 + + + 1 + 2 + 10436011 + + + 2 + 3 + 1342678 + + + 3 + 8 + 964269 + + + 8 + 17 + 90280 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 7005362 + + + 2 + 3 + 1895885 + + + 3 + 4 + 975794 + + + 4 + 6 + 1087204 + + + 6 + 13 + 1008449 + + + 13 + 4326 + 860543 + + + + + + + typeid + sourceid + + + 12 + + + 1 + 2 + 7216656 + + + 2 + 3 + 1788317 + + + 3 + 4 + 996924 + + + 4 + 6 + 1117938 + + + 6 + 13 + 1002686 + + + 13 + 5757 + 710716 + + + + + + + pos + id + + + 12 + + + 1 + 2 + 3841 + + + 50 + 53 + 3841 + + + 104 + 106 + 3841 + + + 157 + 165 + 3841 + + + 214 + 231 + 3841 + + + 291 + 315 + 3841 + + + 485 + 606 + 3841 + + + 804 + 1067 + 3841 + + + 1445 + 2015 + 3841 + + + 3084 + 5199 + 3841 + + + 12689 + 33844 + 3841 + + + + + + + pos + typeid + + + 12 + + + 1 + 2 + 3841 + + + 2 + 5 + 3841 + + + 6 + 7 + 3841 + + + 11 + 14 + 3841 + + + 15 + 20 + 3841 + + + 27 + 37 + 3841 + + + 57 + 75 + 3841 + + + 97 + 153 + 3841 + + + 201 + 289 + 3841 + + + 403 + 777 + 3841 + + + 1979 + 5089 + 3841 + + + + + + + pos + parentid + + + 12 + + + 1 + 2 + 3841 + + + 50 + 53 + 3841 + + + 104 + 106 + 3841 + + + 157 + 165 + 3841 + + + 214 + 231 + 3841 + + + 291 + 315 + 3841 + + + 485 + 606 + 3841 + + + 804 + 1067 + 3841 + + + 1445 + 2015 + 3841 + + + 3084 + 5199 + 3841 + + + 12689 + 33844 + 3841 + + + + + + + pos + sourceid + + + 12 + + + 1 + 2 + 3841 + + + 2 + 5 + 3841 + + + 6 + 8 + 3841 + + + 11 + 15 + 3841 + + + 16 + 29 + 3841 + + + 39 + 63 + 3841 + + + 101 + 144 + 3841 + + + 210 + 386 + 3841 + + + 628 + 1069 + 3841 + + + 1955 + 3748 + 3841 + + + 8555 + 21355 + 3841 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 40633790 + + + 2 + 3 + 14389133 + + + 3 + 4 + 4060689 + + + 4 + 10 + 4992305 + + + 10 + 23 + 931615 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 45326442 + + + 2 + 3 + 14805959 + + + 3 + 23 + 4875132 + + + + + + + parentid + pos + + + 12 + + + 1 + 2 + 40633790 + + + 2 + 3 + 14389133 + + + 3 + 4 + 4060689 + + + 4 + 10 + 4992305 + + + 10 + 23 + 931615 + + + + + + + parentid + sourceid + + + 12 + + + 1 + 2 + 40633790 + + + 2 + 3 + 14389133 + + + 3 + 4 + 4060689 + + + 4 + 10 + 4992305 + + + 10 + 23 + 931615 + + + + + + + sourceid + id + + + 12 + + + 1 + 2 + 68584168 + + + 2 + 286 + 5055693 + + + + + + + sourceid + typeid + + + 12 + + + 1 + 2 + 71932220 + + + 2 + 286 + 1707641 + + + + + + + sourceid + pos + + + 12 + + + 1 + 2 + 73639861 + + + + + + + sourceid + parentid + + + 12 + + + 1 + 2 + 68584168 + + + 2 + 286 + 5055693 + + + + + + + + + paramsKotlinType + 120852585 + + + id + 120852585 + + + kttypeid + 1920 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 120852585 + + + + + + + kttypeid + id + + + 12 + + + 62916 + 62917 + 1920 + + + + + + + + + paramName + 15639610 + + + id + 15639610 + + + nodeName + 2335761 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 15639610 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 998845 + + + 2 + 3 + 451401 + + + 3 + 4 + 249711 + + + 4 + 5 + 170956 + + + 5 + 8 + 182481 + + + 8 + 18 + 176718 + + + 18 + 769 + 105647 + + + + + + + + + isVarargsParam + 945061 + + + param + 945061 + + + + + + exceptions + 1232644 + + + id + 1232644 + + + typeid + 36990 + + + parentid + 987367 + + + + + id + typeid + + + 12 + + + 1 + 2 + 1232644 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 1232644 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 11950 + + + 2 + 3 + 3983 + + + 3 + 4 + 4552 + + + 4 + 7 + 2276 + + + 7 + 8 + 2845 + + + 9 + 13 + 3414 + + + 20 + 35 + 2845 + + + 41 + 93 + 2845 + + + 106 + 813 + 2276 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 11950 + + + 2 + 3 + 3983 + + + 3 + 4 + 4552 + + + 4 + 7 + 2276 + + + 7 + 8 + 2845 + + + 9 + 13 + 3414 + + + 20 + 35 + 2845 + + + 41 + 93 + 2845 + + + 106 + 813 + 2276 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 755179 + + + 2 + 3 + 224220 + + + 3 + 6 + 7967 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 755179 + + + 2 + 3 + 224220 + + + 3 + 6 + 7967 + + + + + + + + + isAnnotType + 29260 + + + interfaceid + 29260 + + + + + + isAnnotElem + 61065 + + + methodid + 61065 + + + + + + annotValue + 1574925 + + + parentid + 568174 + + + id2 + 52104 + + + value + 1574925 + + + + + parentid + id2 + + + 12 + + + 1 + 2 + 153493 + + + 2 + 3 + 252724 + + + 3 + 4 + 48951 + + + 4 + 6 + 26550 + + + 6 + 7 + 35179 + + + 7 + 9 + 46628 + + + 9 + 13 + 4646 + + + + + + + parentid + value + + + 12 + + + 1 + 2 + 138061 + + + 2 + 3 + 268157 + + + 3 + 4 + 47292 + + + 4 + 6 + 26052 + + + 6 + 8 + 39659 + + + 8 + 10 + 44139 + + + 10 + 13 + 4812 + + + + + + + id2 + parentid + + + 12 + + + 1 + 2 + 17091 + + + 2 + 3 + 5144 + + + 3 + 4 + 2655 + + + 4 + 6 + 4812 + + + 6 + 9 + 4314 + + + 9 + 15 + 4148 + + + 16 + 25 + 4314 + + + 27 + 86 + 3982 + + + 86 + 153 + 4148 + + + 164 + 1105 + 1493 + + + + + + + id2 + value + + + 12 + + + 1 + 2 + 15266 + + + 2 + 3 + 6637 + + + 3 + 4 + 2820 + + + 4 + 6 + 3816 + + + 6 + 8 + 3816 + + + 8 + 10 + 4812 + + + 10 + 25 + 4148 + + + 25 + 53 + 3982 + + + 53 + 132 + 3982 + + + 134 + 1105 + 2820 + + + + + + + value + parentid + + + 12 + + + 1 + 2 + 1574925 + + + + + + + value + id2 + + + 12 + + + 1 + 2 + 1574925 + + + + + + + + + isEnumType + 397617 + + + classid + 397617 + + + + + + isEnumConst + 3081053 + + + fieldid + 3081053 + + + + + + typeVars + 6288883 + + + id + 6288883 + + + nodeName + 86438 + + + pos + 7683 + + + kind + 1920 + + + parentid + 4444861 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 6288883 + + + + + + + id + pos + + + 12 + + + 1 + 2 + 6288883 + + + + + + + id + kind + + + 12 + + + 1 + 2 + 6288883 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 6288883 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 21129 + + + 2 + 3 + 11525 + + + 3 + 4 + 9604 + + + 4 + 7 + 7683 + + + 7 + 10 + 7683 + + + 10 + 28 + 7683 + + + 36 + 69 + 7683 + + + 71 + 412 + 7683 + + + 603 + 710 + 5762 + + + + + + + nodeName + pos + + + 12 + + + 1 + 2 + 51863 + + + 2 + 3 + 23050 + + + 3 + 4 + 9604 + + + 4 + 5 + 1920 + + + + + + + nodeName + kind + + + 12 + + + 1 + 2 + 86438 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 21129 + + + 2 + 3 + 11525 + + + 3 + 4 + 9604 + + + 4 + 7 + 7683 + + + 7 + 10 + 7683 + + + 10 + 28 + 7683 + + + 36 + 69 + 7683 + + + 71 + 412 + 7683 + + + 603 + 710 + 5762 + + + + + + + pos + id + + + 12 + + + 6 + 7 + 1920 + + + 89 + 90 + 1920 + + + 865 + 866 + 1920 + + + 2314 + 2315 + 1920 + + + + + + + pos + nodeName + + + 12 + + + 2 + 3 + 1920 + + + 13 + 14 + 1920 + + + 21 + 22 + 1920 + + + 34 + 35 + 1920 + + + + + + + pos + kind + + + 12 + + + 1 + 2 + 7683 + + + + + + + pos + parentid + + + 12 + + + 6 + 7 + 1920 + + + 89 + 90 + 1920 + + + 865 + 866 + 1920 + + + 2314 + 2315 + 1920 + + + + + + + kind + id + + + 12 + + + 3274 + 3275 + 1920 + + + + + + + kind + nodeName + + + 12 + + + 45 + 46 + 1920 + + + + + + + kind + pos + + + 12 + + + 4 + 5 + 1920 + + + + + + + kind + parentid + + + 12 + + + 2314 + 2315 + 1920 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 2783320 + + + 2 + 3 + 1490584 + + + 3 + 5 + 170956 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 2783320 + + + 2 + 3 + 1490584 + + + 3 + 5 + 170956 + + + + + + + parentid + pos + + + 12 + + + 1 + 2 + 2783320 + + + 2 + 3 + 1490584 + + + 3 + 5 + 170956 + + + + + + + parentid + kind + + + 12 + + + 1 + 2 + 4444861 + + + + + + + + + wildcards + 3338447 + + + id + 3338447 + + + nodeName + 533998 + + + kind + 3841 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 3338447 + + + + + + + id + kind + + + 12 + + + 1 + 2 + 3338447 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 397617 + + + 2 + 3 + 55704 + + + 3 + 7 + 44179 + + + 7 + 170 + 36496 + + + + + + + nodeName + kind + + + 12 + + + 1 + 2 + 533998 + + + + + + + kind + id + + + 12 + + + 791 + 792 + 1920 + + + 947 + 948 + 1920 + + + + + + + kind + nodeName + + + 12 + + + 91 + 92 + 1920 + + + 187 + 188 + 1920 + + + + + + + + + typeBounds + 4229725 + + + id + 4229725 + + + typeid + 2852471 + + + pos + 1920 + + + parentid + 4229725 + + + + + id + typeid + + + 12 + + + 1 + 2 + 4229725 + + + + + + + id + pos + + + 12 + + + 1 + 2 + 4229725 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 4229725 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 2091812 + + + 2 + 3 + 695349 + + + 3 + 52 + 65309 + + + + + + + typeid + pos + + + 12 + + + 1 + 2 + 2852471 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 2091812 + + + 2 + 3 + 695349 + + + 3 + 52 + 65309 + + + + + + + pos + id + + + 12 + + + 2202 + 2203 + 1920 + + + + + + + pos + typeid + + + 12 + + + 1485 + 1486 + 1920 + + + + + + + pos + parentid + + + 12 + + + 2202 + 2203 + 1920 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 4229725 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 4229725 + + + + + + + parentid + pos + + + 12 + + + 1 + 2 + 4229725 + + + + + + + + + typeArgs + 53854237 + + + argumentid + 1430551 + + + pos + 57 + + + parentid + 22244248 + + + + + argumentid + pos + + + 12 + + + 1 + 2 + 865848 + + + 2 + 3 + 470615 + + + 3 + 11 + 94087 + + + + + + + argumentid + parentid + + + 12 + + + 1 + 2 + 64071 + + + 2 + 3 + 433698 + + + 3 + 5 + 100595 + + + 5 + 6 + 35547 + + + 6 + 7 + 201249 + + + 7 + 11 + 39437 + + + 11 + 12 + 218178 + + + 12 + 15 + 111421 + + + 15 + 29 + 108138 + + + 29 + 341 + 107450 + + + 341 + 757580 + 10762 + + + + + + + pos + argumentid + + + 12 + + + 4 + 5 + 5 + + + 597 + 598 + 5 + + + 887 + 888 + 5 + + + 1129 + 1130 + 5 + + + 1758 + 1759 + 5 + + + 3885 + 3886 + 5 + + + 4027 + 4028 + 5 + + + 51686 + 51687 + 5 + + + 142042 + 142043 + 5 + + + 161580 + 161581 + 5 + + + + + + + pos + parentid + + + 12 + + + 4 + 5 + 5 + + + 831 + 832 + 5 + + + 3895 + 3896 + 5 + + + 8694 + 8695 + 5 + + + 19012 + 19013 + 5 + + + 85622 + 85623 + 5 + + + 103257 + 103258 + 5 + + + 1447294 + 1447295 + 5 + + + 3800219 + 3800220 + 5 + + + 3848466 + 3848467 + 5 + + + + + + + parentid + argumentid + + + 12 + + + 1 + 2 + 296162 + + + 2 + 3 + 13666793 + + + 3 + 4 + 7750153 + + + 4 + 11 + 531138 + + + + + + + parentid + pos + + + 12 + + + 1 + 2 + 278869 + + + 2 + 3 + 13599976 + + + 3 + 4 + 7768574 + + + 4 + 11 + 596828 + + + + + + + + + isParameterized + 27045654 + + + memberid + 27045654 + + + + + + isRaw + 731846 + + + memberid + 731846 + + + + + + erasure + 27777500 + + + memberid + 27777500 + + + erasureid + 954665 + + + + + memberid + erasureid + + + 12 + + + 1 + 2 + 27777500 + + + + + + + erasureid + memberid + + + 12 + + + 1 + 2 + 142143 + + + 2 + 3 + 138301 + + + 3 + 4 + 86438 + + + 4 + 5 + 57625 + + + 5 + 6 + 65309 + + + 6 + 8 + 69150 + + + 8 + 10 + 61467 + + + 10 + 15 + 72992 + + + 15 + 22 + 76834 + + + 22 + 44 + 74913 + + + 46 + 124 + 72992 + + + 169 + 1564 + 36496 + + + + + + + + + isAnonymClass + 174213 + + + classid + 174213 + + + parent + 174213 + + + + + classid + parent + + + 12 + + + 1 + 2 + 174213 + + + + + + + parent + classid + + + 12 + + + 1 + 2 + 174213 + + + + + + + + + isLocalClassOrInterface + 3841 + + + typeid + 3841 + + + parent + 3841 + + + + + typeid + parent + + + 12 + + + 1 + 2 + 3841 + + + + + + + parent + typeid + + + 12 + + + 1 + 2 + 3841 + + + + + + + + + isDefConstr + 139383 + + + constructorid + 139383 + + + + + + lambdaKind + 167982 + + + exprId + 167982 + + + bodyKind + 13 + + + + + exprId + bodyKind + + + 12 + + + 1 + 2 + 167982 + + + + + + + bodyKind + exprId + + + 12 + + + 12267 + 12268 + 13 + + + + + + + + + arrays + 1375332 + + + id + 1375332 + + + nodeName + 831730 + + + elementtypeid + 1365728 + + + dimension + 3841 + + + componenttypeid + 1375332 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 1375332 + + + + + + + id + elementtypeid + + + 12 + + + 1 + 2 + 1375332 + + + + + + + id + dimension + + + 12 + + + 1 + 2 + 1375332 + + + + + + + id + componenttypeid + + + 12 + + + 1 + 2 + 1375332 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 664616 + + + 2 + 3 + 140222 + + + 3 + 87 + 26891 + + + + + + + nodeName + elementtypeid + + + 12 + + + 1 + 2 + 664616 + + + 2 + 3 + 140222 + + + 3 + 87 + 26891 + + + + + + + nodeName + dimension + + + 12 + + + 1 + 2 + 831730 + + + + + + + nodeName + componenttypeid + + + 12 + + + 1 + 2 + 664616 + + + 2 + 3 + 140222 + + + 3 + 87 + 26891 + + + + + + + elementtypeid + id + + + 12 + + + 1 + 2 + 1356124 + + + 2 + 3 + 9604 + + + + + + + elementtypeid + nodeName + + + 12 + + + 1 + 2 + 1356124 + + + 2 + 3 + 9604 + + + + + + + elementtypeid + dimension + + + 12 + + + 1 + 2 + 1356124 + + + 2 + 3 + 9604 + + + + + + + elementtypeid + componenttypeid + + + 12 + + + 1 + 2 + 1356124 + + + 2 + 3 + 9604 + + + + + + + dimension + id + + + 12 + + + 5 + 6 + 1920 + + + 711 + 712 + 1920 + + + + + + + dimension + nodeName + + + 12 + + + 5 + 6 + 1920 + + + 428 + 429 + 1920 + + + + + + + dimension + elementtypeid + + + 12 + + + 5 + 6 + 1920 + + + 711 + 712 + 1920 + + + + + + + dimension + componenttypeid + + + 12 + + + 5 + 6 + 1920 + + + 711 + 712 + 1920 + + + + + + + componenttypeid + id + + + 12 + + + 1 + 2 + 1375332 + + + + + + + componenttypeid + nodeName + + + 12 + + + 1 + 2 + 1375332 + + + + + + + componenttypeid + elementtypeid + + + 12 + + + 1 + 2 + 1375332 + + + + + + + componenttypeid + dimension + + + 12 + + + 1 + 2 + 1375332 + + + + + + + + + enclInReftype + 4051085 + + + child + 4051085 + + + parent + 1125621 + + + + + child + parent + + + 12 + + + 1 + 2 + 4051085 + + + + + + + parent + child + + + 12 + + + 1 + 2 + 666537 + + + 2 + 3 + 176718 + + + 3 + 4 + 86438 + + + 4 + 6 + 82596 + + + 6 + 17 + 84517 + + + 17 + 265 + 28812 + + + + + + + + + extendsReftype + 34389087 + + + id1 + 33104034 + + + id2 + 13251986 + + + + + id1 + id2 + + + 12 + + + 1 + 2 + 32118635 + + + 2 + 10 + 985399 + + + + + + + id2 + id1 + + + 12 + + + 1 + 2 + 12030322 + + + 2 + 5 + 1023816 + + + 5 + 8715 + 197848 + + + + + + + + + implInterface + 14423708 + + + id1 + 8255839 + + + id2 + 4487119 + + + + + id1 + id2 + + + 12 + + + 1 + 2 + 4223962 + + + 2 + 3 + 2829421 + + + 3 + 4 + 276603 + + + 4 + 5 + 920090 + + + 5 + 7 + 5762 + + + + + + + id2 + id1 + + + 12 + + + 1 + 2 + 4003064 + + + 2 + 4 + 366883 + + + 4 + 2275 + 117172 + + + + + + + + + permits + 129 + + + id1 + 31 + + + id2 + 129 + + + + + id1 + id2 + + + 12 + + + 1 + 2 + 2 + + + 2 + 3 + 8 + + + 3 + 4 + 6 + + + 4 + 5 + 2 + + + 5 + 6 + 2 + + + 6 + 8 + 2 + + + 8 + 9 + 2 + + + 9 + 11 + 2 + + + + + + + id2 + id1 + + + 12 + + + 1 + 2 + 129 + + + + + + + + + hasModifier + 270713939 + + + id1 + 180180147 + + + id2 + 26891 + + + + + id1 + id2 + + + 12 + + + 1 + 2 + 90230296 + + + 2 + 3 + 89365911 + + + 3 + 4 + 583940 + + + + + + + id2 + id1 + + + 12 + + + 4 + 5 + 1920 + + + 14 + 15 + 1920 + + + 20 + 21 + 1920 + + + 21 + 22 + 1920 + + + 34 + 35 + 1920 + + + 50 + 51 + 1920 + + + 109 + 110 + 1920 + + + 219 + 220 + 1920 + + + 3864 + 3865 + 1920 + + + 7193 + 7194 + 1920 + + + 9195 + 9196 + 1920 + + + 14706 + 14707 + 1920 + + + 18810 + 18811 + 1920 + + + 86695 + 86696 + 1920 + + + + + + + + + imports + 368550 + + + id + 368550 + + + holder + 58078 + + + name + 8794 + + + kind + 663 + + + + + id + holder + + + 12 + + + 1 + 2 + 368550 + + + + + + + id + name + + + 12 + + + 1 + 2 + 368550 + + + + + + + id + kind + + + 12 + + + 1 + 2 + 368550 + + + + + + + holder + id + + + 12 + + + 1 + 2 + 28375 + + + 2 + 3 + 9292 + + + 3 + 4 + 5475 + + + 4 + 6 + 4646 + + + 6 + 15 + 4480 + + + 15 + 54 + 4480 + + + 64 + 98 + 1327 + + + + + + + holder + name + + + 12 + + + 1 + 2 + 54593 + + + 2 + 7 + 3484 + + + + + + + holder + kind + + + 12 + + + 1 + 2 + 55091 + + + 2 + 3 + 2986 + + + + + + + name + id + + + 12 + + + 1 + 2 + 4148 + + + 2 + 3 + 1825 + + + 3 + 4 + 829 + + + 4 + 7 + 663 + + + 7 + 26 + 663 + + + 30 + 1962 + 663 + + + + + + + name + holder + + + 12 + + + 1 + 2 + 7301 + + + 2 + 3 + 1161 + + + 3 + 337 + 331 + + + + + + + name + kind + + + 12 + + + 1 + 2 + 8628 + + + 3 + 4 + 165 + + + + + + + kind + id + + + 12 + + + 1 + 2 + 165 + + + 6 + 7 + 165 + + + 260 + 261 + 165 + + + 1954 + 1955 + 165 + + + + + + + kind + holder + + + 12 + + + 1 + 2 + 165 + + + 3 + 4 + 165 + + + 31 + 32 + 165 + + + 333 + 334 + 165 + + + + + + + kind + name + + + 12 + + + 1 + 2 + 497 + + + 52 + 53 + 165 + + + + + + + + + stmts + 2441387 + + + id + 2441387 + + + kind + 9674 + + + parent + 1353860 + + + idx + 15934 + + + bodydecl + 367630 + + + + + id + kind + + + 12 + + + 1 + 2 + 2441387 + + + + + + + id + parent + + + 12 + + + 1 + 2 + 2441387 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 2441387 + + + + + + + id + bodydecl + + + 12 + + + 1 + 2 + 2441387 + + + + + + + kind + id + + + 12 + + + 1 + 2 + 1707 + + + 6 + 7 + 569 + + + 7 + 8 + 569 + + + 17 + 18 + 569 + + + 20 + 21 + 569 + + + 23 + 24 + 569 + + + 33 + 34 + 569 + + + 83 + 84 + 569 + + + 91 + 92 + 569 + + + 97 + 98 + 569 + + + 265 + 266 + 569 + + + 312 + 313 + 569 + + + 560 + 561 + 569 + + + 1243 + 1244 + 569 + + + 1530 + 1531 + 569 + + + + + + + kind + parent + + + 12 + + + 1 + 2 + 2276 + + + 7 + 8 + 569 + + + 12 + 13 + 569 + + + 17 + 18 + 569 + + + 21 + 22 + 569 + + + 33 + 34 + 569 + + + 71 + 72 + 569 + + + 81 + 82 + 569 + + + 91 + 92 + 569 + + + 246 + 247 + 569 + + + 265 + 266 + 569 + + + 271 + 272 + 569 + + + 716 + 717 + 569 + + + 1192 + 1193 + 569 + + + + + + + kind + idx + + + 12 + + + 1 + 2 + 2276 + + + 3 + 4 + 569 + + + 4 + 5 + 569 + + + 6 + 7 + 1138 + + + 7 + 8 + 569 + + + 8 + 9 + 1138 + + + 10 + 11 + 1138 + + + 13 + 14 + 569 + + + 17 + 18 + 569 + + + 21 + 22 + 569 + + + 26 + 27 + 569 + + + + + + + kind + bodydecl + + + 12 + + + 1 + 2 + 2276 + + + 7 + 8 + 1138 + + + 17 + 18 + 569 + + + 20 + 21 + 569 + + + 21 + 22 + 569 + + + 53 + 54 + 569 + + + 54 + 55 + 569 + + + 91 + 92 + 569 + + + 119 + 120 + 569 + + + 179 + 180 + 569 + + + 211 + 212 + 569 + + + 431 + 432 + 569 + + + 646 + 647 + 569 + + + + + + + parent + id + + + 12 + + + 1 + 2 + 989074 + + + 2 + 3 + 191782 + + + 3 + 6 + 107557 + + + 6 + 27 + 65445 + + + + + + + parent + kind + + + 12 + + + 1 + 2 + 1081267 + + + 2 + 3 + 194058 + + + 3 + 6 + 78534 + + + + + + + parent + idx + + + 12 + + + 1 + 2 + 989074 + + + 2 + 3 + 191782 + + + 3 + 6 + 107557 + + + 6 + 27 + 65445 + + + + + + + parent + bodydecl + + + 12 + + + 1 + 2 + 1353860 + + + + + + + idx + id + + + 12 + + + 3 + 5 + 1138 + + + 5 + 6 + 1138 + + + 6 + 7 + 2276 + + + 10 + 15 + 1138 + + + 15 + 16 + 1138 + + + 17 + 20 + 1138 + + + 24 + 32 + 1138 + + + 40 + 43 + 1138 + + + 55 + 72 + 1138 + + + 83 + 94 + 1138 + + + 115 + 160 + 1138 + + + 204 + 386 + 1138 + + + 939 + 1919 + 1138 + + + + + + + idx + kind + + + 12 + + + 1 + 2 + 2276 + + + 2 + 3 + 3983 + + + 3 + 5 + 1138 + + + 5 + 6 + 2276 + + + 6 + 7 + 2276 + + + 7 + 9 + 1138 + + + 9 + 10 + 1138 + + + 12 + 14 + 1138 + + + 16 + 17 + 569 + + + + + + + idx + parent + + + 12 + + + 3 + 5 + 1138 + + + 5 + 6 + 1138 + + + 6 + 7 + 2276 + + + 10 + 15 + 1138 + + + 15 + 16 + 1138 + + + 17 + 20 + 1138 + + + 24 + 32 + 1138 + + + 40 + 43 + 1138 + + + 55 + 72 + 1138 + + + 83 + 94 + 1138 + + + 115 + 160 + 1138 + + + 204 + 386 + 1138 + + + 939 + 1919 + 1138 + + + + + + + idx + bodydecl + + + 12 + + + 3 + 5 + 1138 + + + 5 + 6 + 1138 + + + 6 + 7 + 2276 + + + 10 + 15 + 1138 + + + 15 + 16 + 1138 + + + 17 + 20 + 1138 + + + 24 + 32 + 1138 + + + 40 + 43 + 1138 + + + 54 + 56 + 1138 + + + 68 + 87 + 1138 + + + 104 + 138 + 1138 + + + 167 + 226 + 1138 + + + 337 + 647 + 1138 + + + + + + + bodydecl + id + + + 12 + + + 1 + 2 + 17641 + + + 2 + 3 + 157637 + + + 3 + 4 + 38128 + + + 4 + 5 + 33576 + + + 5 + 7 + 24470 + + + 7 + 10 + 29023 + + + 10 + 16 + 30730 + + + 16 + 34 + 27885 + + + 34 + 131 + 8536 + + + + + + + bodydecl + kind + + + 12 + + + 1 + 2 + 17641 + + + 2 + 3 + 193489 + + + 3 + 4 + 77965 + + + 4 + 5 + 29592 + + + 5 + 7 + 33007 + + + 7 + 11 + 15934 + + + + + + + bodydecl + parent + + + 12 + + + 1 + 2 + 17641 + + + 2 + 3 + 261780 + + + 4 + 5 + 33576 + + + 5 + 10 + 31299 + + + 10 + 88 + 23332 + + + + + + + bodydecl + idx + + + 12 + + + 1 + 2 + 175279 + + + 2 + 3 + 63737 + + + 3 + 4 + 27885 + + + 4 + 5 + 18210 + + + 5 + 7 + 30161 + + + 7 + 11 + 29592 + + + 11 + 28 + 22763 + + + + + + + + + exprs + 7410663 + + + id + 7410663 + + + kind + 1618 + + + typeid + 115976 + + + parent + 5075638 + + + idx + 1426 + + + + + id + kind + + + 12 + + + 1 + 2 + 7410663 + + + + + + + id + typeid + + + 12 + + + 1 + 2 + 7410663 + + + + + + + id + parent + + + 12 + + + 1 + 2 + 7410663 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 7410663 + + + + + + + kind + id + + + 12 + + + 1 + 3 + 137 + + + 3 + 9 + 137 + + + 13 + 31 + 137 + + + 31 + 76 + 137 + + + 85 + 161 + 109 + + + 186 + 307 + 137 + + + 378 + 492 + 137 + + + 494 + 659 + 137 + + + 708 + 1063 + 137 + + + 1114 + 2997 + 137 + + + 3119 + 9319 + 137 + + + 10083 + 75330 + 137 + + + + + + + kind + typeid + + + 12 + + + 1 + 2 + 768 + + + 2 + 3 + 246 + + + 3 + 6 + 137 + + + 18 + 48 + 137 + + + 48 + 152 + 137 + + + 246 + 1578 + 137 + + + 2399 + 2509 + 54 + + + + + + + kind + parent + + + 12 + + + 1 + 3 + 137 + + + 3 + 9 + 137 + + + 13 + 31 + 137 + + + 31 + 76 + 137 + + + 81 + 177 + 137 + + + 183 + 357 + 137 + + + 378 + 482 + 137 + + + 572 + 708 + 137 + + + 708 + 1060 + 137 + + + 1102 + 3043 + 137 + + + 5490 + 10002 + 137 + + + 16929 + 60299 + 109 + + + + + + + kind + idx + + + 12 + + + 1 + 2 + 246 + + + 2 + 3 + 521 + + + 3 + 4 + 246 + + + 4 + 6 + 137 + + + 6 + 8 + 137 + + + 8 + 11 + 137 + + + 12 + 27 + 137 + + + 46 + 49 + 54 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 48881 + + + 2 + 3 + 13002 + + + 3 + 6 + 10697 + + + 6 + 10 + 9628 + + + 10 + 17 + 9271 + + + 17 + 32 + 8722 + + + 32 + 89 + 8750 + + + 89 + 52561 + 7022 + + + + + + + typeid + kind + + + 12 + + + 1 + 2 + 57851 + + + 2 + 3 + 18543 + + + 3 + 4 + 8914 + + + 4 + 5 + 14455 + + + 5 + 6 + 9737 + + + 6 + 32 + 6473 + + + + + + + typeid + parent + + + 12 + + + 1 + 2 + 49045 + + + 2 + 3 + 13413 + + + 3 + 5 + 8668 + + + 5 + 8 + 8530 + + + 8 + 13 + 9244 + + + 13 + 24 + 8750 + + + 24 + 57 + 8805 + + + 57 + 851 + 8722 + + + 890 + 37212 + 795 + + + + + + + typeid + idx + + + 12 + + + 1 + 2 + 58673 + + + 2 + 3 + 18378 + + + 3 + 4 + 14730 + + + 4 + 5 + 19119 + + + 5 + 50 + 5074 + + + + + + + parent + id + + + 12 + + + 1 + 2 + 3222211 + + + 2 + 3 + 1522614 + + + 3 + 48 + 330812 + + + + + + + parent + kind + + + 12 + + + 1 + 2 + 3525291 + + + 2 + 3 + 1385461 + + + 3 + 8 + 164884 + + + + + + + parent + typeid + + + 12 + + + 1 + 2 + 4085559 + + + 2 + 3 + 832078 + + + 3 + 10 + 157999 + + + + + + + parent + idx + + + 12 + + + 1 + 2 + 3222211 + + + 2 + 3 + 1522614 + + + 3 + 48 + 330812 + + + + + + + idx + id + + + 12 + + + 1 + 2 + 82 + + + 2 + 3 + 466 + + + 3 + 4 + 82 + + + 4 + 5 + 54 + + + 5 + 6 + 82 + + + 6 + 8 + 109 + + + 8 + 19 + 109 + + + 24 + 37 + 109 + + + 75 + 343 + 109 + + + 536 + 6117 + 109 + + + 7863 + 137171 + 109 + + + + + + + idx + kind + + + 12 + + + 1 + 2 + 164 + + + 2 + 3 + 521 + + + 3 + 4 + 27 + + + 4 + 5 + 246 + + + 6 + 7 + 54 + + + 7 + 8 + 109 + + + 8 + 13 + 109 + + + 13 + 26 + 109 + + + 27 + 59 + 82 + + + + + + + idx + typeid + + + 12 + + + 1 + 2 + 82 + + + 2 + 3 + 521 + + + 3 + 4 + 54 + + + 4 + 5 + 246 + + + 7 + 12 + 109 + + + 12 + 20 + 109 + + + 29 + 66 + 109 + + + 80 + 1212 + 109 + + + 1956 + 3022 + 82 + + + + + + + idx + parent + + + 12 + + + 1 + 2 + 82 + + + 2 + 3 + 466 + + + 3 + 4 + 82 + + + 4 + 5 + 54 + + + 5 + 6 + 82 + + + 6 + 8 + 109 + + + 8 + 19 + 109 + + + 24 + 37 + 109 + + + 75 + 343 + 109 + + + 536 + 6117 + 109 + + + 7863 + 137171 + 109 + + + + + + + + + exprsKotlinType + 7410663 + + + id + 7410663 + + + kttypeid + 10930 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 7410663 + + + + + + + kttypeid + id + + + 12 + + + 1 + 2 + 8197 + + + 2 + 3 + 1821 + + + 8123 + 8124 + 910 + + + + + + + + + callableEnclosingExpr + 7299071 + + + id + 7299071 + + + callable_id + 19877 + + + + + id + callable_id + + + 12 + + + 1 + 2 + 7299071 + + + + + + + callable_id + id + + + 12 + + + 1 + 2 + 711 + + + 2 + 3 + 1691 + + + 3 + 5 + 1604 + + + 5 + 6 + 806 + + + 6 + 7 + 1955 + + + 7 + 9 + 1374 + + + 9 + 13 + 1825 + + + 13 + 18 + 1574 + + + 18 + 26 + 1530 + + + 26 + 42 + 1530 + + + 42 + 73 + 1504 + + + 73 + 177 + 1495 + + + 179 + 1146 + 1491 + + + 1148 + 37742 + 780 + + + + + + + + + statementEnclosingExpr + 7258714 + + + id + 7258714 + + + statement_id + 525778 + + + + + id + statement_id + + + 12 + + + 1 + 2 + 7258714 + + + + + + + statement_id + id + + + 12 + + + 1 + 3 + 29126 + + + 3 + 5 + 47077 + + + 5 + 7 + 48474 + + + 7 + 8 + 36042 + + + 8 + 9 + 38145 + + + 9 + 10 + 50447 + + + 10 + 11 + 29212 + + + 11 + 12 + 127049 + + + 12 + 35 + 35322 + + + 35 + 40 + 44623 + + + 40 + 81 + 40222 + + + 82 + 210 + 34 + + + + + + + + + isParenthesized + 94652 + + + id + 94652 + + + parentheses + 5 + + + + + id + parentheses + + + 12 + + + 1 + 2 + 94652 + + + + + + + parentheses + id + + + 12 + + + 58 + 59 + 2 + + + 34605 + 34606 + 2 + + + + + + + + + when_if + 74334 + + + id + 74334 + + + + + + when_branch_else + 76075 + + + id + 76075 + + + + + + callableBinding + 1832520 + + + callerid + 1832520 + + + callee + 264311 + + + + + callerid + callee + + + 12 + + + 1 + 2 + 1832520 + + + + + + + callee + callerid + + + 12 + + + 1 + 2 + 162993 + + + 2 + 3 + 33137 + + + 3 + 4 + 16271 + + + 4 + 7 + 22271 + + + 7 + 20 + 19902 + + + 20 + 46115 + 9734 + + + + + + + + + memberRefBinding + 23208 + + + id + 23208 + + + callable + 11197 + + + + + id + callable + + + 12 + + + 1 + 2 + 23208 + + + + + + + callable + id + + + 12 + + + 1 + 2 + 7862 + + + 2 + 3 + 2075 + + + 3 + 7 + 940 + + + 7 + 912 + 319 + + + + + + + + + propertyRefGetBinding + 8876 + + + id + 8876 + + + getter + 5366 + + + + + id + getter + + + 12 + + + 1 + 2 + 8876 + + + + + + + getter + id + + + 12 + + + 1 + 2 + 1951 + + + 2 + 3 + 3328 + + + 3 + 6 + 86 + + + + + + + + + propertyRefFieldBinding + 2 + + + id + 2 + + + field + 2 + + + + + id + field + + + 12 + + + 1 + 2 + 2 + + + + + + + field + id + + + 12 + + + 1 + 2 + 2 + + + + + + + + + propertyRefSetBinding + 2600 + + + id + 2600 + + + setter + 1300 + + + + + id + setter + + + 12 + + + 1 + 2 + 2600 + + + + + + + setter + id + + + 12 + + + 2 + 3 + 1300 + + + + + + + + + variableBinding + 2434277 + + + expr + 2434277 + + + variable + 572528 + + + + + expr + variable + + + 12 + + + 1 + 2 + 2434277 + + + + + + + variable + expr + + + 12 + + + 1 + 2 + 205791 + + + 2 + 3 + 120945 + + + 3 + 4 + 85022 + + + 4 + 5 + 45967 + + + 5 + 7 + 40059 + + + 7 + 14 + 43072 + + + 14 + 464 + 31669 + + + + + + + + + localvars + 385272 + + + id + 385272 + + + nodeName + 139995 + + + typeid + 49510 + + + parentid + 385272 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 385272 + + + + + + + id + typeid + + + 12 + + + 1 + 2 + 385272 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 385272 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 83655 + + + 2 + 3 + 26178 + + + 3 + 5 + 10243 + + + 5 + 9 + 11950 + + + 9 + 42 + 7967 + + + + + + + nodeName + typeid + + + 12 + + + 1 + 2 + 124630 + + + 2 + 3 + 13089 + + + 3 + 19 + 2276 + + + + + + + nodeName + parentid + + + 12 + + + 1 + 2 + 83655 + + + 2 + 3 + 26178 + + + 3 + 5 + 10243 + + + 5 + 9 + 11950 + + + 9 + 42 + 7967 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 16503 + + + 2 + 3 + 9105 + + + 3 + 5 + 2276 + + + 5 + 6 + 5121 + + + 6 + 7 + 2845 + + + 7 + 8 + 2845 + + + 8 + 12 + 4552 + + + 14 + 30 + 3983 + + + 51 + 76 + 2276 + + + + + + + typeid + nodeName + + + 12 + + + 1 + 2 + 23332 + + + 2 + 3 + 9105 + + + 3 + 4 + 6259 + + + 4 + 6 + 3983 + + + 6 + 14 + 3983 + + + 14 + 35 + 2845 + + + + + + + typeid + parentid + + + 12 + + + 1 + 2 + 16503 + + + 2 + 3 + 9105 + + + 3 + 5 + 2276 + + + 5 + 6 + 5121 + + + 6 + 7 + 2845 + + + 7 + 8 + 2845 + + + 8 + 12 + 4552 + + + 14 + 30 + 3983 + + + 51 + 76 + 2276 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 385272 + + + + + + + parentid + nodeName + + + 12 + + + 1 + 2 + 385272 + + + + + + + parentid + typeid + + + 12 + + + 1 + 2 + 385272 + + + + + + + + + localvarsKotlinType + 240107 + + + id + 240107 + + + kttypeid + 1920 + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 240107 + + + + + + + kttypeid + id + + + 12 + + + 125 + 126 + 1920 + + + + + + + + + namestrings + 4022436 + + + name + 23384 + + + value + 22166 + + + parent + 4022436 + + + + + name + value + + + 12 + + + 1 + 2 + 23384 + + + + + + + name + parent + + + 12 + + + 1 + 2 + 9604 + + + 2 + 3 + 3811 + + + 3 + 5 + 2150 + + + 5 + 9 + 1769 + + + 9 + 21 + 1795 + + + 21 + 69 + 1760 + + + 69 + 385 + 1756 + + + 390 + 412517 + 737 + + + + + + + value + name + + + 12 + + + 1 + 2 + 21559 + + + 2 + 12 + 607 + + + + + + + value + parent + + + 12 + + + 1 + 2 + 9118 + + + 2 + 3 + 3594 + + + 3 + 5 + 1912 + + + 5 + 9 + 1665 + + + 9 + 21 + 1691 + + + 21 + 67 + 1678 + + + 67 + 318 + 1665 + + + 320 + 413340 + 841 + + + + + + + parent + name + + + 12 + + + 1 + 2 + 4022436 + + + + + + + parent + value + + + 12 + + + 1 + 2 + 4022436 + + + + + + + + + modules + 7965 + + + id + 7965 + + + name + 7965 + + + + + id + name + + + 12 + + + 1 + 2 + 7965 + + + + + + + name + id + + + 12 + + + 1 + 2 + 7965 + + + + + + + + + isOpen + 1 + + + id + 1 + + + + + + cumodule + 247580 + + + fileId + 247580 + + + moduleId + 1161 + + + + + fileId + moduleId + + + 12 + + + 1 + 2 + 247580 + + + + + + + moduleId + fileId + + + 12 + + + 12 + 13 + 331 + + + 39 + 40 + 165 + + + 64 + 65 + 165 + + + 71 + 72 + 165 + + + 415 + 416 + 165 + + + 879 + 880 + 165 + + + + + + + + + directives + 50279 + + + id + 1161 + + + directive + 50279 + + + + + id + directive + + + 12 + + + 3 + 4 + 165 + + + 4 + 5 + 165 + + + 7 + 8 + 165 + + + 9 + 10 + 165 + + + 43 + 44 + 165 + + + 89 + 90 + 165 + + + 148 + 149 + 165 + + + + + + + directive + id + + + 12 + + + 1 + 2 + 50279 + + + + + + + + + requires + 1991 + + + id + 1991 + + + target + 995 + + + + + id + target + + + 12 + + + 1 + 2 + 1991 + + + + + + + target + id + + + 12 + + + 1 + 2 + 663 + + + 2 + 3 + 165 + + + 6 + 7 + 165 + + + + + + + + + isTransitive + 829 + + + id + 829 + + + + + + isStatic + 1 + + + id + 1 + + + + + + exports + 35013 + + + id + 35013 + + + target + 35013 + + + + + id + target + + + 12 + + + 1 + 2 + 35013 + + + + + + + target + id + + + 12 + + + 1 + 2 + 35013 + + + + + + + + + exportsTo + 28707 + + + id + 12279 + + + target + 7467 + + + + + id + target + + + 12 + + + 1 + 2 + 7301 + + + 2 + 3 + 1825 + + + 3 + 4 + 829 + + + 4 + 5 + 829 + + + 5 + 7 + 995 + + + 9 + 18 + 497 + + + + + + + target + id + + + 12 + + + 1 + 2 + 1991 + + + 2 + 3 + 1825 + + + 3 + 4 + 663 + + + 4 + 5 + 663 + + + 5 + 6 + 663 + + + 6 + 7 + 331 + + + 8 + 10 + 663 + + + 11 + 13 + 663 + + + + + + + + + opens + 165 + + + id + 165 + + + target + 165 + + + + + id + target + + + 12 + + + 1 + 2 + 165 + + + + + + + target + id + + + 12 + + + 1 + 2 + 165 + + + + + + + + + opensTo + 165 + + + id + 165 + + + target + 165 + + + + + id + target + + + 12 + + + 1 + 2 + 165 + + + + + + + target + id + + + 12 + + + 1 + 2 + 165 + + + + + + + + + uses + 10786 + + + id + 10786 + + + serviceInterface + 10786 + + + + + id + serviceInterface + + + 12 + + + 1 + 2 + 10786 + + + + + + + serviceInterface + id + + + 12 + + + 1 + 2 + 10786 + + + + + + + + + provides + 2323 + + + id + 2323 + + + serviceInterface + 2323 + + + + + id + serviceInterface + + + 12 + + + 1 + 2 + 2323 + + + + + + + serviceInterface + id + + + 12 + + + 1 + 2 + 2323 + + + + + + + + + providesWith + 5310 + + + id + 2323 + + + serviceImpl + 5310 + + + + + id + serviceImpl + + + 12 + + + 1 + 2 + 1327 + + + 2 + 3 + 165 + + + 4 + 5 + 663 + + + 6 + 7 + 165 + + + + + + + serviceImpl + id + + + 12 + + + 1 + 2 + 5310 + + + + + + + + + javadoc + 985091 + + + id + 985091 + + + + + + isNormalComment + 649898 + + + commentid + 649898 + + + + + + isEolComment + 610062 + + + commentid + 610062 + + + + + + hasJavadoc + 435352 + + + documentableid + 368199 + + + javadocid + 435352 + + + + + documentableid + javadocid + + + 12 + + + 1 + 2 + 320396 + + + 2 + 3 + 44957 + + + 3 + 27 + 2845 + + + + + + + javadocid + documentableid + + + 12 + + + 1 + 2 + 435352 + + + + + + + + + javadocTag + 335808 + + + id + 335808 + + + name + 577 + + + parentid + 114110 + + + idx + 4789 + + + + + id + name + + + 12 + + + 1 + 2 + 335808 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 335808 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 335808 + + + + + + + name + id + + + 12 + + + 34 + 35 + 82 + + + 69 + 70 + 82 + + + 203 + 204 + 82 + + + 405 + 406 + 82 + + + 608 + 609 + 82 + + + 968 + 969 + 82 + + + 1780 + 1781 + 82 + + + + + + + name + parentid + + + 12 + + + 34 + 35 + 82 + + + 69 + 70 + 82 + + + 158 + 159 + 82 + + + 404 + 405 + 82 + + + 608 + 609 + 82 + + + 668 + 669 + 82 + + + 969 + 970 + 82 + + + + + + + name + idx + + + 12 + + + 17 + 18 + 82 + + + 21 + 22 + 82 + + + 31 + 32 + 82 + + + 35 + 36 + 165 + + + 38 + 39 + 82 + + + 41 + 42 + 82 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 33192 + + + 2 + 3 + 24935 + + + 3 + 4 + 18660 + + + 4 + 5 + 13128 + + + 5 + 6 + 9990 + + + 6 + 7 + 7678 + + + 7 + 11 + 6522 + + + + + + + parentid + name + + + 12 + + + 1 + 2 + 39963 + + + 2 + 3 + 38642 + + + 3 + 4 + 21137 + + + 4 + 5 + 12220 + + + 5 + 6 + 2146 + + + + + + + parentid + idx + + + 12 + + + 1 + 2 + 33192 + + + 2 + 3 + 24935 + + + 3 + 4 + 18660 + + + 4 + 5 + 13128 + + + 5 + 6 + 9990 + + + 6 + 7 + 7678 + + + 7 + 11 + 6522 + + + + + + + idx + id + + + 12 + + + 1 + 2 + 1238 + + + 2 + 3 + 247 + + + 4 + 5 + 330 + + + 5 + 6 + 412 + + + 6 + 8 + 330 + + + 8 + 17 + 412 + + + 21 + 34 + 412 + + + 38 + 72 + 412 + + + 76 + 152 + 412 + + + 199 + 504 + 412 + + + 603 + 713 + 165 + + + + + + + idx + name + + + 12 + + + 1 + 2 + 1321 + + + 2 + 3 + 330 + + + 3 + 4 + 743 + + + 4 + 5 + 412 + + + 5 + 6 + 412 + + + 6 + 7 + 908 + + + 7 + 8 + 660 + + + + + + + idx + parentid + + + 12 + + + 1 + 2 + 1238 + + + 2 + 3 + 247 + + + 4 + 5 + 330 + + + 5 + 6 + 412 + + + 6 + 8 + 330 + + + 8 + 17 + 412 + + + 21 + 34 + 412 + + + 38 + 72 + 412 + + + 76 + 152 + 412 + + + 199 + 504 + 412 + + + 603 + 713 + 165 + + + + + + + + + javadocText + 2502848 + + + id + 2502848 + + + text + 1370363 + + + parentid + 1169475 + + + idx + 42112 + + + + + id + text + + + 12 + + + 1 + 2 + 2502848 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 2502848 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 2502848 + + + + + + + text + id + + + 12 + + + 1 + 2 + 1139314 + + + 2 + 3 + 149670 + + + 3 + 147 + 81379 + + + + + + + text + parentid + + + 12 + + + 1 + 2 + 1140452 + + + 2 + 3 + 149101 + + + 3 + 88 + 80810 + + + + + + + text + idx + + + 12 + + + 1 + 2 + 1346462 + + + 2 + 32 + 23901 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 870135 + + + 2 + 3 + 159344 + + + 3 + 12 + 83086 + + + 12 + 75 + 56908 + + + + + + + parentid + text + + + 12 + + + 1 + 2 + 870135 + + + 2 + 3 + 159344 + + + 3 + 12 + 84225 + + + 12 + 67 + 55770 + + + + + + + parentid + idx + + + 12 + + + 1 + 2 + 870135 + + + 2 + 3 + 159344 + + + 3 + 12 + 83086 + + + 12 + 75 + 56908 + + + + + + + idx + id + + + 12 + + + 2 + 3 + 21056 + + + 3 + 5 + 2276 + + + 5 + 7 + 3414 + + + 7 + 11 + 2276 + + + 12 + 16 + 3414 + + + 19 + 102 + 3414 + + + 108 + 154 + 3414 + + + 181 + 2056 + 2845 + + + + + + + idx + text + + + 12 + + + 1 + 2 + 569 + + + 2 + 3 + 20487 + + + 3 + 5 + 2845 + + + 5 + 7 + 3414 + + + 7 + 13 + 3414 + + + 13 + 23 + 3414 + + + 27 + 47 + 3414 + + + 47 + 123 + 3414 + + + 254 + 1252 + 1138 + + + + + + + idx + parentid + + + 12 + + + 2 + 3 + 21056 + + + 3 + 5 + 2276 + + + 5 + 7 + 3414 + + + 7 + 11 + 2276 + + + 12 + 16 + 3414 + + + 19 + 102 + 3414 + + + 108 + 154 + 3414 + + + 181 + 2056 + 2845 + + + + + + + + + xmlEncoding + 1129463 + + + id + 1129463 + + + encoding + 1920 + + + + + id + encoding + + + 12 + + + 1 + 2 + 1129463 + + + + + + + encoding + id + + + 12 + + + 588 + 589 + 1920 + + + + + + + + + xmlDTDs + 569 + + + id + 569 + + + root + 569 + + + publicId + 569 + + + systemId + 569 + + + fileid + 569 + + + + + id + root + + + 12 + + + 1 + 2 + 569 + + + + + + + id + publicId + + + 12 + + + 1 + 2 + 569 + + + + + + + id + systemId + + + 12 + + + 1 + 2 + 569 + + + + + + + id + fileid + + + 12 + + + 1 + 2 + 569 + + + + + + + root + id + + + 12 + + + 1 + 2 + 569 + + + + + + + root + publicId + + + 12 + + + 1 + 2 + 569 + + + + + + + root + systemId + + + 12 + + + 1 + 2 + 569 + + + + + + + root + fileid + + + 12 + + + 1 + 2 + 569 + + + + + + + publicId + id + + + 12 + + + 1 + 2 + 569 + + + + + + + publicId + root + + + 12 + + + 1 + 2 + 569 + + + + + + + publicId + systemId + + + 12 + + + 1 + 2 + 569 + + + + + + + publicId + fileid + + + 12 + + + 1 + 2 + 569 + + + + + + + systemId + id + + + 12 + + + 1 + 2 + 569 + + + + + + + systemId + root + + + 12 + + + 1 + 2 + 569 + + + + + + + systemId + publicId + + + 12 + + + 1 + 2 + 569 + + + + + + + systemId + fileid + + + 12 + + + 1 + 2 + 569 + + + + + + + fileid + id + + + 12 + + + 1 + 2 + 569 + + + + + + + fileid + root + + + 12 + + + 1 + 2 + 569 + + + + + + + fileid + publicId + + + 12 + + + 1 + 2 + 569 + + + + + + + fileid + systemId + + + 12 + + + 1 + 2 + 569 + + + + + + + + + xmlElements + 150282022 + + + id + 150282022 + + + name + 476372 + + + parentid + 3876287 + + + idx + 1703799 + + + fileid + 1129463 + + + + + id + name + + + 12 + + + 1 + 2 + 150282022 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 150282022 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 150282022 + + + + + + + id + fileid + + + 12 + + + 1 + 2 + 150282022 + + + + + + + name + id + + + 12 + + + 1 + 2 + 149826 + + + 2 + 3 + 57625 + + + 3 + 4 + 23050 + + + 4 + 6 + 42258 + + + 6 + 8 + 34575 + + + 8 + 9 + 17287 + + + 9 + 10 + 32654 + + + 10 + 18 + 40337 + + + 18 + 48 + 36496 + + + 52 + 250 + 36496 + + + 342 + 73380 + 5762 + + + + + + + name + parentid + + + 12 + + + 1 + 2 + 174797 + + + 2 + 3 + 65309 + + + 3 + 4 + 24971 + + + 4 + 5 + 21129 + + + 5 + 6 + 26891 + + + 6 + 8 + 40337 + + + 8 + 10 + 40337 + + + 10 + 21 + 38417 + + + 22 + 128 + 36496 + + + 130 + 229 + 7683 + + + + + + + name + idx + + + 12 + + + 1 + 2 + 263157 + + + 2 + 3 + 69150 + + + 3 + 4 + 34575 + + + 4 + 6 + 28812 + + + 6 + 9 + 28812 + + + 9 + 38 + 36496 + + + 45 + 888 + 15366 + + + + + + + name + fileid + + + 12 + + + 1 + 2 + 259315 + + + 2 + 3 + 51863 + + + 3 + 4 + 24971 + + + 4 + 5 + 19208 + + + 5 + 7 + 42258 + + + 7 + 16 + 36496 + + + 17 + 114 + 38417 + + + 118 + 131 + 3841 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 2358811 + + + 2 + 3 + 605069 + + + 3 + 4 + 251632 + + + 4 + 8 + 301574 + + + 8 + 777 + 316941 + + + 777 + 888 + 42258 + + + + + + + parentid + name + + + 12 + + + 1 + 2 + 3200146 + + + 2 + 3 + 411063 + + + 3 + 17 + 265078 + + + + + + + parentid + idx + + + 12 + + + 1 + 2 + 2358811 + + + 2 + 3 + 605069 + + + 3 + 4 + 251632 + + + 4 + 8 + 301574 + + + 8 + 777 + 316941 + + + 777 + 888 + 42258 + + + + + + + parentid + fileid + + + 12 + + + 1 + 2 + 3876287 + + + + + + + idx + id + + + 12 + + + 2 + 8 + 144064 + + + 9 + 76 + 136380 + + + 76 + 82 + 128697 + + + 82 + 89 + 122934 + + + 89 + 92 + 111409 + + + 92 + 95 + 134459 + + + 95 + 97 + 149826 + + + 97 + 98 + 211294 + + + 98 + 99 + 130618 + + + 99 + 104 + 155589 + + + 104 + 106 + 130618 + + + 106 + 159 + 128697 + + + 162 + 2019 + 19208 + + + + + + + idx + name + + + 12 + + + 1 + 2 + 1381095 + + + 2 + 5 + 126776 + + + 5 + 9 + 145985 + + + 9 + 150 + 49942 + + + + + + + idx + parentid + + + 12 + + + 2 + 8 + 144064 + + + 9 + 76 + 136380 + + + 76 + 82 + 128697 + + + 82 + 89 + 122934 + + + 89 + 92 + 111409 + + + 92 + 95 + 134459 + + + 95 + 97 + 149826 + + + 97 + 98 + 211294 + + + 98 + 99 + 130618 + + + 99 + 104 + 155589 + + + 104 + 106 + 130618 + + + 106 + 159 + 128697 + + + 162 + 2019 + 19208 + + + + + + + idx + fileid + + + 12 + + + 2 + 8 + 144064 + + + 9 + 76 + 136380 + + + 76 + 82 + 128697 + + + 82 + 89 + 122934 + + + 89 + 92 + 111409 + + + 92 + 95 + 134459 + + + 95 + 97 + 149826 + + + 97 + 98 + 211294 + + + 98 + 99 + 130618 + + + 99 + 104 + 155589 + + + 104 + 106 + 130618 + + + 106 + 139 + 128697 + + + 141 + 589 + 19208 + + + + + + + fileid + id + + + 12 + + + 1 + 2 + 82596 + + + 2 + 3 + 190164 + + + 3 + 4 + 249711 + + + 4 + 5 + 105647 + + + 5 + 7 + 84517 + + + 7 + 10 + 94121 + + + 10 + 31 + 88359 + + + 35 + 694 + 86438 + + + 738 + 776 + 28812 + + + 777 + 779 + 92201 + + + 788 + 889 + 26891 + + + + + + + fileid + name + + + 12 + + + 1 + 2 + 82596 + + + 2 + 3 + 562810 + + + 3 + 4 + 195927 + + + 4 + 5 + 92201 + + + 5 + 6 + 86438 + + + 6 + 9 + 92201 + + + 9 + 69 + 17287 + + + + + + + fileid + parentid + + + 12 + + + 1 + 2 + 82596 + + + 2 + 3 + 800997 + + + 3 + 4 + 80675 + + + 4 + 6 + 82596 + + + 6 + 165 + 82596 + + + + + + + fileid + idx + + + 12 + + + 1 + 2 + 286207 + + + 2 + 3 + 309257 + + + 3 + 4 + 124855 + + + 4 + 7 + 94121 + + + 7 + 17 + 94121 + + + 18 + 763 + 86438 + + + 764 + 777 + 92201 + + + 777 + 888 + 42258 + + + + + + + + + xmlAttrs + 182798274 + + + id + 182798274 + + + elementid + 149002731 + + + name + 722241 + + + value + 11548187 + + + idx + 44179 + + + fileid + 1127542 + + + + + id + elementid + + + 12 + + + 1 + 2 + 182798274 + + + + + + + id + name + + + 12 + + + 1 + 2 + 182798274 + + + + + + + id + value + + + 12 + + + 1 + 2 + 182798274 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 182798274 + + + + + + + id + fileid + + + 12 + + + 1 + 2 + 182798274 + + + + + + + elementid + id + + + 12 + + + 1 + 2 + 136351973 + + + 2 + 6 + 11204353 + + + 6 + 24 + 1446404 + + + + + + + elementid + name + + + 12 + + + 1 + 2 + 136351973 + + + 2 + 6 + 11223562 + + + 6 + 23 + 1427196 + + + + + + + elementid + value + + + 12 + + + 1 + 2 + 136426886 + + + 2 + 6 + 11279267 + + + 6 + 21 + 1296577 + + + + + + + elementid + idx + + + 12 + + + 1 + 2 + 136351973 + + + 2 + 6 + 11204353 + + + 6 + 24 + 1446404 + + + + + + + elementid + fileid + + + 12 + + + 1 + 2 + 149002731 + + + + + + + name + id + + + 12 + + + 1 + 2 + 149826 + + + 2 + 3 + 78755 + + + 3 + 4 + 44179 + + + 4 + 5 + 24971 + + + 5 + 6 + 42258 + + + 6 + 8 + 51863 + + + 8 + 11 + 59546 + + + 11 + 22 + 55704 + + + 23 + 38 + 57625 + + + 38 + 79 + 57625 + + + 81 + 168 + 55704 + + + 168 + 74700 + 44179 + + + + + + + name + elementid + + + 12 + + + 1 + 2 + 149826 + + + 2 + 3 + 78755 + + + 3 + 4 + 44179 + + + 4 + 5 + 24971 + + + 5 + 6 + 42258 + + + 6 + 8 + 51863 + + + 8 + 11 + 65309 + + + 11 + 25 + 61467 + + + 25 + 39 + 59546 + + + 43 + 91 + 57625 + + + 91 + 227 + 55704 + + + 227 + 74700 + 30733 + + + + + + + name + value + + + 12 + + + 1 + 2 + 303495 + + + 2 + 3 + 113330 + + + 3 + 4 + 48021 + + + 4 + 5 + 51863 + + + 5 + 9 + 59546 + + + 9 + 21 + 55704 + + + 22 + 64 + 59546 + + + 68 + 2100 + 30733 + + + + + + + name + idx + + + 12 + + + 1 + 2 + 284286 + + + 2 + 3 + 134459 + + + 3 + 4 + 69150 + + + 4 + 5 + 76834 + + + 5 + 7 + 46100 + + + 7 + 10 + 57625 + + + 10 + 21 + 53783 + + + + + + + name + fileid + + + 12 + + + 1 + 2 + 251632 + + + 2 + 3 + 74913 + + + 3 + 4 + 38417 + + + 4 + 5 + 34575 + + + 5 + 6 + 53783 + + + 6 + 9 + 59546 + + + 9 + 17 + 63388 + + + 17 + 34 + 55704 + + + 36 + 91 + 55704 + + + 91 + 223 + 34575 + + + + + + + value + id + + + 12 + + + 1 + 2 + 6308091 + + + 2 + 3 + 1707641 + + + 3 + 5 + 885514 + + + 5 + 31 + 870147 + + + 31 + 91 + 908564 + + + 91 + 1111 + 866306 + + + 3397 + 3398 + 1920 + + + + + + + value + elementid + + + 12 + + + 1 + 2 + 6434868 + + + 2 + 3 + 1626965 + + + 3 + 5 + 897039 + + + 5 + 33 + 910485 + + + 33 + 93 + 891277 + + + 93 + 3398 + 787551 + + + + + + + value + name + + + 12 + + + 1 + 2 + 10480191 + + + 2 + 4 + 929694 + + + 4 + 53 + 138301 + + + + + + + value + idx + + + 12 + + + 1 + 2 + 9563942 + + + 2 + 3 + 1396462 + + + 3 + 20 + 587781 + + + + + + + value + fileid + + + 12 + + + 1 + 2 + 7433713 + + + 2 + 3 + 1252398 + + + 3 + 10 + 897039 + + + 10 + 83 + 877831 + + + 83 + 99 + 881672 + + + 99 + 182 + 205531 + + + + + + + idx + id + + + 12 + + + 1 + 6 + 3841 + + + 12 + 14 + 3841 + + + 17 + 26 + 3841 + + + 39 + 56 + 3841 + + + 83 + 110 + 3841 + + + 153 + 232 + 3841 + + + 316 + 400 + 3841 + + + 468 + 545 + 3841 + + + 626 + 754 + 3841 + + + 951 + 1491 + 3841 + + + 4718 + 6587 + 3841 + + + 77571 + 77572 + 1920 + + + + + + + idx + elementid + + + 12 + + + 1 + 6 + 3841 + + + 12 + 14 + 3841 + + + 17 + 26 + 3841 + + + 39 + 56 + 3841 + + + 83 + 110 + 3841 + + + 153 + 232 + 3841 + + + 316 + 400 + 3841 + + + 468 + 545 + 3841 + + + 626 + 754 + 3841 + + + 951 + 1491 + 3841 + + + 4718 + 6587 + 3841 + + + 77571 + 77572 + 1920 + + + + + + + idx + name + + + 12 + + + 1 + 4 + 3841 + + + 7 + 10 + 3841 + + + 11 + 17 + 3841 + + + 18 + 23 + 3841 + + + 26 + 38 + 3841 + + + 39 + 49 + 3841 + + + 57 + 67 + 3841 + + + 72 + 79 + 3841 + + + 95 + 101 + 3841 + + + 105 + 106 + 3841 + + + 106 + 132 + 3841 + + + 140 + 141 + 1920 + + + + + + + idx + value + + + 12 + + + 1 + 5 + 3841 + + + 7 + 10 + 3841 + + + 11 + 18 + 3841 + + + 22 + 32 + 3841 + + + 46 + 63 + 3841 + + + 85 + 119 + 3841 + + + 142 + 185 + 3841 + + + 212 + 228 + 3841 + + + 253 + 275 + 3841 + + + 307 + 423 + 3841 + + + 580 + 1324 + 3841 + + + 3579 + 3580 + 1920 + + + + + + + idx + fileid + + + 12 + + + 1 + 6 + 3841 + + + 7 + 8 + 3841 + + + 10 + 19 + 3841 + + + 23 + 36 + 3841 + + + 45 + 59 + 3841 + + + 73 + 97 + 3841 + + + 115 + 131 + 3841 + + + 140 + 148 + 3841 + + + 168 + 181 + 3841 + + + 248 + 363 + 3841 + + + 473 + 530 + 3841 + + + 587 + 588 + 1920 + + + + + + + fileid + id + + + 12 + + + 1 + 3 + 84517 + + + 3 + 5 + 86438 + + + 5 + 6 + 51863 + + + 6 + 7 + 86438 + + + 7 + 8 + 72992 + + + 8 + 10 + 82596 + + + 10 + 15 + 92201 + + + 15 + 27 + 86438 + + + 27 + 41 + 86438 + + + 41 + 65 + 86438 + + + 65 + 157 + 92201 + + + 162 + 817 + 86438 + + + 818 + 832 + 94121 + + + 832 + 1187 + 38417 + + + + + + + fileid + elementid + + + 12 + + + 1 + 2 + 128697 + + + 2 + 3 + 265078 + + + 3 + 4 + 159431 + + + 4 + 5 + 109488 + + + 5 + 8 + 101805 + + + 8 + 14 + 86438 + + + 14 + 295 + 86438 + + + 330 + 775 + 71071 + + + 776 + 778 + 92201 + + + 787 + 888 + 26891 + + + + + + + fileid + name + + + 12 + + + 1 + 2 + 71071 + + + 2 + 3 + 92201 + + + 3 + 4 + 71071 + + + 4 + 5 + 94121 + + + 5 + 6 + 170956 + + + 6 + 7 + 161351 + + + 7 + 8 + 71071 + + + 8 + 12 + 86438 + + + 12 + 18 + 97963 + + + 18 + 24 + 96042 + + + 24 + 37 + 88359 + + + 37 + 55 + 26891 + + + + + + + fileid + value + + + 12 + + + 1 + 3 + 97963 + + + 3 + 4 + 55704 + + + 4 + 5 + 103726 + + + 5 + 6 + 124855 + + + 6 + 8 + 88359 + + + 8 + 12 + 99884 + + + 12 + 19 + 86438 + + + 19 + 27 + 97963 + + + 27 + 41 + 86438 + + + 42 + 170 + 86438 + + + 205 + 780 + 80675 + + + 781 + 783 + 92201 + + + 791 + 893 + 26891 + + + + + + + fileid + idx + + + 12 + + + 1 + 2 + 111409 + + + 2 + 3 + 107567 + + + 3 + 4 + 213215 + + + 4 + 5 + 218977 + + + 5 + 6 + 130618 + + + 6 + 10 + 96042 + + + 10 + 12 + 65309 + + + 12 + 15 + 97963 + + + 15 + 24 + 86438 + + + + + + + + + xmlNs + 1811367 + + + id + 11525 + + + prefixName + 13445 + + + URI + 11525 + + + fileid + 1054550 + + + + + id + prefixName + + + 12 + + + 1 + 2 + 9604 + + + 2 + 3 + 1920 + + + + + + + id + URI + + + 12 + + + 1 + 2 + 11525 + + + + + + + id + fileid + + + 12 + + + 2 + 3 + 1920 + + + 20 + 21 + 1920 + + + 88 + 89 + 1920 + + + 167 + 168 + 1920 + + + 213 + 214 + 1920 + + + 453 + 454 + 1920 + + + + + + + prefixName + id + + + 12 + + + 1 + 2 + 13445 + + + + + + + prefixName + URI + + + 12 + + + 1 + 2 + 13445 + + + + + + + prefixName + fileid + + + 12 + + + 1 + 2 + 1920 + + + 2 + 3 + 1920 + + + 20 + 21 + 1920 + + + 88 + 89 + 1920 + + + 166 + 167 + 1920 + + + 213 + 214 + 1920 + + + 453 + 454 + 1920 + + + + + + + URI + id + + + 12 + + + 1 + 2 + 11525 + + + + + + + URI + prefixName + + + 12 + + + 1 + 2 + 9604 + + + 2 + 3 + 1920 + + + + + + + URI + fileid + + + 12 + + + 2 + 3 + 1920 + + + 20 + 21 + 1920 + + + 88 + 89 + 1920 + + + 167 + 168 + 1920 + + + 213 + 214 + 1920 + + + 453 + 454 + 1920 + + + + + + + fileid + id + + + 12 + + + 1 + 2 + 470609 + + + 2 + 3 + 411063 + + + 3 + 4 + 172877 + + + + + + + fileid + prefixName + + + 12 + + + 1 + 2 + 470609 + + + 2 + 3 + 411063 + + + 3 + 4 + 172877 + + + + + + + fileid + URI + + + 12 + + + 1 + 2 + 470609 + + + 2 + 3 + 411063 + + + 3 + 4 + 172877 + + + + + + + + + xmlHasNs + 36540446 + + + elementId + 36540446 + + + nsId + 11525 + + + fileid + 1048787 + + + + + elementId + nsId + + + 12 + + + 1 + 2 + 36540446 + + + + + + + elementId + fileid + + + 12 + + + 1 + 2 + 36540446 + + + + + + + nsId + elementId + + + 12 + + + 13 + 14 + 1920 + + + 84 + 85 + 1920 + + + 2426 + 2427 + 1920 + + + 2733 + 2734 + 1920 + + + 3704 + 3705 + 1920 + + + 10063 + 10064 + 1920 + + + + + + + nsId + fileid + + + 12 + + + 2 + 3 + 1920 + + + 20 + 21 + 1920 + + + 86 + 87 + 1920 + + + 164 + 165 + 1920 + + + 209 + 210 + 1920 + + + 453 + 454 + 1920 + + + + + + + fileid + elementId + + + 12 + + + 1 + 3 + 63388 + + + 3 + 5 + 88359 + + + 5 + 6 + 48021 + + + 6 + 7 + 92201 + + + 7 + 8 + 69150 + + + 8 + 10 + 86438 + + + 10 + 15 + 92201 + + + 15 + 25 + 78755 + + + 25 + 36 + 80675 + + + 36 + 49 + 82596 + + + 49 + 54 + 21129 + + + 54 + 55 + 82596 + + + 55 + 81 + 80675 + + + 81 + 298 + 78755 + + + 298 + 833 + 3841 + + + + + + + fileid + nsId + + + 12 + + + 1 + 2 + 472530 + + + 2 + 3 + 407221 + + + 3 + 4 + 169035 + + + + + + + + + xmlComments + 151257816 + + + id + 151257816 + + + text + 2387624 + + + parentid + 1185168 + + + fileid + 1108333 + + + + + id + text + + + 12 + + + 1 + 2 + 151257816 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 151257816 + + + + + + + id + fileid + + + 12 + + + 1 + 2 + 151257816 + + + + + + + text + id + + + 12 + + + 1 + 2 + 328466 + + + 2 + 7 + 195927 + + + 7 + 32 + 197848 + + + 32 + 61 + 180560 + + + 61 + 76 + 180560 + + + 76 + 84 + 192085 + + + 84 + 90 + 176718 + + + 90 + 94 + 157510 + + + 94 + 95 + 84517 + + + 95 + 96 + 142143 + + + 96 + 98 + 197848 + + + 98 + 100 + 178639 + + + 100 + 460 + 174797 + + + + + + + text + parentid + + + 12 + + + 1 + 2 + 332308 + + + 2 + 6 + 190164 + + + 6 + 32 + 201689 + + + 32 + 61 + 182481 + + + 61 + 75 + 186323 + + + 75 + 84 + 209373 + + + 84 + 90 + 172877 + + + 90 + 94 + 169035 + + + 94 + 95 + 94121 + + + 95 + 96 + 145985 + + + 96 + 98 + 201689 + + + 98 + 100 + 190164 + + + 100 + 460 + 111409 + + + + + + + text + fileid + + + 12 + + + 1 + 2 + 347674 + + + 2 + 7 + 188243 + + + 7 + 32 + 188243 + + + 32 + 61 + 182481 + + + 61 + 75 + 186323 + + + 75 + 84 + 209373 + + + 84 + 90 + 172877 + + + 90 + 94 + 169035 + + + 94 + 95 + 94121 + + + 95 + 96 + 145985 + + + 96 + 98 + 201689 + + + 98 + 100 + 190164 + + + 100 + 460 + 111409 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 943140 + + + 2 + 724 + 90280 + + + 726 + 830 + 109488 + + + 831 + 941 + 42258 + + + + + + + parentid + text + + + 12 + + + 1 + 2 + 943140 + + + 2 + 697 + 90280 + + + 697 + 795 + 48021 + + + 795 + 827 + 90280 + + + 838 + 899 + 13445 + + + + + + + parentid + fileid + + + 12 + + + 1 + 2 + 1185168 + + + + + + + fileid + id + + + 12 + + + 1 + 2 + 847097 + + + 2 + 549 + 84517 + + + 579 + 829 + 57625 + + + 829 + 832 + 92201 + + + 834 + 941 + 26891 + + + + + + + fileid + text + + + 12 + + + 1 + 2 + 847097 + + + 2 + 536 + 84517 + + + 560 + 795 + 72992 + + + 795 + 812 + 84517 + + + 819 + 899 + 19208 + + + + + + + fileid + parentid + + + 12 + + + 1 + 2 + 1052629 + + + 2 + 6 + 55704 + + + + + + + + + xmlChars + 142938589 + + + id + 142938589 + + + text + 109773086 + + + parentid + 142938589 + + + idx + 1920 + + + isCDATA + 3841 + + + fileid + 249711 + + + + + id + text + + + 12 + + + 1 + 2 + 142938589 + + + + + + + id + parentid + + + 12 + + + 1 + 2 + 142938589 + + + + + + + id + idx + + + 12 + + + 1 + 2 + 142938589 + + + + + + + id + isCDATA + + + 12 + + + 1 + 2 + 142938589 + + + + + + + id + fileid + + + 12 + + + 1 + 2 + 142938589 + + + + + + + text + id + + + 12 + + + 1 + 2 + 93927944 + + + 2 + 3 + 9865517 + + + 3 + 128 + 5979625 + + + + + + + text + parentid + + + 12 + + + 1 + 2 + 93927944 + + + 2 + 3 + 9865517 + + + 3 + 128 + 5979625 + + + + + + + text + idx + + + 12 + + + 1 + 2 + 109773086 + + + + + + + text + isCDATA + + + 12 + + + 1 + 2 + 109773086 + + + + + + + text + fileid + + + 12 + + + 1 + 2 + 105030493 + + + 2 + 76 + 4742593 + + + + + + + parentid + id + + + 12 + + + 1 + 2 + 142938589 + + + + + + + parentid + text + + + 12 + + + 1 + 2 + 142938589 + + + + + + + parentid + idx + + + 12 + + + 1 + 2 + 142938589 + + + + + + + parentid + isCDATA + + + 12 + + + 1 + 2 + 142938589 + + + + + + + parentid + fileid + + + 12 + + + 1 + 2 + 142938589 + + + + + + + idx + id + + + 12 + + + 74414 + 74415 + 1920 + + + + + + + idx + text + + + 12 + + + 57148 + 57149 + 1920 + + + + + + + idx + parentid + + + 12 + + + 74414 + 74415 + 1920 + + + + + + + idx + isCDATA + + + 12 + + + 2 + 3 + 1920 + + + + + + + idx + fileid + + + 12 + + + 130 + 131 + 1920 + + + + + + + isCDATA + id + + + 12 + + + 518 + 519 + 1920 + + + 73896 + 73897 + 1920 + + + + + + + isCDATA + text + + + 12 + + + 492 + 493 + 1920 + + + 56656 + 56657 + 1920 + + + + + + + isCDATA + parentid + + + 12 + + + 518 + 519 + 1920 + + + 73896 + 73897 + 1920 + + + + + + + isCDATA + idx + + + 12 + + + 1 + 2 + 3841 + + + + + + + isCDATA + fileid + + + 12 + + + 98 + 99 + 1920 + + + 130 + 131 + 1920 + + + + + + + fileid + id + + + 12 + + + 1 + 2 + 21129 + + + 2 + 23 + 19208 + + + 24 + 243 + 19208 + + + 294 + 566 + 19208 + + + 610 + 686 + 19208 + + + 691 + 764 + 19208 + + + 765 + 775 + 19208 + + + 775 + 776 + 5762 + + + 776 + 777 + 69150 + + + 777 + 803 + 19208 + + + 807 + 888 + 19208 + + + + + + + fileid + text + + + 12 + + + 1 + 2 + 21129 + + + 2 + 21 + 19208 + + + 22 + 188 + 19208 + + + 208 + 492 + 19208 + + + 525 + 589 + 19208 + + + 590 + 638 + 19208 + + + 639 + 651 + 19208 + + + 652 + 656 + 17287 + + + 656 + 659 + 23050 + + + 659 + 663 + 21129 + + + 663 + 667 + 19208 + + + 667 + 701 + 19208 + + + 702 + 744 + 13445 + + + + + + + fileid + parentid + + + 12 + + + 1 + 2 + 21129 + + + 2 + 23 + 19208 + + + 24 + 243 + 19208 + + + 294 + 566 + 19208 + + + 610 + 686 + 19208 + + + 691 + 764 + 19208 + + + 765 + 775 + 19208 + + + 775 + 776 + 5762 + + + 776 + 777 + 69150 + + + 777 + 803 + 19208 + + + 807 + 888 + 19208 + + + + + + + fileid + idx + + + 12 + + + 1 + 2 + 249711 + + + + + + + fileid + isCDATA + + + 12 + + + 1 + 2 + 61467 + + + 2 + 3 + 188243 + + + + + + + + + xmllocations + 630217533 + + + xmlElement + 628417691 + + + location + 590551854 + + + + + xmlElement + location + + + 12 + + + 1 + 2 + 628406166 + + + 2 + 454 + 11525 + + + + + + + location + xmlElement + + + 12 + + + 1 + 2 + 577165407 + + + 2 + 25 + 13386446 + + + + + + + + + configs + 1 + + + id + 1 + + + + + + configNames + 1 + + + id + 1 + + + config + 1 + + + name + 1 + + + + + id + config + + + 12 + + + 1 + 2 + 1 + + + + + + + id + name + + + 12 + + + 1 + 2 + 1 + + + + + + + config + id + + + 12 + + + + + + config + name + + + 12 + + + + + + name + id + + + 12 + + + + + + name + config + + + 12 + + + + + + + + configValues + 1 + + + id + 1 + + + config + 1 + + + value + 1 + + + + + id + config + + + 12 + + + 1 + 2 + 1 + + + + + + + id + value + + + 12 + + + 1 + 2 + 1 + + + + + + + config + id + + + 12 + + + + + + config + value + + + 12 + + + + + + value + id + + + 12 + + + + + + value + config + + + 12 + + + + + + + + configLocations + 1 + + + locatable + 1 + + + location + 1 + + + + + locatable + location + + + 12 + + + + + + location + locatable + + + 12 + + + + + + + + ktComments + 188243 + + + id + 188243 + + + kind + 5762 + + + text + 136380 + + + + + id + kind + + + 12 + + + 1 + 2 + 188243 + + + + + + + id + text + + + 12 + + + 1 + 2 + 188243 + + + + + + + kind + id + + + 12 + + + 16 + 17 + 1920 + + + 22 + 23 + 1920 + + + 60 + 61 + 1920 + + + + + + + kind + text + + + 12 + + + 1 + 2 + 1920 + + + 16 + 17 + 1920 + + + 54 + 55 + 1920 + + + + + + + text + id + + + 12 + + + 1 + 2 + 130618 + + + 4 + 23 + 5762 + + + + + + + text + kind + + + 12 + + + 1 + 2 + 136380 + + + + + + + + + ktCommentSections + 52611 + + + id + 52611 + + + comment + 48161 + + + content + 44765 + + + + + id + comment + + + 12 + + + 1 + 2 + 52611 + + + + + + + id + content + + + 12 + + + 1 + 2 + 52611 + + + + + + + comment + id + + + 12 + + + 1 + 2 + 46367 + + + 2 + 18 + 1793 + + + + + + + comment + content + + + 12 + + + 1 + 2 + 46367 + + + 2 + 18 + 1793 + + + + + + + content + id + + + 12 + + + 1 + 2 + 39616 + + + 2 + 3 + 4313 + + + 3 + 63 + 835 + + + + + + + content + comment + + + 12 + + + 1 + 2 + 39712 + + + 2 + 3 + 4231 + + + 3 + 56 + 821 + + + + + + + + + ktCommentSectionNames + 4450 + + + id + 4450 + + + name + 13 + + + + + id + name + + + 12 + + + 1 + 2 + 4450 + + + + + + + name + id + + + 12 + + + 325 + 326 + 13 + + + + + + + + + ktCommentSectionSubjectNames + 4450 + + + id + 4450 + + + subjectname + 2916 + + + + + id + subjectname + + + 12 + + + 1 + 2 + 4450 + + + + + + + subjectname + id + + + 12 + + + 1 + 2 + 2218 + + + 2 + 3 + 438 + + + 3 + 9 + 219 + + + 10 + 16 + 41 + + + + + + + + + ktCommentOwners + 75329 + + + id + 47914 + + + owner + 73508 + + + + + id + owner + + + 12 + + + 1 + 2 + 30838 + + + 2 + 3 + 10872 + + + 3 + 4 + 4025 + + + 4 + 6 + 2177 + + + + + + + owner + id + + + 12 + + + 1 + 2 + 71701 + + + 2 + 4 + 1807 + + + + + + + + + ktExtensionFunctions + 1206297 + + + id + 1206297 + + + typeid + 97963 + + + kttypeid + 1920 + + + + + id + typeid + + + 12 + + + 1 + 2 + 1206297 + + + + + + + id + kttypeid + + + 12 + + + 1 + 2 + 1206297 + + + + + + + typeid + id + + + 12 + + + 1 + 2 + 55704 + + + 2 + 3 + 5762 + + + 3 + 4 + 3841 + + + 5 + 6 + 13445 + + + 7 + 16 + 7683 + + + 20 + 87 + 7683 + + + 109 + 227 + 3841 + + + + + + + typeid + kttypeid + + + 12 + + + 1 + 2 + 97963 + + + + + + + kttypeid + id + + + 12 + + + 628 + 629 + 1920 + + + + + + + kttypeid + typeid + + + 12 + + + 51 + 52 + 1920 + + + + + + + + + ktProperties + 21895839 + + + id + 21895839 + + + nodeName + 13542035 + + + + + id + nodeName + + + 12 + + + 1 + 2 + 21895839 + + + + + + + nodeName + id + + + 12 + + + 1 + 2 + 11824790 + + + 2 + 4 + 1142909 + + + 4 + 352 + 574335 + + + + + + + + + ktPropertyGetters + 5985387 + + + id + 5985387 + + + getter + 5985387 + + + + + id + getter + + + 12 + + + 1 + 2 + 5985387 + + + + + + + getter + id + + + 12 + + + 1 + 2 + 5985387 + + + + + + + + + ktPropertySetters + 366883 + + + id + 366883 + + + setter + 366883 + + + + + id + setter + + + 12 + + + 1 + 2 + 366883 + + + + + + + setter + id + + + 12 + + + 1 + 2 + 366883 + + + + + + + + + ktPropertyBackingFields + 14423708 + + + id + 14423708 + + + backingField + 14423708 + + + + + id + backingField + + + 12 + + + 1 + 2 + 14423708 + + + + + + + backingField + id + + + 12 + + + 1 + 2 + 14423708 + + + + + + + + + ktSyntheticBody + 9108 + + + id + 9108 + + + kind + 1821 + + + + + id + kind + + + 12 + + + 1 + 2 + 9108 + + + + + + + kind + id + + + 12 + + + 5 + 6 + 1821 + + + + + + + + + ktLocalFunction + 3841 + + + id + 3841 + + + + + + ktInitializerAssignment + 199475 + + + id + 199475 + + + + + + ktPropertyDelegates + 5201 + + + id + 5201 + + + variableId + 5201 + + + + + id + variableId + + + 12 + + + 1 + 2 + 5201 + + + + + + + variableId + id + + + 12 + + + 1 + 2 + 5201 + + + + + + + + + compiler_generated + 1467534 + + + id + 1467534 + + + kind + 13445 + + + + + id + kind + + + 12 + + + 1 + 2 + 1467534 + + + + + + + kind + id + + + 12 + + + 1 + 2 + 1920 + + + 8 + 9 + 1920 + + + 38 + 39 + 1920 + + + 81 + 82 + 1920 + + + 85 + 86 + 1920 + + + 236 + 237 + 1920 + + + 315 + 316 + 1920 + + + + + + + + + ktFunctionOriginalNames + 1586627 + + + id + 1586627 + + + name + 186323 + + + + + id + name + + + 12 + + + 1 + 2 + 1586627 + + + + + + + name + id + + + 12 + + + 1 + 2 + 147905 + + + 2 + 4 + 13445 + + + 6 + 16 + 15366 + + + 22 + 339 + 9604 + + + + + + + + + ktDataClasses + 113330 + + + id + 113330 + + + + + + diff --git a/java/ql/lib/upgrades/44d61b266bebf261cb027872646262e645efa059/upgrade.properties b/java/ql/lib/upgrades/44d61b266bebf261cb027872646262e645efa059/upgrade.properties new file mode 100644 index 00000000000..e027c6666fb --- /dev/null +++ b/java/ql/lib/upgrades/44d61b266bebf261cb027872646262e645efa059/upgrade.properties @@ -0,0 +1,6 @@ +description: Merge class and interface tables +compatibility: full +classes_or_interfaces.rel: run classes_or_interfaces.qlo +isInterface.rel: run isInterface.qlo +classes.rel: delete +interfaces.rel: delete diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index fe6ce573ada..0741ea4a1a3 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.5.3 + +### New Queries + +* Added a new query, `java/xxe-local`, which is a version of the XXE query that uses local sources (for example, reads from a local file). + +### Minor Analysis Improvements + +* The `java/index-out-of-bounds` query has improved its handling of arrays of constant length, and may report additional results in those cases. + ## 0.5.2 ### 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 aedc7fc4b2c..e64059b63d6 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -29,7 +29,7 @@ class TaintedPathConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(PathCreation p).getAnInput() or - sinkNode(sink, "create-file") + sinkNode(sink, ["create-file", "read-file"]) } override predicate isSanitizer(DataFlow::Node sanitizer) { diff --git a/java/ql/src/Telemetry/ExternalApi.qll b/java/ql/src/Telemetry/ExternalApi.qll index 5e28e540683..1675307e2ef 100644 --- a/java/ql/src/Telemetry/ExternalApi.qll +++ b/java/ql/src/Telemetry/ExternalApi.qll @@ -6,6 +6,7 @@ private import semmle.code.java.dataflow.ExternalFlow private import semmle.code.java.dataflow.FlowSources private import semmle.code.java.dataflow.FlowSummary private import semmle.code.java.dataflow.internal.DataFlowPrivate +private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import semmle.code.java.dataflow.TaintTracking pragma[nomagic] @@ -91,8 +92,17 @@ class ExternalApi extends Callable { pragma[nomagic] predicate isSink() { sinkNode(this.getAnInput(), _) } - /** Holds if this API is supported by existing CodeQL libraries, that is, it is either a recognized source or sink or has a flow summary. */ - predicate isSupported() { this.hasSummary() or this.isSource() or this.isSink() } + /** Holds if this API is a known neutral. */ + pragma[nomagic] + predicate isNeutral() { this = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() } + + /** + * Holds if this API is supported by existing CodeQL libraries, that is, it is either a + * recognized source, sink or neutral or it has a flow summary. + */ + predicate isSupported() { + this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral() + } } /** DEPRECATED: Alias for ExternalApi */ diff --git a/java/ql/src/Telemetry/SupportedExternalApis.ql b/java/ql/src/Telemetry/SupportedExternalApis.ql index ad1554dba91..a28b408cbb5 100644 --- a/java/ql/src/Telemetry/SupportedExternalApis.ql +++ b/java/ql/src/Telemetry/SupportedExternalApis.ql @@ -7,13 +7,9 @@ */ import java -import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import ExternalApi -private predicate relevant(ExternalApi api) { - api.isSupported() or - api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() -} +private predicate relevant(ExternalApi api) { api.isSupported() } from string apiName, int usages where Results::restrict(apiName, usages) diff --git a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql index 3031529626d..c4ff31847e3 100644 --- a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -7,13 +7,9 @@ */ import java -import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import ExternalApi -private predicate relevant(ExternalApi api) { - not api.isSupported() and - not api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() -} +private predicate relevant(ExternalApi api) { not api.isSupported() } from string apiName, int usages where Results::restrict(apiName, usages) diff --git a/java/ql/src/change-notes/2023-02-06-index-out-of-bounds-constant.md b/java/ql/src/change-notes/2023-02-06-index-out-of-bounds-constant.md deleted file mode 100644 index 364dfb1ab22..00000000000 --- a/java/ql/src/change-notes/2023-02-06-index-out-of-bounds-constant.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The `java/index-out-of-bounds` query has improved its handling of arrays of constant length, and may report additional results in those cases. diff --git a/java/ql/src/change-notes/2023-02-09-xxe-local.md b/java/ql/src/change-notes/2023-02-09-xxe-local.md deleted file mode 100644 index fd9d7209253..00000000000 --- a/java/ql/src/change-notes/2023-02-09-xxe-local.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: newQuery ---- -* Added a new query, `java/xxe-local`, which is a version of the XXE query that uses local sources (for example, reads from a local file). diff --git a/java/ql/src/change-notes/released/0.5.3.md b/java/ql/src/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..dfd7f6d2343 --- /dev/null +++ b/java/ql/src/change-notes/released/0.5.3.md @@ -0,0 +1,9 @@ +## 0.5.3 + +### New Queries + +* Added a new query, `java/xxe-local`, which is a version of the XXE query that uses local sources (for example, reads from a local file). + +### Minor Analysis Improvements + +* The `java/index-out-of-bounds` query has improved its handling of arrays of constant length, and may report additional results in those cases. diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index f1efa658670..7347b058157 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.5.3-dev +version: 0.5.4-dev groups: - java - queries diff --git a/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll index 8a48272a2ae..8855d7af7a6 100644 --- a/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll +++ b/java/ql/src/utils/flowtestcasegenerator/FlowTestCaseUtils.qll @@ -64,11 +64,12 @@ string getZero(PrimitiveType t) { * Holds if `c` may require disambiguation from an overload with the same argument count. */ predicate mayBeAmbiguous(Callable c) { - exists(Callable other, string package, string type, string name | - c.hasQualifiedName(package, type, name) and + exists(Callable other, Callable override, string package, string type, string name | + override = [c, c.(Method).getASourceOverriddenMethod*()] and + override.hasQualifiedName(package, type, name) and other.hasQualifiedName(package, type, name) and - other.getNumberOfParameters() = c.getNumberOfParameters() and - other != c + other.getNumberOfParameters() = override.getNumberOfParameters() and + other != override ) or c.isVarargs() diff --git a/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py index fb10c934afd..5e35ca52dd1 100755 --- a/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py +++ b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import errno import json @@ -13,11 +13,14 @@ import tempfile if any(s == "--help" for s in sys.argv): print("""Usage: -GenerateFlowTestCase.py specsToTest.csv projectPom.xml outdir [--force] +GenerateFlowTestCase.py specsToTest projectPom.xml outdir [--force] -This generates test cases exercising function model specifications found in specsToTest.csv +This generates test cases exercising function model specifications found in specsToTest producing files Test.java, test.ql, test.ext.yml and test.expected in outdir. +specsToTest should either be a .csv file, a .yml file, or a directory of .yml files, containing the +model specifications to test. + projectPom.xml should be a Maven pom sufficient to resolve the classes named in specsToTest.csv. Typically this means supplying a skeleton POM section that retrieves whatever jars contain the needed classes. @@ -40,14 +43,15 @@ if "--force" in sys.argv: if len(sys.argv) != 4: print( - "Usage: GenerateFlowTestCase.py specsToTest.csv projectPom.xml outdir [--force]", file=sys.stderr) - print("specsToTest.csv should contain CSV rows describing method taint-propagation specifications to test", file=sys.stderr) - print("projectPom.xml should import dependencies sufficient to resolve the types used in specsToTest.csv", file=sys.stderr) + "Usage: GenerateFlowTestCase.py specsToTest projectPom.xml outdir [--force]", file=sys.stderr) + print("specsToTest should contain CSV rows or YAML models describing method taint-propagation specifications to test", file=sys.stderr) + print("projectPom.xml should import dependencies sufficient to resolve the types used in specsToTest", file=sys.stderr) + print("\nRun with --help for more details.", file=sys.stderr) sys.exit(1) try: os.makedirs(sys.argv[3]) -except Exception as e: +except OSError as e: if e.errno != errno.EEXIST: print("Failed to create output directory %s: %s" % (sys.argv[3], e)) sys.exit(1) @@ -75,38 +79,86 @@ except Exception as e: (sys.argv[2], e), file=sys.stderr) sys.exit(1) -commentRegex = re.compile("^\s*(//|#)") +commentRegex = re.compile(r"^\s*(//|#)") def isComment(s): return commentRegex.match(s) is not None -try: - with open(sys.argv[1], "r") as f: - specs = [l for l in f if not isComment(l)] -except Exception as e: - print("Failed to open %s: %s\n" % (sys.argv[1], e)) +def readCsv(file): + try: + with open(file, "r") as f: + specs = [l.strip() for l in f if not isComment(l)] + except Exception as e: + print("Failed to open %s: %s\n" % (file, e)) + sys.exit(1) + + specs = [row.split(";") for row in specs] + return specs + + +def readYml(file): + try: + import yaml + with open(file, "r") as f: + doc = yaml.load(f.read(), yaml.Loader) + specs = [] + for ext in doc['extensions']: + if ext['addsTo']['extensible'] == 'summaryModel': + for row in ext['data']: + if isinstance(row[2], bool): + row[2] = str(row[2]).lower() + specs.append(row) + return specs + except ImportError: + print("PyYAML not found - try \n pip install pyyaml") + sys.exit(1) + except ValueError as e: + print("Invalid yaml model in %s: %s\n" % (file, e)) + sys.exit(1) + except OSError as e: + print("Failed to open %s: %s\n" % (file, e)) + sys.exit(1) + + +def readYmlDir(dirname): + specs = [] + for f in os.listdir(dirname): + if f.endswith('.yml'): + specs += readYml(f"{dirname}/{f}") + return specs + + +specsFile = sys.argv[1] +if os.path.isdir(specsFile): + specs = readYmlDir(specsFile) +elif specsFile.endswith(".yml") or specsFile.endswith(".yaml"): + specs = readYml(specsFile) +elif specsFile.endswith(".csv"): + specs = readCsv(specsFile) +else: + print(f"Invalid specs {specsFile}. Must be a csv file, a yml file, or a directory of yml files.") sys.exit(1) + projectTestPkgDir = os.path.join(projectDir, "src", "main", "java", "test") projectTestFile = os.path.join(projectTestPkgDir, "Test.java") os.makedirs(projectTestPkgDir) -def qualifiedOuterNameFromCsvRow(row): - cells = row.split(";") - if len(cells) < 2: +def qualifiedOuterNameFromRow(row): + if len(row) < 2: return None - return cells[0] + "." + cells[1].replace("$", ".") + return row[0] + "." + row[1].replace("$", ".") with open(projectTestFile, "w") as testJava: testJava.write("package test;\n\npublic class Test {\n\n") for i, spec in enumerate(specs): - outerName = qualifiedOuterNameFromCsvRow(spec) + outerName = qualifiedOuterNameFromRow(spec) if outerName is None: print("A taint specification has the wrong format: should be 'package;classname;methodname....'", file=sys.stderr) print("Mis-formatted row: " + spec, file=sys.stderr) @@ -140,7 +192,7 @@ dependencies: with open(qlFile, "w") as f: f.write( "import java\nimport utils.flowtestcasegenerator.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") - f.write(",\n".join('\t\t\t"%s"' % spec.strip() for spec in specs)) + f.write(",\n".join('\t\t\t"%s"' % ';'.join(spec) for spec in specs)) f.write("\n\t\t]\n\t}\n}\n") print("Generating tests") @@ -221,7 +273,7 @@ if len(supportModelRows) != 0: # Make a test extension file with open(resultYml, "w") as f: models = "\n".join(' - [%s]' % - modelSpecRow[0].strip() for modelSpecRow in supportModelRows) + modelSpecRow[0].strip() for modelSpecRow in supportModelRows) dataextensions = f"""extensions: - addsTo: pack: codeql/java-tests diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index d7c3a010bb3..879df6bb873 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -36,8 +36,6 @@ private predicate isInTestFile(J::File file) { private predicate isJdkInternal(J::CompilationUnit cu) { cu.getPackage().getName().matches("org.graalvm%") or cu.getPackage().getName().matches("com.sun%") or - cu.getPackage().getName().matches("javax.swing%") or - cu.getPackage().getName().matches("java.awt%") or cu.getPackage().getName().matches("sun%") or cu.getPackage().getName().matches("jdk%") or cu.getPackage().getName().matches("java2d%") or @@ -57,12 +55,18 @@ private predicate isJdkInternal(J::CompilationUnit cu) { cu.getPackage().getName() = "" } +private predicate isInfrequentlyUsed(J::CompilationUnit cu) { + cu.getPackage().getName().matches("javax.swing%") or + cu.getPackage().getName().matches("java.awt%") +} + /** * Holds if it is relevant to generate models for `api`. */ private predicate isRelevantForModels(J::Callable api) { not isInTestFile(api.getCompilationUnit().getFile()) and not isJdkInternal(api.getCompilationUnit()) and + not isInfrequentlyUsed(api.getCompilationUnit()) and not api instanceof J::MainMethod and not api instanceof J::StaticInitializer and not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod()) and diff --git a/java/ql/src/utils/stub-generator/Stubs.qll b/java/ql/src/utils/stub-generator/Stubs.qll index b670d3837bb..785f621cba0 100644 --- a/java/ql/src/utils/stub-generator/Stubs.qll +++ b/java/ql/src/utils/stub-generator/Stubs.qll @@ -515,7 +515,7 @@ private RefType getAReferencedType(RefType t) { /** A top level type whose file should be stubbed */ class GeneratedTopLevel extends TopLevelType instanceof GeneratedType { - GeneratedTopLevel() { this = this.getSourceDeclaration() } + GeneratedTopLevel() { this = this.(ClassOrInterface).getSourceDeclaration() } private TopLevelType getAnImportedType() { result = getAReferencedType(this).getSourceDeclaration() and @@ -523,9 +523,8 @@ class GeneratedTopLevel extends TopLevelType instanceof GeneratedType { } private string stubAnImport() { - exists(RefType t, string pkg, string name | + exists(ClassOrInterface t, string pkg, string name | t = this.getAnImportedType() and - (t instanceof Class or t instanceof Interface) and t.hasQualifiedName(pkg, name) and t != this and pkg != "java.lang" diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java index 0c0e386e9c2..35a118f8048 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java @@ -145,7 +145,7 @@ class StrBuilderTest { // Test all fluent methods are passing taint through to their result: StrBuilder fluentAllMethodsTest = new StrBuilder(taint()); - sink(fluentAllMethodsTest // $hasTaintFlow + sink(fluentAllMethodsTest .append("text") .appendAll("text") .appendFixedWidthPadLeft("text", 4, ' ') @@ -171,7 +171,7 @@ class StrBuilderTest { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); + .trim()); // $hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: StrBuilder fluentAllMethodsTest2 = new StrBuilder(); diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java index 74f0f1d17c9..43171647004 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java @@ -145,7 +145,7 @@ class StrBuilderTextTest { // Test all fluent methods are passing taint through to their result: StrBuilder fluentAllMethodsTest = new StrBuilder(taint()); - sink(fluentAllMethodsTest // $hasTaintFlow + sink(fluentAllMethodsTest .append("text") .appendAll("text") .appendFixedWidthPadLeft("text", 4, ' ') @@ -171,7 +171,7 @@ class StrBuilderTextTest { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); + .trim()); // $hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: StrBuilder fluentAllMethodsTest2 = new StrBuilder(); diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java index e490c11c7cb..41941cca223 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java @@ -146,7 +146,7 @@ class TextStringBuilderTest { // Test all fluent methods are passing taint through to their result: TextStringBuilder fluentAllMethodsTest = new TextStringBuilder(taint()); - sink(fluentAllMethodsTest // $hasTaintFlow + sink(fluentAllMethodsTest .append("text") .appendAll("text") .appendFixedWidthPadLeft("text", 4, ' ') @@ -172,7 +172,7 @@ class TextStringBuilderTest { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); + .trim()); // $hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: TextStringBuilder fluentAllMethodsTest2 = new TextStringBuilder(); 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 new file mode 100644 index 00000000000..866a6bd77d3 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java @@ -0,0 +1,99 @@ +package generatedtest; + +import java.net.URI; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.Charset; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "java.net;URI;false;URI;(String);;Argument[0];Argument[-1];taint;manual" + URI out = null; + String in = (String) source(); + out = new URI(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URI;false;create;;;Argument[0];ReturnValue;taint;manual" + URI out = null; + String in = (String) source(); + out = URI.create(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URI;false;toASCIIString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + URI in = (URI) source(); + out = in.toASCIIString(); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URI;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + URI in = (URI) source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URI;false;toURL;;;Argument[-1];ReturnValue;taint;manual" + URL out = null; + URI in = (URI) source(); + out = in.toURL(); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URL;false;URL;(String);;Argument[0];Argument[-1];taint;manual" + URL out = null; + String in = (String) source(); + out = new URL(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URL;false;toExternalForm;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + URL in = (URL) source(); + out = in.toExternalForm(); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URL;false;toURI;;;Argument[-1];ReturnValue;taint;manual" + URI out = null; + URL in = (URL) source(); + out = in.toURI(); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URLDecoder;false;decode;;;Argument[0];ReturnValue;taint;manual" + String out = null; + String in = (String) source(); + out = URLDecoder.decode(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URLDecoder;false;decode;;;Argument[0];ReturnValue;taint;manual" + String out = null; + String in = (String) source(); + out = URLDecoder.decode(in, (Charset) null); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URLDecoder;false;decode;;;Argument[0];ReturnValue;taint;manual" + String out = null; + String in = (String) source(); + out = URLDecoder.decode(in, (String) null); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.net/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/jdk/java.net/test.ql b/java/ql/test/library-tests/frameworks/jdk/java.net/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.net/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/qlengine/selectAtType.ql b/java/ql/test/library-tests/qlengine/selectAtType.ql index 3947b504059..14fa6ce034f 100644 --- a/java/ql/test/library-tests/qlengine/selectAtType.ql +++ b/java/ql/test/library-tests/qlengine/selectAtType.ql @@ -1,5 +1,5 @@ import java -@class clasz() { any() } +@classorinterface clasz() { any() } select clasz() diff --git a/java/ql/test/query-tests/security/CWE-079/semmle/tests/JsfXSS.java b/java/ql/test/query-tests/security/CWE-079/semmle/tests/JsfXSS.java index 9fd7a1ffcae..281b89720d2 100644 --- a/java/ql/test/query-tests/security/CWE-079/semmle/tests/JsfXSS.java +++ b/java/ql/test/query-tests/security/CWE-079/semmle/tests/JsfXSS.java @@ -24,9 +24,9 @@ public class JsfXSS extends Renderer ResponseWriter writer = facesContext.getResponseWriter(); writer.write(""); diff --git a/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/AndroidManifest.xml index 78d85ecb7a5..9a915624e5e 100644 --- a/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/AndroidManifest.xml +++ b/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" package="com.example.happybirthday"> - + tools:targetApi="31"> diff --git a/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/Testbuild/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/Testbuild/AndroidManifest.xml index 613bc8aeca1..cb8591f3a70 100644 --- a/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/Testbuild/AndroidManifest.xml +++ b/java/ql/test/query-tests/security/CWE-489/debuggable-attribute/Testbuild/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" package="com.example.happybirthday"> - + tools:targetApi="31"> diff --git a/java/ql/test/query-tests/security/CWE-524/res/layout/Test.xml b/java/ql/test/query-tests/security/CWE-524/res/layout/Test.xml index 107c13dd306..3446d530794 100644 --- a/java/ql/test/query-tests/security/CWE-524/res/layout/Test.xml +++ b/java/ql/test/query-tests/security/CWE-524/res/layout/Test.xml @@ -4,9 +4,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:inputType="text"/> - + android:inputType="textMultiLine"/> - + diff --git a/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedMSSQLCredentials.java b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedMSSQLCredentials.java new file mode 100644 index 00000000000..173c965a8c7 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedMSSQLCredentials.java @@ -0,0 +1,10 @@ +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; + +public class HardcodedMSSQLCredentials { + public static void main(SQLServerDataSource ds) throws Exception { + ds.setUser("Username"); // $ HardcodedCredentialsApiCall + ds.setPassword("password"); // $ HardcodedCredentialsApiCall + ds.getConnection("Username", null); // $ HardcodedCredentialsApiCall + ds.getConnection(null, "password"); // $ HardcodedCredentialsApiCall + } +} \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-798/semmle/tests/options b/java/ql/test/query-tests/security/CWE-798/semmle/tests/options index 1009a2fc6e8..215e0929c43 100644 --- a/java/ql/test/query-tests/security/CWE-798/semmle/tests/options +++ b/java/ql/test/query-tests/security/CWE-798/semmle/tests/options @@ -1 +1 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/amazon-aws-sdk-1.11.700:${testdir}/../../../../../stubs/azure-sdk-for-java:${testdir}/../../../../../stubs/shiro-core-1.4.0:${testdir}/../../../../../stubs/jsch-0.1.55:${testdir}/../../../../../stubs/ganymed-ssh-2-260:${testdir}/../../../../../stubs/apache-mina-sshd-2.8.0:${testdir}/../../../../../stubs/sshj-0.33.0:${testdir}/../../../../../stubs/j2ssh-1.5.5:${testdir}/../../../../../stubs/trilead-ssh2-212:${testdir}/../../../../../stubs/apache-commons-net-3.8.0:${testdir}/../../../../../stubs/mongodbClient +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/amazon-aws-sdk-1.11.700:${testdir}/../../../../../stubs/azure-sdk-for-java:${testdir}/../../../../../stubs/shiro-core-1.4.0:${testdir}/../../../../../stubs/jsch-0.1.55:${testdir}/../../../../../stubs/ganymed-ssh-2-260:${testdir}/../../../../../stubs/apache-mina-sshd-2.8.0:${testdir}/../../../../../stubs/sshj-0.33.0:${testdir}/../../../../../stubs/j2ssh-1.5.5:${testdir}/../../../../../stubs/trilead-ssh2-212:${testdir}/../../../../../stubs/apache-commons-net-3.8.0:${testdir}/../../../../../stubs/mongodbClient:${testdir}/../../../../../stubs/mssql-jdbc-12.2.0 diff --git a/java/ql/test/query-tests/security/CWE-926/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-926/AndroidManifest.xml index 210c97b26a2..c759d38e7dd 100644 --- a/java/ql/test/query-tests/security/CWE-926/AndroidManifest.xml +++ b/java/ql/test/query-tests/security/CWE-926/AndroidManifest.xml @@ -14,58 +14,58 @@ android:theme="@style/Theme.HappyBirthday" tools:targetApi="31"> - - + - - + - - + - - + - - + - - + - - + - @@ -73,41 +73,41 @@ - + - - + - - + - - + - - + diff --git a/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml index 928dc72a665..ba2bbbb006b 100644 --- a/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml +++ b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml @@ -17,22 +17,22 @@ - + android:readPermission="android.permission.MANAGE_DOCUMENTS"> - + android:writePermission="android.permission.MANAGE_DOCUMENTS"> diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java new file mode 100644 index 00000000000..24ca455ddd0 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java @@ -0,0 +1,166 @@ +// Generated automatically from com.microsoft.sqlserver.jdbc.ISQLServerDataSource for testing purposes + +package com.microsoft.sqlserver.jdbc; + +import com.microsoft.sqlserver.jdbc.SQLServerAccessTokenCallback; +import javax.sql.CommonDataSource; +import org.ietf.jgss.GSSCredential; + +public interface ISQLServerDataSource extends CommonDataSource +{ + GSSCredential getGSSCredentials(); + SQLServerAccessTokenCallback getAccessTokenCallback(); + String getAADSecurePrincipalId(); + String getAccessToken(); + String getApplicationIntent(); + String getApplicationName(); + String getAuthentication(); + String getClientCertificate(); + String getClientKey(); + String getColumnEncryptionSetting(); + String getDatabaseName(); + String getDatetimeParameterType(); + String getDescription(); + String getDomain(); + String getEnclaveAttestationProtocol(); + String getEnclaveAttestationUrl(); + String getEncrypt(); + String getFailoverPartner(); + String getHostNameInCertificate(); + String getIPAddressPreference(); + String getInstanceName(); + String getJAASConfigurationName(); + String getJASSConfigurationName(); + String getKeyStoreAuthentication(); + String getKeyStoreLocation(); + String getKeyStorePrincipalId(); + String getKeyVaultProviderClientId(); + String getMSIClientId(); + String getMaxResultBuffer(); + String getPrepareMethod(); + String getRealm(); + String getResponseBuffering(); + String getSSLProtocol(); + String getSelectMethod(); + String getServerCertificate(); + String getServerName(); + String getServerSpn(); + String getSocketFactoryClass(); + String getSocketFactoryConstructorArg(); + String getTrustManagerClass(); + String getTrustManagerConstructorArg(); + String getTrustStore(); + String getTrustStoreType(); + String getURL(); + String getUser(); + String getWorkstationID(); + boolean getDelayLoadingLobs(); + boolean getDisableStatementPooling(); + boolean getEnablePrepareOnFirstPreparedStatementCall(); + boolean getFIPS(); + boolean getLastUpdateCount(); + boolean getMultiSubnetFailover(); + boolean getReplication(); + boolean getSendStringParametersAsUnicode(); + boolean getSendTemporalDataTypesAsStringForBulkCopy(); + boolean getSendTimeAsDatetime(); + boolean getServerNameAsACE(); + boolean getTransparentNetworkIPResolution(); + boolean getTrustServerCertificate(); + boolean getUseBulkCopyForBatchInsert(); + boolean getUseFmtOnly(); + boolean getXopenStates(); + int getCancelQueryTimeout(); + int getConnectRetryCount(); + int getConnectRetryInterval(); + int getLockTimeout(); + int getMsiTokenCacheTtl(); + int getPacketSize(); + int getPortNumber(); + int getQueryTimeout(); + int getServerPreparedStatementDiscardThreshold(); + int getSocketTimeout(); + int getStatementPoolingCacheSize(); + void setAADSecurePrincipalId(String p0); + void setAADSecurePrincipalSecret(String p0); + void setAccessToken(String p0); + void setAccessTokenCallback(SQLServerAccessTokenCallback p0); + void setApplicationIntent(String p0); + void setApplicationName(String p0); + void setAuthentication(String p0); + void setAuthenticationScheme(String p0); + void setCancelQueryTimeout(int p0); + void setClientCertificate(String p0); + void setClientKey(String p0); + void setClientKeyPassword(String p0); + void setColumnEncryptionSetting(String p0); + void setConnectRetryCount(int p0); + void setConnectRetryInterval(int p0); + void setDatabaseName(String p0); + void setDatetimeParameterType(String p0); + void setDelayLoadingLobs(boolean p0); + void setDescription(String p0); + void setDisableStatementPooling(boolean p0); + void setDomain(String p0); + void setEnablePrepareOnFirstPreparedStatementCall(boolean p0); + void setEnclaveAttestationProtocol(String p0); + void setEnclaveAttestationUrl(String p0); + void setEncrypt(String p0); + void setEncrypt(boolean p0); + void setFIPS(boolean p0); + void setFailoverPartner(String p0); + void setGSSCredentials(GSSCredential p0); + void setHostNameInCertificate(String p0); + void setIPAddressPreference(String p0); + void setInstanceName(String p0); + void setIntegratedSecurity(boolean p0); + void setJAASConfigurationName(String p0); + void setJASSConfigurationName(String p0); + void setKeyStoreAuthentication(String p0); + void setKeyStoreLocation(String p0); + void setKeyStorePrincipalId(String p0); + void setKeyStoreSecret(String p0); + void setKeyVaultProviderClientId(String p0); + void setKeyVaultProviderClientKey(String p0); + void setLastUpdateCount(boolean p0); + void setLockTimeout(int p0); + void setMSIClientId(String p0); + void setMaxResultBuffer(String p0); + void setMsiTokenCacheTtl(int p0); + void setMultiSubnetFailover(boolean p0); + void setPacketSize(int p0); + void setPassword(String p0); + void setPortNumber(int p0); + void setPrepareMethod(String p0); + void setQueryTimeout(int p0); + void setRealm(String p0); + void setReplication(boolean p0); + void setResponseBuffering(String p0); + void setSSLProtocol(String p0); + void setSelectMethod(String p0); + void setSendStringParametersAsUnicode(boolean p0); + void setSendTemporalDataTypesAsStringForBulkCopy(boolean p0); + void setSendTimeAsDatetime(boolean p0); + void setServerCertificate(String p0); + void setServerName(String p0); + void setServerNameAsACE(boolean p0); + void setServerPreparedStatementDiscardThreshold(int p0); + void setServerSpn(String p0); + void setSocketFactoryClass(String p0); + void setSocketFactoryConstructorArg(String p0); + void setSocketTimeout(int p0); + void setStatementPoolingCacheSize(int p0); + void setTransparentNetworkIPResolution(boolean p0); + void setTrustManagerClass(String p0); + void setTrustManagerConstructorArg(String p0); + void setTrustServerCertificate(boolean p0); + void setTrustStore(String p0); + void setTrustStorePassword(String p0); + void setTrustStoreType(String p0); + void setURL(String p0); + void setUseBulkCopyForBatchInsert(boolean p0); + void setUseFmtOnly(boolean p0); + void setUser(String p0); + void setWorkstationID(String p0); + void setXopenStates(boolean p0); +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerAccessTokenCallback.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerAccessTokenCallback.java new file mode 100644 index 00000000000..50e38691e96 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerAccessTokenCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from com.microsoft.sqlserver.jdbc.SQLServerAccessTokenCallback for testing purposes + +package com.microsoft.sqlserver.jdbc; + +import com.microsoft.sqlserver.jdbc.SqlAuthenticationToken; + +public interface SQLServerAccessTokenCallback +{ + SqlAuthenticationToken getAccessToken(String p0, String p1); +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java new file mode 100644 index 00000000000..03ba02d9ac0 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -0,0 +1,185 @@ +// Generated automatically from com.microsoft.sqlserver.jdbc.SQLServerDataSource for testing purposes + +package com.microsoft.sqlserver.jdbc; + +import com.microsoft.sqlserver.jdbc.ISQLServerDataSource; +import com.microsoft.sqlserver.jdbc.SQLServerAccessTokenCallback; +import java.io.PrintWriter; +import java.io.Serializable; +import java.sql.Connection; +import java.util.logging.Logger; +import javax.naming.Reference; +import javax.naming.Referenceable; +import javax.sql.DataSource; +import org.ietf.jgss.GSSCredential; + +public class SQLServerDataSource implements DataSource, ISQLServerDataSource, Referenceable, Serializable +{ + public T unwrap(Class p0){ return null; } + public Connection getConnection(){ return null; } + public Connection getConnection(String p0, String p1){ return null; } + public GSSCredential getGSSCredentials(){ return null; } + public Logger getParentLogger(){ return null; } + public PrintWriter getLogWriter(){ return null; } + public Reference getReference(){ return null; } + public SQLServerAccessTokenCallback getAccessTokenCallback(){ return null; } + public SQLServerDataSource(){} + public String getAADSecurePrincipalId(){ return null; } + public String getAccessToken(){ return null; } + public String getApplicationIntent(){ return null; } + public String getApplicationName(){ return null; } + public String getAuthentication(){ return null; } + public String getClientCertificate(){ return null; } + public String getClientKey(){ return null; } + public String getColumnEncryptionSetting(){ return null; } + public String getDatabaseName(){ return null; } + public String getDatetimeParameterType(){ return null; } + public String getDescription(){ return null; } + public String getDomain(){ return null; } + public String getEnclaveAttestationProtocol(){ return null; } + public String getEnclaveAttestationUrl(){ return null; } + public String getEncrypt(){ return null; } + public String getFailoverPartner(){ return null; } + public String getHostNameInCertificate(){ return null; } + public String getIPAddressPreference(){ return null; } + public String getInstanceName(){ return null; } + public String getJAASConfigurationName(){ return null; } + public String getJASSConfigurationName(){ return null; } + public String getKeyStoreAuthentication(){ return null; } + public String getKeyStoreLocation(){ return null; } + public String getKeyStorePrincipalId(){ return null; } + public String getKeyVaultProviderClientId(){ return null; } + public String getMSIClientId(){ return null; } + public String getMaxResultBuffer(){ return null; } + public String getPrepareMethod(){ return null; } + public String getRealm(){ return null; } + public String getResponseBuffering(){ return null; } + public String getSSLProtocol(){ return null; } + public String getSelectMethod(){ return null; } + public String getServerCertificate(){ return null; } + public String getServerName(){ return null; } + public String getServerSpn(){ return null; } + public String getSocketFactoryClass(){ return null; } + public String getSocketFactoryConstructorArg(){ return null; } + public String getTrustManagerClass(){ return null; } + public String getTrustManagerConstructorArg(){ return null; } + public String getTrustStore(){ return null; } + public String getTrustStoreType(){ return null; } + public String getURL(){ return null; } + public String getUser(){ return null; } + public String getWorkstationID(){ return null; } + public String toString(){ return null; } + public boolean getDelayLoadingLobs(){ return false; } + public boolean getDisableStatementPooling(){ return false; } + public boolean getEnablePrepareOnFirstPreparedStatementCall(){ return false; } + public boolean getFIPS(){ return false; } + public boolean getLastUpdateCount(){ return false; } + public boolean getMultiSubnetFailover(){ return false; } + public boolean getReplication(){ return false; } + public boolean getSendStringParametersAsUnicode(){ return false; } + public boolean getSendTemporalDataTypesAsStringForBulkCopy(){ return false; } + public boolean getSendTimeAsDatetime(){ return false; } + public boolean getServerNameAsACE(){ return false; } + public boolean getTransparentNetworkIPResolution(){ return false; } + public boolean getTrustServerCertificate(){ return false; } + public boolean getUseBulkCopyForBatchInsert(){ return false; } + public boolean getUseFmtOnly(){ return false; } + public boolean getXopenStates(){ return false; } + public boolean isWrapperFor(Class p0){ return false; } + public int getCancelQueryTimeout(){ return 0; } + public int getConnectRetryCount(){ return 0; } + public int getConnectRetryInterval(){ return 0; } + public int getLockTimeout(){ return 0; } + public int getLoginTimeout(){ return 0; } + public int getMsiTokenCacheTtl(){ return 0; } + public int getPacketSize(){ return 0; } + public int getPortNumber(){ return 0; } + public int getQueryTimeout(){ return 0; } + public int getServerPreparedStatementDiscardThreshold(){ return 0; } + public int getSocketTimeout(){ return 0; } + public int getStatementPoolingCacheSize(){ return 0; } + public void setAADSecurePrincipalId(String p0){} + public void setAADSecurePrincipalSecret(String p0){} + public void setAccessToken(String p0){} + public void setAccessTokenCallback(SQLServerAccessTokenCallback p0){} + public void setApplicationIntent(String p0){} + public void setApplicationName(String p0){} + public void setAuthentication(String p0){} + public void setAuthenticationScheme(String p0){} + public void setCancelQueryTimeout(int p0){} + public void setClientCertificate(String p0){} + public void setClientKey(String p0){} + public void setClientKeyPassword(String p0){} + public void setColumnEncryptionSetting(String p0){} + public void setConnectRetryCount(int p0){} + public void setConnectRetryInterval(int p0){} + public void setDatabaseName(String p0){} + public void setDatetimeParameterType(String p0){} + public void setDelayLoadingLobs(boolean p0){} + public void setDescription(String p0){} + public void setDisableStatementPooling(boolean p0){} + public void setDomain(String p0){} + public void setEnablePrepareOnFirstPreparedStatementCall(boolean p0){} + public void setEnclaveAttestationProtocol(String p0){} + public void setEnclaveAttestationUrl(String p0){} + public void setEncrypt(String p0){} + public void setEncrypt(boolean p0){} + public void setFIPS(boolean p0){} + public void setFailoverPartner(String p0){} + public void setGSSCredentials(GSSCredential p0){} + public void setHostNameInCertificate(String p0){} + public void setIPAddressPreference(String p0){} + public void setInstanceName(String p0){} + public void setIntegratedSecurity(boolean p0){} + public void setJAASConfigurationName(String p0){} + public void setJASSConfigurationName(String p0){} + public void setKeyStoreAuthentication(String p0){} + public void setKeyStoreLocation(String p0){} + public void setKeyStorePrincipalId(String p0){} + public void setKeyStoreSecret(String p0){} + public void setKeyVaultProviderClientId(String p0){} + public void setKeyVaultProviderClientKey(String p0){} + public void setLastUpdateCount(boolean p0){} + public void setLockTimeout(int p0){} + public void setLogWriter(PrintWriter p0){} + public void setLoginTimeout(int p0){} + public void setMSIClientId(String p0){} + public void setMaxResultBuffer(String p0){} + public void setMsiTokenCacheTtl(int p0){} + public void setMultiSubnetFailover(boolean p0){} + public void setPacketSize(int p0){} + public void setPassword(String p0){} + public void setPortNumber(int p0){} + public void setPrepareMethod(String p0){} + public void setQueryTimeout(int p0){} + public void setRealm(String p0){} + public void setReplication(boolean p0){} + public void setResponseBuffering(String p0){} + public void setSSLProtocol(String p0){} + public void setSelectMethod(String p0){} + public void setSendStringParametersAsUnicode(boolean p0){} + public void setSendTemporalDataTypesAsStringForBulkCopy(boolean p0){} + public void setSendTimeAsDatetime(boolean p0){} + public void setServerCertificate(String p0){} + public void setServerName(String p0){} + public void setServerNameAsACE(boolean p0){} + public void setServerPreparedStatementDiscardThreshold(int p0){} + public void setServerSpn(String p0){} + public void setSocketFactoryClass(String p0){} + public void setSocketFactoryConstructorArg(String p0){} + public void setSocketTimeout(int p0){} + public void setStatementPoolingCacheSize(int p0){} + public void setTransparentNetworkIPResolution(boolean p0){} + public void setTrustManagerClass(String p0){} + public void setTrustManagerConstructorArg(String p0){} + public void setTrustServerCertificate(boolean p0){} + public void setTrustStore(String p0){} + public void setTrustStorePassword(String p0){} + public void setTrustStoreType(String p0){} + public void setURL(String p0){} + public void setUseBulkCopyForBatchInsert(boolean p0){} + public void setUseFmtOnly(boolean p0){} + public void setUser(String p0){} + public void setWorkstationID(String p0){} + public void setXopenStates(boolean p0){} +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SqlAuthenticationToken.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SqlAuthenticationToken.java new file mode 100644 index 00000000000..454119f9225 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/com/microsoft/sqlserver/jdbc/SqlAuthenticationToken.java @@ -0,0 +1,16 @@ +// Generated automatically from com.microsoft.sqlserver.jdbc.SqlAuthenticationToken for testing purposes + +package com.microsoft.sqlserver.jdbc; + +import java.io.Serializable; +import java.util.Date; + +public class SqlAuthenticationToken implements Serializable +{ + protected SqlAuthenticationToken() {} + public Date getExpiresOn(){ return null; } + public SqlAuthenticationToken(String p0, Date p1){} + public SqlAuthenticationToken(String p0, long p1){} + public String getAccessToken(){ return null; } + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/SecretKey.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/SecretKey.java new file mode 100644 index 00000000000..88c9e4539ba --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/SecretKey.java @@ -0,0 +1,11 @@ +// Generated automatically from javax.crypto.SecretKey for testing purposes + +package javax.crypto; + +import java.security.Key; +import javax.security.auth.Destroyable; + +public interface SecretKey extends Destroyable, Key +{ + static long serialVersionUID = 0; +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/spec/SecretKeySpec.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/spec/SecretKeySpec.java new file mode 100644 index 00000000000..d90b6b2baca --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/crypto/spec/SecretKeySpec.java @@ -0,0 +1,18 @@ +// Generated automatically from javax.crypto.spec.SecretKeySpec for testing purposes + +package javax.crypto.spec; + +import java.security.spec.KeySpec; +import javax.crypto.SecretKey; + +public class SecretKeySpec implements KeySpec, SecretKey +{ + protected SecretKeySpec() {} + public SecretKeySpec(byte[] p0, String p1){} + public SecretKeySpec(byte[] p0, int p1, int p2, String p3){} + public String getAlgorithm(){ return null; } + public String getFormat(){ return null; } + public boolean equals(Object p0){ return false; } + public byte[] getEncoded(){ return null; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/RefAddr.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/RefAddr.java new file mode 100644 index 00000000000..77d0a07406a --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/RefAddr.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.naming.RefAddr for testing purposes + +package javax.naming; + +import java.io.Serializable; + +abstract public class RefAddr implements Serializable +{ + protected RefAddr() {} + protected RefAddr(String p0){} + protected String addrType = null; + public String getType(){ return null; } + public String toString(){ return null; } + public abstract Object getContent(); + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Reference.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Reference.java new file mode 100644 index 00000000000..5dbfa520ead --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Reference.java @@ -0,0 +1,36 @@ +// Generated automatically from javax.naming.Reference for testing purposes + +package javax.naming; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Vector; +import javax.naming.RefAddr; + +public class Reference implements Cloneable, Serializable +{ + protected Reference() {} + protected String classFactory = null; + protected String classFactoryLocation = null; + protected String className = null; + protected Vector addrs = null; + public Enumeration getAll(){ return null; } + public Object clone(){ return null; } + public Object remove(int p0){ return null; } + public RefAddr get(String p0){ return null; } + public RefAddr get(int p0){ return null; } + public Reference(String p0){} + public Reference(String p0, RefAddr p1){} + public Reference(String p0, RefAddr p1, String p2, String p3){} + public Reference(String p0, String p1, String p2){} + public String getClassName(){ return null; } + public String getFactoryClassLocation(){ return null; } + public String getFactoryClassName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public void add(RefAddr p0){} + public void add(int p0, RefAddr p1){} + public void clear(){} +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Referenceable.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Referenceable.java new file mode 100644 index 00000000000..d3cc3ca087d --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/naming/Referenceable.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.naming.Referenceable for testing purposes + +package javax.naming; + +import javax.naming.Reference; + +public interface Referenceable +{ + Reference getReference(); +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/security/auth/Destroyable.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/security/auth/Destroyable.java new file mode 100644 index 00000000000..979ca409ba6 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/security/auth/Destroyable.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.security.auth.Destroyable for testing purposes + +package javax.security.auth; + + +public interface Destroyable +{ + default boolean isDestroyed(){ return false; } + default void destroy(){} +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/sql/CommonDataSource.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/sql/CommonDataSource.java new file mode 100644 index 00000000000..cdc814157ce --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/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/mssql-jdbc-12.2.0/javax/sql/DataSource.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/javax/sql/DataSource.java new file mode 100644 index 00000000000..d28d63d6e0a --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/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/mssql-jdbc-12.2.0/org/ietf/jgss/GSSCredential.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/GSSCredential.java new file mode 100644 index 00000000000..120a67f30c7 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/GSSCredential.java @@ -0,0 +1,27 @@ +// Generated automatically from org.ietf.jgss.GSSCredential for testing purposes + +package org.ietf.jgss; + +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; + +public interface GSSCredential extends Cloneable +{ + GSSName getName(); + GSSName getName(Oid p0); + Oid[] getMechs(); + boolean equals(Object p0); + int getRemainingAcceptLifetime(Oid p0); + int getRemainingInitLifetime(Oid p0); + int getRemainingLifetime(); + int getUsage(); + int getUsage(Oid p0); + int hashCode(); + static int ACCEPT_ONLY = 0; + static int DEFAULT_LIFETIME = 0; + static int INDEFINITE_LIFETIME = 0; + static int INITIATE_AND_ACCEPT = 0; + static int INITIATE_ONLY = 0; + void add(GSSName p0, int p1, int p2, Oid p3, int p4); + void dispose(); +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/GSSName.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/GSSName.java new file mode 100644 index 00000000000..3ca10408640 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/GSSName.java @@ -0,0 +1,24 @@ +// Generated automatically from org.ietf.jgss.GSSName for testing purposes + +package org.ietf.jgss; + +import org.ietf.jgss.Oid; + +public interface GSSName +{ + GSSName canonicalize(Oid p0); + Oid getStringNameType(); + String toString(); + boolean equals(GSSName p0); + boolean equals(Object p0); + boolean isAnonymous(); + boolean isMN(); + byte[] export(); + int hashCode(); + static Oid NT_ANONYMOUS = null; + static Oid NT_EXPORT_NAME = null; + static Oid NT_HOSTBASED_SERVICE = null; + static Oid NT_MACHINE_UID_NAME = null; + static Oid NT_STRING_UID_NAME = null; + static Oid NT_USER_NAME = null; +} diff --git a/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/Oid.java b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/Oid.java new file mode 100644 index 00000000000..151f60ed841 --- /dev/null +++ b/java/ql/test/stubs/mssql-jdbc-12.2.0/org/ietf/jgss/Oid.java @@ -0,0 +1,18 @@ +// Generated automatically from org.ietf.jgss.Oid for testing purposes + +package org.ietf.jgss; + +import java.io.InputStream; + +public class Oid +{ + protected Oid() {} + public Oid(InputStream p0){} + public Oid(String p0){} + public Oid(byte[] p0){} + public String toString(){ return null; } + public boolean containedIn(Oid[] p0){ return false; } + public boolean equals(Object p0){ return false; } + public byte[] getDER(){ return null; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected index 79483bc24b1..8f6c51aee54 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.expected @@ -1,4 +1,5 @@ | p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[-1];create-file;generated | +| p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[0];read-file;generated | | p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];create-file;generated | | p;Sinks;true;readUrl;(URL,Charset);;Argument[0];open-url;generated | | p;Sources;true;readUrl;(URL);;Argument[0];open-url;generated | diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointCharacteristics.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointCharacteristics.qll index 160c81f8acd..25ac8ca402a 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointCharacteristics.qll +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointCharacteristics.qll @@ -409,7 +409,7 @@ private class CryptographicOperationFlowCharacteristic extends NotASinkCharacter CryptographicOperationFlowCharacteristic() { this = "CryptographicOperationFlow" } override predicate appliesToEndpoint(DataFlow::Node n) { - any(CryptographicOperation op).getInput() = n + any(CryptographicOperation op).getAnInput() = n } } diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index 2f3fbd9a5a0..189237b0de6 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-lib description: CodeQL libraries for the experimental ML-powered queries -version: 0.4.8 +version: 0.4.9 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index cca1fbe4f2d..eb73f66c56e 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/javascript-experimental-atm-queries description: Experimental ML-powered queries for JavaScript language: javascript -version: 0.4.8 +version: 0.4.9 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index 81e26afe0ea..428036e9c45 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.3 + +### Minor Analysis Improvements + +* Added dataflow sources for the [express-ws](https://www.npmjs.com/package/express-ws) library. + ## 0.4.2 ### Minor Analysis Improvements diff --git a/javascript/ql/lib/change-notes/2023-02-12-express-ws.md b/javascript/ql/lib/change-notes/2023-02-12-express-ws.md deleted file mode 100644 index f1e59ca7e1c..00000000000 --- a/javascript/ql/lib/change-notes/2023-02-12-express-ws.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added dataflow sources for the [express-ws](https://www.npmjs.com/package/express-ws) library. \ No newline at end of file diff --git a/javascript/ql/lib/change-notes/2023-02-14-regex-injection-process-env.md b/javascript/ql/lib/change-notes/2023-02-14-regex-injection-process-env.md new file mode 100644 index 00000000000..504b71a92b5 --- /dev/null +++ b/javascript/ql/lib/change-notes/2023-02-14-regex-injection-process-env.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `js/regex-injection` query now recognizes environment variables and command-line arguments as sources. \ No newline at end of file diff --git a/javascript/ql/lib/change-notes/2023-02-15-cryptographic-operation-getinput-deprecated.md b/javascript/ql/lib/change-notes/2023-02-15-cryptographic-operation-getinput-deprecated.md new file mode 100644 index 00000000000..246d23739c1 --- /dev/null +++ b/javascript/ql/lib/change-notes/2023-02-15-cryptographic-operation-getinput-deprecated.md @@ -0,0 +1,7 @@ +--- +category: breaking +--- +* The `CryptographicOperation` concept has been changed to use a range pattern. This is a breaking change and existing implementations of `CryptographicOperation` will need to be updated in order to compile. These implementations can be updated by: + 1. Extending `CryptographicOperation::Range` rather than `CryptographicOperation` + 2. Renaming the `getInput()` member predicate as `getAnInput()` + 3. Implementing the `BlockMode getBlockMode()` member predicate. The implementation for this can be `none()` if the operation is a hashing operation or an encryption operation using a stream cipher. diff --git a/javascript/ql/lib/change-notes/released/0.4.3.md b/javascript/ql/lib/change-notes/released/0.4.3.md new file mode 100644 index 00000000000..03f2bdd2cf1 --- /dev/null +++ b/javascript/ql/lib/change-notes/released/0.4.3.md @@ -0,0 +1,5 @@ +## 0.4.3 + +### Minor Analysis Improvements + +* Added dataflow sources for the [express-ws](https://www.npmjs.com/package/express-ws) library. diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index 94c5b17423c..1ec9c4ea5d9 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.2 +lastReleaseVersion: 0.4.3 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 8ce67542e11..16aa05fb0ff 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.4.3-dev +version: 0.4.4-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/lib/semmle/javascript/Concepts.qll b/javascript/ql/lib/semmle/javascript/Concepts.qll index e3c3f0d2357..67cf325eb11 100644 --- a/javascript/ql/lib/semmle/javascript/Concepts.qll +++ b/javascript/ql/lib/semmle/javascript/Concepts.qll @@ -110,3 +110,40 @@ abstract class PersistentWriteAccess extends DataFlow::Node { */ abstract DataFlow::Node getValue(); } + +/** + * Provides models for cryptographic things. + */ +module Cryptography { + private import semmle.javascript.internal.ConceptsShared::Cryptography as SC + + /** + * A data-flow node that is an application of a cryptographic algorithm. For example, + * encryption, decryption, signature-validation. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `CryptographicOperation::Range` instead. + */ + class CryptographicOperation extends SC::CryptographicOperation instanceof CryptographicOperation::Range { + /** + * DEPRECATED. This predicate has been renamed to `getAnInput`. + * + * To implement `CryptographicOperation`, please extend + * `CryptographicOperation::Range` and implement `getAnInput` instead of + * extending this class directly. + */ + deprecated final DataFlow::Node getInput() { result = this.getAnInput() } + } + + class EncryptionAlgorithm = SC::EncryptionAlgorithm; + + class HashingAlgorithm = SC::HashingAlgorithm; + + class PasswordHashingAlgorithm = SC::PasswordHashingAlgorithm; + + module CryptographicOperation = SC::CryptographicOperation; + + class BlockMode = SC::BlockMode; + + class CryptographicAlgorithm = SC::CryptographicAlgorithm; +} diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index 11fe4739f7b..925352cacad 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -379,7 +379,10 @@ class NullLiteral extends @null_literal, Literal { } * false * ``` */ -class BooleanLiteral extends @boolean_literal, Literal { } +class BooleanLiteral extends @boolean_literal, Literal { + /** Gets the value of this literal. */ + boolean getBoolValue() { if this.getRawValue() = "true" then result = true else result = false } +} /** * A numeric literal. diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index 515e900f277..d05045784a6 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -198,9 +198,7 @@ class PackageJson extends JsonObject { /** * Gets the main module of this package. */ - Module getMainModule() { - result = min(Module m, int prio | m.getFile() = resolveMainModule(this, prio) | m order by prio) - } + Module getMainModule() { result = this.getExportedModule(".") } /** * Gets the module exported under the given relative path. @@ -208,10 +206,12 @@ class PackageJson extends JsonObject { * The main module is considered exported under the path `"."`. */ Module getExportedModule(string relativePath) { - relativePath = "." and - result = this.getMainModule() - or - result.getFile() = MainModulePath::of(this, relativePath).resolve() + result = + min(Module m, int prio | + m.getFile() = resolveMainModule(this, prio, relativePath) + | + m order by prio + ) } /** diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 2fd172cc277..f6eabf7483c 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -62,7 +62,7 @@ File loadAsFile(Require req, int rootPriority, int priority) { */ File loadAsDirectory(Require req, int rootPriority, int priority) { exists(Folder dir | dir = req.getImportedPath().resolve(rootPriority) | - result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority) or + result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority, ".") or result = tryExtensions(dir, "index", priority - (numberOfExtensions() + 1)) ) } @@ -132,12 +132,10 @@ private File resolveMainPath(PackageJson pkg, string mainPath, int priority) { /** * Gets the main module described by `pkg` with the given `priority`. */ -File resolveMainModule(PackageJson pkg, int priority) { - exists(int subPriority, string mainPath | - result = resolveMainPath(pkg, mainPath, subPriority) and - if mainPath = "." then subPriority = priority else priority = subPriority + 1000 - ) +File resolveMainModule(PackageJson pkg, int priority, string exportPath) { + result = resolveMainPath(pkg, exportPath, priority) or + exportPath = "." and exists(Folder folder, Folder child | child = folder or child = folder.getChildContainer(getASrcFolderName()) or @@ -149,6 +147,7 @@ File resolveMainModule(PackageJson pkg, int priority) { ) or // if there is no main module, then we look for files that are explicitly included in the published package. + exportPath = "." and exists(PathExpr file | // `FilesPath` only exists if there is no main module for a given package. file = FilesPath::of(pkg) and priority = 100 // fixing the priority, because there might be multiple files in the package. diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index 64205648588..ace840613e1 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -133,7 +133,9 @@ private DataFlow::Node getAValueExportedByPackage() { DataFlow::globalVarRef("define").getACall().getAnArgument() = factory.getALocalUse() and func.getFile() = min(int j, File f | - f = NodeModule::resolveMainModule(any(PackageJson pack | exists(pack.getPackageName())), j) + f = + NodeModule::resolveMainModule(any(PackageJson pack | exists(pack.getPackageName())), j, + ".") | f order by j ) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll index f4a91834ad4..86309cb1a6c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll @@ -161,7 +161,7 @@ abstract class Configuration extends string { */ predicate isBarrier(DataFlow::Node node) { exists(BarrierGuardNode guard | - isBarrierGuardInternal(guard) and + isBarrierGuardInternal(this, guard) and barrierGuardBlocksNode(guard, node, "") ) } @@ -181,7 +181,7 @@ abstract class Configuration extends string { */ predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) { exists(BarrierGuardNode guard | - isBarrierGuardInternal(guard) and + isBarrierGuardInternal(this, guard) and barrierGuardBlocksNode(guard, node, lbl) ) or @@ -198,17 +198,6 @@ abstract class Configuration extends string { */ predicate isBarrierGuard(BarrierGuardNode guard) { none() } - /** - * Holds if `guard` is a barrier guard for this configuration, added through - * `isBarrierGuard` or `AdditionalBarrierGuardNode`. - */ - pragma[nomagic] - private predicate isBarrierGuardInternal(BarrierGuardNode guard) { - isBarrierGuard(guard) - or - guard.(AdditionalBarrierGuardNode).appliesTo(this) - } - /** * Holds if data may flow from `source` to `sink` for this configuration. */ @@ -267,6 +256,17 @@ abstract class Configuration extends string { } } +/** + * Holds if `guard` is a barrier guard for this configuration, added through + * `isBarrierGuard` or `AdditionalBarrierGuardNode`. + */ +pragma[nomagic] +private predicate isBarrierGuardInternal(Configuration cfg, BarrierGuardNode guard) { + cfg.isBarrierGuard(guard) + or + guard.(AdditionalBarrierGuardNode).appliesTo(cfg) +} + /** * A label describing the kind of information tracked by a flow configuration. * @@ -368,6 +368,8 @@ private predicate barrierGuardBlocksExpr( // Handle labelled barrier guard functions specially, to avoid negative recursion // through the non-abstract 3-argument version of blocks(). guard.(AdditionalBarrierGuardCall).internalBlocksLabel(outcome, test, label) + or + guard.(CallAgainstEqualityCheck).internalBlocksLabel(outcome, test, label) } /** @@ -1979,7 +1981,7 @@ private class BarrierGuardFunction extends Function { /** * Holds if this function applies to the flow in `cfg`. */ - predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(guard) } + predicate appliesTo(Configuration cfg) { isBarrierGuardInternal(cfg, guard) } } /** @@ -1999,6 +2001,42 @@ private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, Dat override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } } +/** + * A sanitizer where an inner sanitizer is compared against a boolean. + * E.g. (assuming `sanitizes(e)` is an existing sanitizer): + * ```javascript + * if (sanitizes(e) === true) { + * // e is sanitized + * } + * ``` + */ +private class CallAgainstEqualityCheck extends AdditionalBarrierGuardNode { + DataFlow::BarrierGuardNode prev; + boolean polarity; + + CallAgainstEqualityCheck() { + prev instanceof DataFlow::CallNode and + exists(EqualityTest test, BooleanLiteral bool | + this.asExpr() = test and + test.hasOperands(prev.asExpr(), bool) and + polarity = test.getPolarity().booleanXor(bool.getBoolValue()) + ) + } + + override predicate blocks(boolean outcome, Expr e) { + none() // handled by internalBlocksLabel + } + + predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel lbl) { + exists(boolean prevOutcome | + barrierGuardBlocksExpr(prev, prevOutcome, e, lbl) and + outcome = prevOutcome.booleanXor(polarity) + ) + } + + override predicate appliesTo(Configuration cfg) { isBarrierGuardInternal(cfg, prev) } +} + /** * A guard node for a variable in a negative condition, such as `x` in `if(!x)`. * Can be added to a `isBarrier` in a data-flow configuration to block flow through such checks. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 9cf4dcfaace..21d23f517f3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -3,22 +3,7 @@ */ import javascript -import semmle.javascript.security.CryptoAlgorithms - -/** - * An application of a cryptographic algorithm. - */ -abstract class CryptographicOperation extends DataFlow::Node { - /** - * Gets the input the algorithm is used on, e.g. the plain text input to be encrypted. - */ - abstract DataFlow::Node getInput(); - - /** - * Gets the applied algorithm. - */ - abstract CryptographicAlgorithm getAlgorithm(); -} +import semmle.javascript.Concepts::Cryptography /** * A key used in a cryptographic algorithm. @@ -52,13 +37,21 @@ class CryptographicKeyCredentialsExpr extends CredentialsNode instanceof Cryptog override string getCredentialsKind() { result = "key" } } +// Holds if `algorithm` is an `EncryptionAlgorithm` that uses a block cipher +private predicate isBlockEncryptionAlgorithm(CryptographicAlgorithm algorithm) { + algorithm instanceof EncryptionAlgorithm and + not algorithm.(EncryptionAlgorithm).isStreamCipher() +} + /** * A model of the asmCrypto library. */ private module AsmCrypto { - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; // non-functional + private string algorithmName; + private string methodName; Apply() { /* @@ -71,17 +64,31 @@ private module AsmCrypto { * ``` */ - exists(DataFlow::SourceNode asmCrypto, string algorithmName | + exists(DataFlow::SourceNode asmCrypto | asmCrypto = DataFlow::globalVarRef("asmCrypto") and algorithm.matchesName(algorithmName) and - this = asmCrypto.getAPropertyRead(algorithmName).getAMemberCall(_) and - input = this.getAnArgument() + this = asmCrypto.getAPropertyRead(algorithmName).getAMemberCall(methodName) and + input = this.getArgument(0) ) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + override BlockMode getBlockMode() { + isBlockEncryptionAlgorithm(this.getAlgorithm()) and + result.matchesString(algorithmName) + } + + DataFlow::Node getKey() { + methodName = ["encrypt", "decrypt"] and + result = super.getArgument(1) + } + } + + private class Key extends CryptographicKey { + Key() { this = any(Apply apply).getKey() } } } @@ -93,7 +100,7 @@ private module BrowserIdCrypto { Key() { this = any(Apply apply).getKey() } } - private class Apply extends CryptographicOperation instanceof DataFlow::MethodCallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::MethodCallNode { CryptographicAlgorithm algorithm; // non-functional Apply() { @@ -126,10 +133,13 @@ private module BrowserIdCrypto { ) } - override DataFlow::Node getInput() { result = super.getArgument(0) } + override DataFlow::Node getAnInput() { result = super.getArgument(0) } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + // not relevant for browserid-crypto + override BlockMode getBlockMode() { none() } + DataFlow::Node getKey() { result = super.getArgument(1) } } } @@ -139,7 +149,7 @@ private module BrowserIdCrypto { */ private module NodeJSCrypto { private class InstantiatedAlgorithm extends DataFlow::CallNode { - CryptographicAlgorithm algorithm; // non-functional + private string algorithmName; InstantiatedAlgorithm() { /* @@ -158,11 +168,24 @@ private module NodeJSCrypto { exists(DataFlow::SourceNode mod | mod = DataFlow::moduleImport("crypto") and this = mod.getAMemberCall("create" + ["Hash", "Hmac", "Sign", "Cipher"]) and - algorithm.matchesName(this.getArgument(0).getStringValue()) + algorithmName = this.getArgument(0).getStringValue() ) } - CryptographicAlgorithm getAlgorithm() { result = algorithm } + CryptographicAlgorithm getAlgorithm() { result.matchesName(algorithmName) } + + private BlockMode getExplicitBlockMode() { result.matchesString(algorithmName) } + + BlockMode getBlockMode() { + isBlockEncryptionAlgorithm(this.getAlgorithm()) and + ( + if exists(this.getExplicitBlockMode()) + then result = this.getExplicitBlockMode() + else + // CBC is the default if not explicitly specified + result = "CBC" + ) + } } private class CreateKey extends CryptographicKeyCreation, DataFlow::CallNode { @@ -211,14 +234,16 @@ private module NodeJSCrypto { override predicate isSymmetricKey() { none() } } - private class Apply extends CryptographicOperation instanceof DataFlow::MethodCallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::MethodCallNode { InstantiatedAlgorithm instantiation; Apply() { this = instantiation.getAMethodCall(any(string m | m = "update" or m = "write")) } - override DataFlow::Node getInput() { result = super.getArgument(0) } + override DataFlow::Node getAnInput() { result = super.getArgument(0) } override CryptographicAlgorithm getAlgorithm() { result = instantiation.getAlgorithm() } + + override BlockMode getBlockMode() { result = instantiation.getBlockMode() } } private class Key extends CryptographicKey { @@ -252,23 +277,18 @@ private module CryptoJS { /** * Matches `CryptoJS.` and `require("crypto-js/")` */ - private DataFlow::SourceNode getAlgorithmNode(CryptographicAlgorithm algorithm) { + private API::Node getAlgorithmNode(CryptographicAlgorithm algorithm) { exists(string algorithmName | algorithm.matchesName(algorithmName) | - exists(DataFlow::SourceNode mod | mod = DataFlow::moduleImport("crypto-js") | - result = mod.getAPropertyRead(algorithmName) or - result = mod.getAPropertyRead("Hmac" + algorithmName) // they prefix Hmac + exists(API::Node mod | mod = API::moduleImport("crypto-js") | + result = mod.getMember(algorithmName) or + result = mod.getMember("Hmac" + algorithmName) // they prefix Hmac ) or - exists(DataFlow::SourceNode mod | - mod = DataFlow::moduleImport("crypto-js/" + algorithmName) and - result = mod - ) + result = API::moduleImport("crypto-js/" + algorithmName) ) } - private DataFlow::CallNode getEncryptionApplication( - DataFlow::Node input, CryptographicAlgorithm algorithm - ) { + private API::CallNode getEncryptionApplication(API::Node input, CryptographicAlgorithm algorithm) { /* * ``` * var CryptoJS = require("crypto-js"); @@ -282,13 +302,11 @@ private module CryptoJS { * Also matches where `CryptoJS.` has been replaced by `require("crypto-js/")` */ - result = getAlgorithmNode(algorithm).getAMemberCall("encrypt") and - input = result.getArgument(0) + result = getAlgorithmNode(algorithm).getMember("encrypt").getACall() and + input = result.getParameter(0) } - private DataFlow::CallNode getDirectApplication( - DataFlow::Node input, CryptographicAlgorithm algorithm - ) { + private API::CallNode getDirectApplication(API::Node input, CryptographicAlgorithm algorithm) { /* * ``` * var CryptoJS = require("crypto-js"); @@ -304,11 +322,11 @@ private module CryptoJS { */ result = getAlgorithmNode(algorithm).getACall() and - input = result.getArgument(0) + input = result.getParameter(0) } - private class Apply extends CryptographicOperation { - DataFlow::Node input; + private class Apply extends CryptographicOperation::Range instanceof API::CallNode { + API::Node input; CryptographicAlgorithm algorithm; // non-functional Apply() { @@ -316,22 +334,41 @@ private module CryptoJS { this = getDirectApplication(input, algorithm) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input.asSink() } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // e.g. CryptoJS.AES.encrypt("msg", "key", { mode: CryptoJS.mode. }) + private BlockMode getExplicitBlockMode() { + exists(string modeString | + API::moduleImport("crypto-js").getMember("mode").getMember(modeString).asSource() = + super.getParameter(2).getMember("mode").asSink() + | + result.matchesString(modeString) + ) + } + + override BlockMode getBlockMode() { + isBlockEncryptionAlgorithm(this.getAlgorithm()) and + ( + if exists(this.getExplicitBlockMode()) + then result = this.getExplicitBlockMode() + else + // CBC is the default if not explicitly specified + result = "CBC" + ) + } } private class Key extends CryptographicKey { Key() { - exists(DataFlow::SourceNode e, CryptographicAlgorithm algorithm | - e = getAlgorithmNode(algorithm) - | + exists(API::Node e, CryptographicAlgorithm algorithm | e = getAlgorithmNode(algorithm) | exists(string name | name = "encrypt" or name = "decrypt" | algorithm instanceof EncryptionAlgorithm and - this = e.getAMemberCall(name).getArgument(1) + this = e.getMember(name).getACall().getArgument(1) ) or algorithm instanceof HashingAlgorithm and @@ -374,7 +411,7 @@ private module CryptoJS { * A model of the TweetNaCl library. */ private module TweetNaCl { - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; @@ -401,9 +438,12 @@ private module TweetNaCl { ) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // No block ciphers implemented + override BlockMode getBlockMode() { none() } } } @@ -434,7 +474,7 @@ private module HashJs { ) } - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; // non-functional @@ -456,9 +496,12 @@ private module HashJs { input = super.getArgument(0) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // not relevant for hash.js + override BlockMode getBlockMode() { none() } } } @@ -478,19 +521,20 @@ private module Forge { private class KeyCipher extends Cipher { DataFlow::Node key; CryptographicAlgorithm algorithm; // non-functional + private string blockModeString; KeyCipher() { exists(DataFlow::SourceNode mod, string algorithmName | mod = getAnImportNode() and algorithm.matchesName(algorithmName) | - exists(string createName, string cipherName, string cipherPrefix, string cipherSuffix | + exists(string createName, string cipherName, string cipherPrefix | // `require('forge').cipher.createCipher("3DES-CBC").update("secret", "key");` (createName = "createCipher" or createName = "createDecipher") and this = mod.getAPropertyRead("cipher").getAMemberCall(createName) and this.getArgument(0).mayHaveStringValue(cipherName) and - cipherName = cipherPrefix + "-" + cipherSuffix and - cipherSuffix = ["CBC", "CFB", "CTR", "ECB", "GCM", "OFB"] and + cipherName = cipherPrefix + "-" + blockModeString and + blockModeString = ["CBC", "CFB", "CTR", "ECB", "GCM", "OFB"] and algorithmName = cipherPrefix and key = this.getArgument(1) ) @@ -500,7 +544,8 @@ private module Forge { createName = "createEncryptionCipher" or createName = "createDecryptionCipher" | this = mod.getAPropertyRead(algorithmName).getAMemberCall(createName) and - key = this.getArgument(0) + key = this.getArgument(0) and + blockModeString = algorithmName ) ) } @@ -508,6 +553,11 @@ private module Forge { override CryptographicAlgorithm getAlgorithm() { result = algorithm } DataFlow::Node getKey() { result = key } + + BlockMode getBlockMode() { + isBlockEncryptionAlgorithm(this.getAlgorithm()) and + result.matchesString(blockModeString) + } } private class NonKeyCipher extends Cipher { @@ -527,21 +577,22 @@ private module Forge { override CryptographicAlgorithm getAlgorithm() { result = algorithm } } - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; // non-functional + private Cipher cipher; Apply() { - exists(Cipher cipher | - this = cipher.getAMemberCall("update") and - super.getArgument(0) = input and - algorithm = cipher.getAlgorithm() - ) + this = cipher.getAMemberCall("update") and + super.getArgument(0) = input and + algorithm = cipher.getAlgorithm() } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + override BlockMode getBlockMode() { result = cipher.(KeyCipher).getBlockMode() } } private class Key extends CryptographicKey { @@ -586,7 +637,7 @@ private module Forge { * A model of the md5 library. */ private module Md5 { - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; @@ -600,9 +651,12 @@ private module Md5 { ) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // not relevant for md5 + override BlockMode getBlockMode() { none() } } } @@ -610,7 +664,7 @@ private module Md5 { * A model of the bcrypt, bcryptjs, bcrypt-nodejs libraries. */ private module Bcrypt { - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; @@ -633,9 +687,12 @@ private module Bcrypt { ) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // not relevant for bcrypt + override BlockMode getBlockMode() { none() } } } @@ -643,7 +700,7 @@ private module Bcrypt { * A model of the hasha library. */ private module Hasha { - private class Apply extends CryptographicOperation instanceof DataFlow::CallNode { + private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode { DataFlow::Node input; CryptographicAlgorithm algorithm; @@ -659,9 +716,12 @@ private module Hasha { ) } - override DataFlow::Node getInput() { result = input } + override DataFlow::Node getAnInput() { result = input } override CryptographicAlgorithm getAlgorithm() { result = algorithm } + + // not relevant for hasha + override BlockMode getBlockMode() { none() } } } diff --git a/javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll b/javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll index 2f6c8bb8b29..e86b156e204 100644 --- a/javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll +++ b/javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll @@ -45,8 +45,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ BlockMode getBlockMode() { result = super.getBlockMode() } } @@ -69,8 +73,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ abstract BlockMode getBlockMode(); } @@ -81,10 +89,21 @@ module Cryptography { * data of arbitrary length using a block encryption algorithm. */ class BlockMode extends string { - BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] } + BlockMode() { + this = + [ + "ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP", + "XTS", // https://csrc.nist.gov/publications/detail/sp/800-38e/final + "EAX" // https://en.wikipedia.org/wiki/EAX_mode + ] + } /** Holds if this block mode is considered to be insecure. */ predicate isWeak() { this = "ECB" } + + /** Holds if the given string appears to match this block mode. */ + bindingset[s] + predicate matchesString(string s) { s.toUpperCase().matches("%" + this + "%") } } } diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index 22a2d1c1eb2..79dd19dd972 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -26,6 +26,26 @@ private newtype TCryptographicAlgorithm = isWeakPasswordHashingAlgorithm(name) and isWeak = true } +/** + * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. + * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. + * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. + */ +bindingset[name] +private CryptographicAlgorithm getBestAlgorithmForName(string name) { + result = + max(CryptographicAlgorithm algorithm | + algorithm.getName() = + [ + name.toUpperCase(), // the full name + name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces + name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores + ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces + | + algorithm order by algorithm.getName().length() + ) +} + /** * A cryptographic algorithm. */ @@ -39,15 +59,11 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { abstract string getName(); /** - * Holds if the name of this algorithm matches `name` modulo case, - * white space, dashes, underscores, and anything after a dash in the name - * (to ignore modes of operation, such as CBC or ECB). + * Holds if the name of this algorithm is the most specific match for `name`. + * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. */ bindingset[name] - predicate matchesName(string name) { - [name.toUpperCase(), name.toUpperCase().regexpCapture("^(\\w+)(?:-.*)?$", 1)] - .regexpReplaceAll("[-_ ]", "") = getName() - } + predicate matchesName(string name) { this = getBestAlgorithmForName(name) } /** * Holds if this algorithm is weak. diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll index 832f811f67b..01a5b1b260b 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll @@ -41,7 +41,7 @@ module BrokenCryptoAlgorithm { WeakCryptographicOperationSink() { exists(CryptographicOperation application | application.getAlgorithm().isWeak() and - this = application.getInput() + this = application.getAnInput() ) } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index eed346d8d0b..14fbcd4f400 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -10,7 +10,10 @@ module IndirectCommandInjection { /** * A data flow source for command-injection vulnerabilities. */ - abstract class Source extends DataFlow::Node { } + abstract class Source extends DataFlow::Node { + /** Gets a description of this source. */ + string describe() { result = "command-line argument" } + } /** * A data flow sink for command-injection vulnerabilities. @@ -37,6 +40,15 @@ module IndirectCommandInjection { } } + /** + * A read of `process.env`, considered as a flow source for command injection. + */ + private class ProcessEnvAsSource extends Source { + ProcessEnvAsSource() { this = NodeJSLib::process().getAPropertyRead("env") } + + override string describe() { result = "environment variable" } + } + /** * An object containing parsed command-line arguments, considered as a flow source for command injection. */ diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll index 1697d55fe0b..8901be9962f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll @@ -47,7 +47,7 @@ module InsufficientPasswordHash { application.getAlgorithm().isWeak() or not application.getAlgorithm() instanceof PasswordHashingAlgorithm | - this = application.getInput() + this = application.getAnInput() ) } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll index ab9f3d90e02..6f2499c7fe4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll @@ -10,7 +10,10 @@ module RegExpInjection { /** * A data flow source for untrusted user input used to construct regular expressions. */ - abstract class Source extends DataFlow::Node { } + abstract class Source extends DataFlow::Node { + /** Gets a description of this source. */ + string describe() { result = "user-provided value" } + } /** * A data flow sink for untrusted user input used to construct regular expressions. @@ -30,6 +33,16 @@ module RegExpInjection { RemoteFlowSourceAsSource() { not this instanceof ClientSideRemoteFlowSource } } + private import IndirectCommandInjectionCustomizations + + /** + * A read of `process.env`, `process.argv`, and similar, considered as a flow source for regular + * expression injection. + */ + class ArgvAsSource extends Source instanceof IndirectCommandInjection::Source { + override string describe() { result = IndirectCommandInjection::Source.super.describe() } + } + /** * The source string of a regular expression. */ diff --git a/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll b/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll index a234ba2cc1f..8bb63d97876 100644 --- a/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll +++ b/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll @@ -14,8 +14,20 @@ predicate isStrongHashingAlgorithm(string name) { name = [ + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 + // and https://www.blake2.net/ + "BLAKE2", "BLAKE2B", "BLAKE2S", + // see https://github.com/BLAKE3-team/BLAKE3 + "BLAKE3", + // "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512" + "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 + "SHAKE128", "SHAKE256", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 + "SM3", + // see https://security.stackexchange.com/a/216297 + "WHIRLPOOL", ] } diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index 192e7caf996..7eb1ebe12bd 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +No user-facing changes. + ## 0.5.2 No user-facing changes. diff --git a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql index 7520a95ed9c..34f89023441 100644 --- a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql +++ b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql @@ -25,4 +25,4 @@ where then cfg.isSinkWithHighlight(sink.getNode(), highlight) else highlight = sink.getNode() select highlight, source, sink, "This command depends on an unsanitized $@.", source.getNode(), - "command-line argument" + source.getNode().(Source).describe() diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql index 8da2080d167..5b679cf1dcf 100644 --- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql +++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql @@ -20,4 +20,4 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", - source.getNode(), "user-provided value" + source.getNode(), source.getNode().(Source).describe() diff --git a/javascript/ql/src/change-notes/released/0.5.3.md b/javascript/ql/src/change-notes/released/0.5.3.md new file mode 100644 index 00000000000..e97503053f0 --- /dev/null +++ b/javascript/ql/src/change-notes/released/0.5.3.md @@ -0,0 +1,3 @@ +## 0.5.3 + +No user-facing changes. diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 25edf011032..0fa78fbcee3 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.5.3-dev +version: 0.5.4-dev groups: - javascript - queries diff --git a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicKey.expected b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicKey.expected index 4be374d96ae..1b714e688df 100644 --- a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicKey.expected +++ b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicKey.expected @@ -1,10 +1,12 @@ -| tst.js:5:26:5:42 | keypair.secretKey | -| tst.js:19:42:19:51 | 'a secret' | -| tst.js:29:36:29:51 | 'secret key 123' | -| tst.js:32:26:32:30 | "Key" | -| tst.js:35:30:35:34 | "Key" | -| tst.js:37:48:37:63 | 'secret key 123' | -| tst.js:39:38:39:42 | "Key" | -| tst.js:57:45:57:47 | key | -| tst.js:59:50:59:52 | key | -| tst.js:73:32:73:39 | "secret" | +| tst.js:3:34:3:36 | key | +| tst.js:7:26:7:42 | keypair.secretKey | +| tst.js:21:42:21:51 | 'a secret' | +| tst.js:36:36:36:51 | 'secret key 123' | +| tst.js:39:26:39:30 | "Key" | +| tst.js:42:30:42:34 | "Key" | +| tst.js:44:48:44:63 | 'secret key 123' | +| tst.js:46:38:46:42 | "Key" | +| tst.js:50:29:50:33 | "key" | +| tst.js:68:45:68:47 | key | +| tst.js:70:50:70:52 | key | +| tst.js:84:32:84:39 | "secret" | diff --git a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.expected b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.expected index 09134c235bc..0844cb2c577 100644 --- a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.expected +++ b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.expected @@ -1,31 +1,35 @@ -| tst.js:1:1:1:27 | asmCryp ... (input) | SHA256 | tst.js:1:22:1:26 | input | -| tst.js:5:5:5:43 | jwcrypt ... retKey) | DSA | tst.js:5:19:5:23 | input | -| tst.js:10:18:10:55 | cipher. ... 'hex') | AES192 | tst.js:10:32:10:39 | 'input1' | -| tst.js:11:18:11:54 | cipher. ... 'hex') | AES192 | tst.js:11:31:11:38 | 'input2' | -| tst.js:15:1:15:21 | hash.up ... nput1') | SHA256 | tst.js:15:13:15:20 | 'input1' | -| tst.js:16:1:16:20 | hash.write('input2') | SHA256 | tst.js:16:12:16:19 | 'input2' | -| tst.js:20:1:20:21 | hmac.up ... nput1') | SHA256 | tst.js:20:13:20:20 | 'input1' | -| tst.js:21:1:21:20 | hmac.write('input2') | SHA256 | tst.js:21:12:21:19 | 'input2' | -| tst.js:25:1:25:21 | sign.up ... nput1') | SHA256 | tst.js:25:13:25:20 | 'input1' | -| tst.js:26:1:26:20 | sign.write('input2') | SHA256 | tst.js:26:12:26:19 | 'input2' | -| tst.js:29:1:29:52 | CryptoJ ... y 123') | AES | tst.js:29:22:29:33 | 'my message' | -| tst.js:32:1:32:31 | CryptoJ ... "Key") | SHA1 | tst.js:32:15:32:23 | "Message" | -| tst.js:35:1:35:35 | CryptoJ ... "Key") | SHA1 | tst.js:35:19:35:27 | "Message" | -| tst.js:37:1:37:64 | require ... y 123') | AES | tst.js:37:34:37:45 | 'my message' | -| tst.js:39:1:39:43 | require ... "Key") | SHA1 | tst.js:39:27:39:35 | "Message" | -| tst.js:41:1:41:34 | require ... ssage') | ED25519 | tst.js:41:22:41:33 | 'my message' | -| tst.js:43:1:43:34 | require ... ssage') | SHA512 | tst.js:43:22:43:33 | 'my message' | -| tst.js:45:1:45:39 | require ... ssage') | ED25519 | tst.js:45:27:45:38 | 'my message' | -| tst.js:47:1:47:39 | require ... ssage') | SHA512 | tst.js:47:27:47:38 | 'my message' | -| tst.js:49:1:49:41 | require ... ('abc') | SHA256 | tst.js:49:36:49:40 | 'abc' | -| tst.js:51:1:51:51 | require ... ('abc') | SHA512 | tst.js:51:46:51:50 | 'abc' | -| tst.js:53:1:53:86 | require ... y dog') | MD5 | tst.js:53:41:53:85 | 'The qu ... zy dog' | -| tst.js:55:1:55:91 | require ... y dog') | MD5 | tst.js:55:46:55:90 | 'The qu ... zy dog' | -| tst.js:57:1:57:65 | require ... ecret") | RC2 | tst.js:57:57:57:64 | "secret" | -| tst.js:59:1:59:70 | require ... ecret") | 3DES | tst.js:59:62:59:69 | "secret" | -| tst.js:61:1:61:25 | require ... ssage") | MD5 | tst.js:61:16:61:24 | "message" | -| tst.js:63:1:63:32 | require ... ssword) | BCRYPT | tst.js:63:24:63:31 | password | -| tst.js:65:1:65:36 | require ... ssword) | BCRYPT | tst.js:65:28:65:35 | password | -| tst.js:67:1:67:34 | require ... ssword) | BCRYPT | tst.js:67:26:67:33 | password | -| tst.js:69:1:69:39 | require ... ssword) | BCRYPT | tst.js:69:31:69:38 | password | -| tst.js:71:1:71:49 | require ... md5" }) | MD5 | tst.js:71:18:71:26 | 'unicorn' | +| tst.js:1:1:1:27 | asmCryp ... (input) | SHA256 | tst.js:1:22:1:26 | input | | +| tst.js:3:1:3:41 | asmCryp ... ey, iv) | AES | tst.js:3:27:3:31 | input | OFB | +| tst.js:7:5:7:43 | jwcrypt ... retKey) | DSA | tst.js:7:19:7:23 | input | | +| tst.js:12:18:12:55 | cipher. ... 'hex') | AES192 | tst.js:12:32:12:39 | 'input1' | CBC | +| tst.js:13:18:13:54 | cipher. ... 'hex') | AES192 | tst.js:13:31:13:38 | 'input2' | CBC | +| tst.js:17:1:17:21 | hash.up ... nput1') | SHA256 | tst.js:17:13:17:20 | 'input1' | | +| tst.js:18:1:18:20 | hash.write('input2') | SHA256 | tst.js:18:12:18:19 | 'input2' | | +| tst.js:22:1:22:21 | hmac.up ... nput1') | SHA256 | tst.js:22:13:22:20 | 'input1' | | +| tst.js:23:1:23:20 | hmac.write('input2') | SHA256 | tst.js:23:12:23:19 | 'input2' | | +| tst.js:27:1:27:21 | sign.up ... nput1') | SHA256 | tst.js:27:13:27:20 | 'input1' | | +| tst.js:28:1:28:20 | sign.write('input2') | SHA256 | tst.js:28:12:28:19 | 'input2' | | +| tst.js:32:1:32:38 | cipher. ... 'hex') | AES | tst.js:32:15:32:22 | 'input1' | ECB | +| tst.js:33:1:33:37 | cipher. ... 'hex') | AES | tst.js:33:14:33:21 | 'input2' | ECB | +| tst.js:36:1:36:52 | CryptoJ ... y 123') | AES | tst.js:36:22:36:33 | 'my message' | CBC | +| tst.js:39:1:39:31 | CryptoJ ... "Key") | SHA1 | tst.js:39:15:39:23 | "Message" | | +| tst.js:42:1:42:35 | CryptoJ ... "Key") | SHA1 | tst.js:42:19:42:27 | "Message" | | +| tst.js:44:1:44:64 | require ... y 123') | AES | tst.js:44:34:44:45 | 'my message' | CBC | +| tst.js:46:1:46:43 | require ... "Key") | SHA1 | tst.js:46:27:46:35 | "Message" | | +| tst.js:50:1:50:40 | CryptoJ ... , opts) | AES | tst.js:50:22:50:26 | "msg" | CFB | +| tst.js:52:1:52:34 | require ... ssage') | ED25519 | tst.js:52:22:52:33 | 'my message' | | +| tst.js:54:1:54:34 | require ... ssage') | SHA512 | tst.js:54:22:54:33 | 'my message' | | +| tst.js:56:1:56:39 | require ... ssage') | ED25519 | tst.js:56:27:56:38 | 'my message' | | +| tst.js:58:1:58:39 | require ... ssage') | SHA512 | tst.js:58:27:58:38 | 'my message' | | +| tst.js:60:1:60:41 | require ... ('abc') | SHA256 | tst.js:60:36:60:40 | 'abc' | | +| tst.js:62:1:62:51 | require ... ('abc') | SHA512 | tst.js:62:46:62:50 | 'abc' | | +| tst.js:64:1:64:86 | require ... y dog') | MD5 | tst.js:64:41:64:85 | 'The qu ... zy dog' | | +| tst.js:66:1:66:91 | require ... y dog') | MD5 | tst.js:66:46:66:90 | 'The qu ... zy dog' | | +| tst.js:68:1:68:65 | require ... ecret") | RC2 | tst.js:68:57:68:64 | "secret" | | +| tst.js:70:1:70:70 | require ... ecret") | 3DES | tst.js:70:62:70:69 | "secret" | CBC | +| tst.js:72:1:72:25 | require ... ssage") | MD5 | tst.js:72:16:72:24 | "message" | | +| tst.js:74:1:74:32 | require ... ssword) | BCRYPT | tst.js:74:24:74:31 | password | | +| tst.js:76:1:76:36 | require ... ssword) | BCRYPT | tst.js:76:28:76:35 | password | | +| tst.js:78:1:78:34 | require ... ssword) | BCRYPT | tst.js:78:26:78:33 | password | | +| tst.js:80:1:80:39 | require ... ssword) | BCRYPT | tst.js:80:31:80:38 | password | | +| tst.js:82:1:82:49 | require ... md5" }) | MD5 | tst.js:82:18:82:26 | 'unicorn' | | diff --git a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.ql b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.ql index d085113b9c7..33b56f278a0 100644 --- a/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.ql +++ b/javascript/ql/test/library-tests/CryptoLibraries/CryptographicOperation.ql @@ -1,4 +1,16 @@ import javascript +string getBlockMode(CryptographicOperation operation) { + if + operation.getAlgorithm() instanceof EncryptionAlgorithm and + not operation.getAlgorithm().(EncryptionAlgorithm).isStreamCipher() + then + if exists(operation.getBlockMode()) + then result = operation.getBlockMode() + else result = "" + else result = "" +} + from CryptographicOperation operation -select operation, operation.getAlgorithm().getName(), operation.getInput() +select operation, operation.getAlgorithm().getName(), operation.getAnInput(), + getBlockMode(operation) diff --git a/javascript/ql/test/library-tests/CryptoLibraries/tst.js b/javascript/ql/test/library-tests/CryptoLibraries/tst.js index 5efd150bd16..97f373d805b 100644 --- a/javascript/ql/test/library-tests/CryptoLibraries/tst.js +++ b/javascript/ql/test/library-tests/CryptoLibraries/tst.js @@ -1,5 +1,7 @@ asmCrypto.SHA256.hex(input); +asmCrypto.AES_OFB.encrypt(input, key, iv) + var jwcrypto = require("browserid-crypto"); jwcrypto.generateKeypair({algorithm: 'DSA'}, function(err, keypair) { jwcrypto.sign(input, keypair.secretKey); @@ -25,6 +27,11 @@ const sign = crypto.createSign('SHA256'); sign.update('input1'); sign.write('input2'); +var crypto = require('crypto'); +var cipher = crypto.createCipher('aes-192-ecb', 'a password'); +cipher.update('input1', 'utf8', 'hex'); +cipher.write('input2', 'utf8', 'hex'); + var CryptoJS = require("crypto-js"); CryptoJS.AES.encrypt('my message', 'secret key 123'); @@ -38,6 +45,10 @@ require("crypto-js/aes").encrypt('my message', 'secret key 123'); require("crypto-js/sha1")("Message", "Key"); +var CryptoJS = require("crypto-js"); +var opts = { mode: CryptoJS.mode.CFB } +CryptoJS.AES.encrypt("msg", "key", opts) + require("nacl").sign('my message'); require("nacl").hash('my message'); diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected index 2b7a9927826..b4022c8550c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected @@ -301,6 +301,24 @@ nodes | lib/lib.js:562:26:562:29 | name | | lib/lib.js:566:26:566:29 | name | | lib/lib.js:566:26:566:29 | name | +| lib/lib.js:572:41:572:44 | name | +| lib/lib.js:572:41:572:44 | name | +| lib/lib.js:573:22:573:25 | name | +| lib/lib.js:573:22:573:25 | name | +| lib/lib.js:579:25:579:28 | name | +| lib/lib.js:579:25:579:28 | name | +| lib/lib.js:590:29:590:32 | name | +| lib/lib.js:590:29:590:32 | name | +| lib/lib.js:593:25:593:28 | name | +| lib/lib.js:593:25:593:28 | name | +| lib/lib.js:608:42:608:45 | name | +| lib/lib.js:608:42:608:45 | name | +| lib/lib.js:609:22:609:25 | name | +| lib/lib.js:609:22:609:25 | name | +| lib/lib.js:626:29:626:32 | name | +| lib/lib.js:626:29:626:32 | name | +| lib/lib.js:629:25:629:28 | name | +| lib/lib.js:629:25:629:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -703,6 +721,34 @@ edges | lib/lib.js:558:41:558:44 | name | lib/lib.js:566:26:566:29 | name | | lib/lib.js:558:41:558:44 | name | lib/lib.js:566:26:566:29 | name | | lib/lib.js:558:41:558:44 | name | lib/lib.js:566:26:566:29 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:573:22:573:25 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:573:22:573:25 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:573:22:573:25 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:573:22:573:25 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:579:25:579:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:579:25:579:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:579:25:579:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:579:25:579:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:590:29:590:32 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:590:29:590:32 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:590:29:590:32 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:590:29:590:32 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:593:25:593:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:593:25:593:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:593:25:593:28 | name | +| lib/lib.js:572:41:572:44 | name | lib/lib.js:593:25:593:28 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | +| lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -826,6 +872,13 @@ edges | lib/lib.js:560:14:560:29 | "rm -rf " + name | lib/lib.js:558:41:558:44 | name | lib/lib.js:560:26:560:29 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:558:41:558:44 | name | library input | lib/lib.js:560:9:560:30 | exec("r ... + name) | shell command | | lib/lib.js:562:14:562:29 | "rm -rf " + name | lib/lib.js:558:41:558:44 | name | lib/lib.js:562:26:562:29 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:558:41:558:44 | name | library input | lib/lib.js:562:9:562:30 | exec("r ... + name) | shell command | | lib/lib.js:566:14:566:29 | "rm -rf " + name | lib/lib.js:558:41:558:44 | name | lib/lib.js:566:26:566:29 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:558:41:558:44 | name | library input | lib/lib.js:566:9:566:30 | exec("r ... + name) | shell command | +| lib/lib.js:573:10:573:25 | "rm -rf " + name | lib/lib.js:572:41:572:44 | name | lib/lib.js:573:22:573:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:572:41:572:44 | name | library input | lib/lib.js:573:2:573:26 | cp.exec ... + name) | shell command | +| lib/lib.js:579:13:579:28 | "rm -rf " + name | lib/lib.js:572:41:572:44 | name | lib/lib.js:579:25:579:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:572:41:572:44 | name | library input | lib/lib.js:579:5:579:29 | cp.exec ... + name) | shell command | +| lib/lib.js:590:17:590:32 | "rm -rf " + name | lib/lib.js:572:41:572:44 | name | lib/lib.js:590:29:590:32 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:572:41:572:44 | name | library input | lib/lib.js:590:9:590:33 | cp.exec ... + name) | shell command | +| lib/lib.js:593:13:593:28 | "rm -rf " + name | lib/lib.js:572:41:572:44 | name | lib/lib.js:593:25:593:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:572:41:572:44 | name | library input | lib/lib.js:593:5:593:29 | cp.exec ... + name) | shell command | +| lib/lib.js:609:10:609:25 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:609:2:609:26 | cp.exec ... + name) | shell command | +| lib/lib.js:626:17:626:32 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:626:9:626:33 | cp.exec ... + name) | shell command | +| lib/lib.js:629:13:629:28 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:629:5:629:29 | cp.exec ... + name) | shell command | | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command | | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4:26 | cp.exec ... + name) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js index eb528e59450..504de998c1c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js @@ -568,3 +568,63 @@ module.exports.badSanitizer = function (name) { exec("rm -rf " + name); // OK } } + +module.exports.safeWithBool = function (name) { + cp.exec("rm -rf " + name); // NOT OK + + if (isSafeName(name)) { + cp.exec("rm -rf " + name); // OK + } + + cp.exec("rm -rf " + name); // NOT OK + + if (isSafeName(name) === true) { + cp.exec("rm -rf " + name); // OK + } + + if (isSafeName(name) !== false) { + cp.exec("rm -rf " + name); // OK + } + + if (isSafeName(name) == false) { + cp.exec("rm -rf " + name); // NOT OK + } + + cp.exec("rm -rf " + name); // NOT OK +} + +function indirectThing(name) { + return isSafeName(name); +} + +function indirectThing2(name) { + return isSafeName(name) === true; +} + +function moreIndirect(name) { + return indirectThing2(name) !== false; +} + +module.exports.veryIndeirect = function (name) { + cp.exec("rm -rf " + name); // NOT OK + + if (indirectThing(name)) { + cp.exec("rm -rf " + name); // OK + } + + if (indirectThing2(name)) { + cp.exec("rm -rf " + name); // OK + } + + if (moreIndirect(name)) { + cp.exec("rm -rf " + name); // OK + } + + if (moreIndirect(name) !== false) { + cp.exec("rm -rf " + name); // OK + } else { + cp.exec("rm -rf " + name); // NOT OK + } + + cp.exec("rm -rf " + name); // NOT OK +} diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected index 0dea7f25189..726fb896435 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/UnsafeHtmlConstruction.expected @@ -12,6 +12,10 @@ nodes | lib2/index.ts:1:28:1:28 | s | | lib2/index.ts:2:29:2:29 | s | | lib2/index.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | +| lib2/src/MyNode.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:2:29:2:29 | s | | lib/src/MyNode.ts:1:28:1:28 | s | | lib/src/MyNode.ts:1:28:1:28 | s | | lib/src/MyNode.ts:2:29:2:29 | s | @@ -108,6 +112,10 @@ edges | lib2/index.ts:1:28:1:28 | s | lib2/index.ts:2:29:2:29 | s | | lib2/index.ts:1:28:1:28 | s | lib2/index.ts:2:29:2:29 | s | | lib2/index.ts:1:28:1:28 | s | lib2/index.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | lib2/src/MyNode.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | lib2/src/MyNode.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | lib2/src/MyNode.ts:2:29:2:29 | s | +| lib2/src/MyNode.ts:1:28:1:28 | s | lib2/src/MyNode.ts:2:29:2:29 | s | | lib/src/MyNode.ts:1:28:1:28 | s | lib/src/MyNode.ts:2:29:2:29 | s | | lib/src/MyNode.ts:1:28:1:28 | s | lib/src/MyNode.ts:2:29:2:29 | s | | lib/src/MyNode.ts:1:28:1:28 | s | lib/src/MyNode.ts:2:29:2:29 | s | @@ -200,6 +208,7 @@ edges | jquery-plugin.js:12:31:12:41 | options.foo | jquery-plugin.js:11:34:11:40 | options | jquery-plugin.js:12:31:12:41 | options.foo | This HTML construction which depends on $@ might later allow $@. | jquery-plugin.js:11:34:11:40 | options | library input | jquery-plugin.js:12:20:12:53 | " ... /span>" | cross-site scripting | | jquery-plugin.js:14:31:14:35 | stuff | jquery-plugin.js:11:27:11:31 | stuff | jquery-plugin.js:14:31:14:35 | stuff | This HTML construction which depends on $@ might later allow $@. | jquery-plugin.js:11:27:11:31 | stuff | library input | jquery-plugin.js:14:20:14:47 | " ... /span>" | cross-site scripting | | lib2/index.ts:2:29:2:29 | s | lib2/index.ts:1:28:1:28 | s | lib2/index.ts:2:29:2:29 | s | This HTML construction which depends on $@ might later allow $@. | lib2/index.ts:1:28:1:28 | s | library input | lib2/index.ts:3:49:3:52 | html | cross-site scripting | +| lib2/src/MyNode.ts:2:29:2:29 | s | lib2/src/MyNode.ts:1:28:1:28 | s | lib2/src/MyNode.ts:2:29:2:29 | s | This HTML construction which depends on $@ might later allow $@. | lib2/src/MyNode.ts:1:28:1:28 | s | library input | lib2/src/MyNode.ts:3:49:3:52 | html | cross-site scripting | | lib/src/MyNode.ts:2:29:2:29 | s | lib/src/MyNode.ts:1:28:1:28 | s | lib/src/MyNode.ts:2:29:2:29 | s | This HTML construction which depends on $@ might later allow $@. | lib/src/MyNode.ts:1:28:1:28 | s | library input | lib/src/MyNode.ts:3:49:3:52 | html | cross-site scripting | | main.js:2:29:2:29 | s | main.js:1:55:1:55 | s | main.js:2:29:2:29 | s | This HTML construction which depends on $@ might later allow $@. | main.js:1:55:1:55 | s | library input | main.js:3:49:3:52 | html | cross-site scripting | | main.js:7:49:7:49 | s | main.js:6:49:6:49 | s | main.js:7:49:7:49 | s | This XML parsing which depends on $@ might later allow $@. | main.js:6:49:6:49 | s | library input | main.js:8:48:8:66 | doc.documentElement | cross-site scripting | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/package.json b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/package.json index 8c1cbff3c1d..5c0fb2e5b7c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/package.json +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/package.json @@ -1,6 +1,6 @@ { "name": "my-unsafe-library", - "main": "./foobar.js", + "main": "./index.ts", "exports": { "./MyNode": { "require": "./lib/MyNode.cjs", diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/src/MyNode.ts b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/src/MyNode.ts index 35908c88f16..e28325ce0cf 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/src/MyNode.ts +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeHtmlConstruction/lib2/src/MyNode.ts @@ -1,4 +1,4 @@ export function trivialXss(s: string) { - const html = "" + s + ""; // OK - this file is not recognized as a main file. + const html = "" + s + ""; // NOT OK - this file is not recognized as a main file. document.querySelector("#html").innerHTML = html; } \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/koarouter.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/koarouter.js new file mode 100644 index 00000000000..bc21bb58f4a --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/koarouter.js @@ -0,0 +1,23 @@ +const Router = require('koa-router') +const {Sequelize} = require("sequelize"); + +new Router().get("/hello", (ctx) => { + const { version } = ctx.query; + + if (version && validVersion(version) === false) { + throw new Error(`invalid version ${version}`); + } + + const conditions = ['1']; + + if (version) { + conditions.push(`version = ${version}`) + } + + new Sequelize().query(`SELECT * FROM t WHERE ${conditions.join(' and ')}`, null); // OK +}); + +function validVersion(version) { + const pattern = /^[a-zA-Z0-9]+$/; + return pattern.test(version); +} diff --git a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected index 7d24e94a590..693ef9e5e95 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected @@ -56,6 +56,16 @@ nodes | RegExpInjection.js:87:14:87:55 | "^.*\\.( ... + ")$" | | RegExpInjection.js:87:25:87:29 | input | | RegExpInjection.js:87:25:87:48 | input.r ... g, "\|") | +| RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | +| RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | +| RegExpInjection.js:91:20:91:30 | process.env | +| RegExpInjection.js:91:20:91:30 | process.env | +| RegExpInjection.js:91:20:91:35 | process.env.HOME | +| RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | +| RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | +| RegExpInjection.js:93:20:93:31 | process.argv | +| RegExpInjection.js:93:20:93:31 | process.argv | +| RegExpInjection.js:93:20:93:34 | process.argv[1] | | tst.js:1:46:1:46 | e | | tst.js:1:46:1:46 | e | | tst.js:2:9:2:21 | data | @@ -121,6 +131,14 @@ edges | RegExpInjection.js:87:25:87:29 | input | RegExpInjection.js:87:25:87:48 | input.r ... g, "\|") | | RegExpInjection.js:87:25:87:48 | input.r ... g, "\|") | RegExpInjection.js:87:14:87:55 | "^.*\\.( ... + ")$" | | RegExpInjection.js:87:25:87:48 | input.r ... g, "\|") | RegExpInjection.js:87:14:87:55 | "^.*\\.( ... + ")$" | +| RegExpInjection.js:91:20:91:30 | process.env | RegExpInjection.js:91:20:91:35 | process.env.HOME | +| RegExpInjection.js:91:20:91:30 | process.env | RegExpInjection.js:91:20:91:35 | process.env.HOME | +| RegExpInjection.js:91:20:91:35 | process.env.HOME | RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | +| RegExpInjection.js:91:20:91:35 | process.env.HOME | RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | +| RegExpInjection.js:93:20:93:31 | process.argv | RegExpInjection.js:93:20:93:34 | process.argv[1] | +| RegExpInjection.js:93:20:93:31 | process.argv | RegExpInjection.js:93:20:93:34 | process.argv[1] | +| RegExpInjection.js:93:20:93:34 | process.argv[1] | RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | +| RegExpInjection.js:93:20:93:34 | process.argv[1] | RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | | tst.js:1:46:1:46 | e | tst.js:2:16:2:16 | e | | tst.js:1:46:1:46 | e | tst.js:2:16:2:16 | e | | tst.js:2:9:2:21 | data | tst.js:3:21:3:24 | data | @@ -146,4 +164,6 @@ edges | RegExpInjection.js:54:14:54:52 | key.spl ... in("-") | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:54:14:54:52 | key.spl ... in("-") | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value | | RegExpInjection.js:64:14:64:18 | input | RegExpInjection.js:60:39:60:56 | req.param("input") | RegExpInjection.js:64:14:64:18 | input | This regular expression is constructed from a $@. | RegExpInjection.js:60:39:60:56 | req.param("input") | user-provided value | | RegExpInjection.js:87:14:87:55 | "^.*\\.( ... + ")$" | RegExpInjection.js:82:15:82:32 | req.param("input") | RegExpInjection.js:87:14:87:55 | "^.*\\.( ... + ")$" | This regular expression is constructed from a $@. | RegExpInjection.js:82:15:82:32 | req.param("input") | user-provided value | +| RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | RegExpInjection.js:91:20:91:30 | process.env | RegExpInjection.js:91:16:91:50 | `^${pro ... r.app$` | This regular expression is constructed from a $@. | RegExpInjection.js:91:20:91:30 | process.env | environment variable | +| RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | RegExpInjection.js:93:20:93:31 | process.argv | RegExpInjection.js:93:16:93:49 | `^${pro ... r.app$` | This regular expression is constructed from a $@. | RegExpInjection.js:93:20:93:31 | process.argv | command-line argument | | tst.js:3:16:3:35 | "^"+ data.name + "$" | tst.js:1:46:1:46 | e | tst.js:3:16:3:35 | "^"+ data.name + "$" | This regular expression is constructed from a $@. | tst.js:1:46:1:46 | e | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js index 3551a1ff72a..1f8113f7d75 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js +++ b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js @@ -86,3 +86,9 @@ app.get('/has-sanitizer', function(req, res) { new RegExp("^.*\.(" + input.replace(/,/g, "|") + ")$"); // NOT OK }); + +app.get("argv", function(req, res) { + new RegExp(`^${process.env.HOME}/Foo/bar.app$`); // NOT OK + + new RegExp(`^${process.argv[1]}/Foo/bar.app$`); // NOT OK +}); diff --git a/misc/bazel/workspace.bzl b/misc/bazel/workspace.bzl index 46426f48d5c..ef89ccfb666 100644 --- a/misc/bazel/workspace.bzl +++ b/misc/bazel/workspace.bzl @@ -33,3 +33,13 @@ def codeql_workspace(repository_name = "codeql"): "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.8.1.tar.gz", ], ) + + maybe( + repo_rule = http_archive, + name = "bazel_skylib", + sha256 = "b8a1527901774180afc798aeb28c4634bdccf19c4d98e7bdd1ce79d1fe9aaad7", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", + ], + ) diff --git a/misc/bazel/workspace_deps.bzl b/misc/bazel/workspace_deps.bzl index 987fd144fd8..674be778d78 100644 --- a/misc/bazel/workspace_deps.bzl +++ b/misc/bazel/workspace_deps.bzl @@ -1,9 +1,11 @@ load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") load("@rules_python//python:pip.bzl", "pip_install") +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") def codeql_workspace_deps(repository_name = "codeql"): pip_install( - name = "swift_codegen_deps", - requirements = "@%s//swift/codegen:requirements.txt" % repository_name, + name = "codegen_deps", + requirements = "@%s//misc/codegen:requirements.txt" % repository_name, ) + bazel_skylib_workspace() rules_pkg_dependencies() diff --git a/swift/codegen/.pep8 b/misc/codegen/.pep8 similarity index 100% rename from swift/codegen/.pep8 rename to misc/codegen/.pep8 diff --git a/misc/codegen/BUILD.bazel b/misc/codegen/BUILD.bazel new file mode 100644 index 00000000000..102e52fb10b --- /dev/null +++ b/misc/codegen/BUILD.bazel @@ -0,0 +1,14 @@ +load("@codegen_deps//:requirements.bzl", "requirement") + +py_binary( + name = "codegen", + srcs = ["codegen.py"], + data = [ + "//misc/codegen/templates:cpp", + "//misc/codegen/templates:trap", + ], + visibility = ["//visibility:public"], + deps = [ + "//misc/codegen/generators", + ], +) diff --git a/misc/codegen/README.md b/misc/codegen/README.md new file mode 100644 index 00000000000..2d45ac67ac2 --- /dev/null +++ b/misc/codegen/README.md @@ -0,0 +1,38 @@ +# Code generation suite + +This directory contains the code generation suite used by the Swift extractor and the QL library. This suite will use +the abstract class specification of `schema.py` to generate: + +* the `dbscheme` file (see [`dbschemegen.py`](generators/dbschemegen.py)) +* the QL generated code and when appropriate the corresponding stubs (see [`qlgen.py`](generators/qlgen.py)) +* C++ tags and trap entries (see [`trapgen.py`](generators/trapgen.py)) +* C++ structured classes (see [`cppgen.py`](generators/cppgen.py)) + +An example `schema.py` [can be found in the Swift package](../../swift/schema.py). + +## Usage + +By default `bazel run //misc/codegen -- -c your-codegen.conf` will load options from `your-codegen.conf`. See +the [Swift configuration](../../swift/codegen.conf) for an example. Calling `misc/codegen/codegen.py` directly (provided +you installed dependencies via `pip3 install -r misc/codegen/requirements.txt`) will use a file named `codegen.conf` +contained in an ancestor directory if any exists. + +See `bazel run //misc/codegen -- --help` for a list of all options. In particular `--generate` can be used with a comma +separated list to select what to generate (choosing among `dbscheme`, `ql`, `trap` and `cpp`). + +## Implementation notes + +The suite uses [mustache templating](https://mustache.github.io/) for generation. Templates are +in [the `templates` directory](templates), prefixed with the generation target they are used for. + +Rather than passing dictionaries to the templating engine, python dataclasses are used as defined +in [the `lib` directory](lib). For each of the four generation targets the entry point for the implementation is +specified as the `generate` function in the modules within [the `generators` directory](generators). + +Finally, [`codegen.py`](codegen.py) is the driver script gluing everything together and specifying the command line +options. + +Unit tests are in [the `test` directory](test) and can be run via `bazel test //misc/codegen/test`. + +For more details about each specific generation target, please refer to the module docstrings +in [the `generators` directory](generators). diff --git a/misc/codegen/codegen.py b/misc/codegen/codegen.py new file mode 100755 index 00000000000..11f6fbe4a7b --- /dev/null +++ b/misc/codegen/codegen.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +""" Driver script to run all code generation """ + +import argparse +import logging +import os +import sys +import pathlib +import typing +import shlex + +if 'BUILD_WORKSPACE_DIRECTORY' not in os.environ: + # we are not running with `bazel run`, set up module search path + _repo_root = pathlib.Path(__file__).resolve().parents[2] + sys.path.append(str(_repo_root)) + +from misc.codegen.lib import render, paths +from misc.codegen.generators import generate + + +def _parse_args() -> argparse.Namespace: + dirs = [pathlib.Path().resolve()] + dirs.extend(dirs[0].parents) + for dir in dirs: + conf = dir / "codegen.conf" + if conf.exists(): + break + else: + conf = None + + p = argparse.ArgumentParser(description="Code generation suite") + p.add_argument("--generate", type=lambda x: x.split(","), + help="specify what targets to generate as a comma separated list, choosing among dbscheme, ql, trap " + "and cpp") + p.add_argument("--verbose", "-v", action="store_true", help="print more information") + p.add_argument("--quiet", "-q", action="store_true", help="only print errors") + p.add_argument("--configuration-file", "-c", type=_abspath, default=conf, + help="A configuration file to load options from. By default, the first codegen.conf file found by " + "going up directories from the current location. If present all paths provided in options are " + "considered relative to its directory") + p.add_argument("--root-dir", type=_abspath, + help="the directory that should be regarded as the root of the language pack codebase. Used to " + "compute QL imports and in some comments and as root for relative paths provided as options. " + "If not provided it defaults to the directory of the configuration file, if any") + path_arguments = [ + p.add_argument("--schema", default="schema.py", + help="input schema file (default %(default)s)"), + p.add_argument("--dbscheme", + help="output file for dbscheme generation, input file for trap generation"), + p.add_argument("--ql-output", + help="output directory for generated QL files"), + p.add_argument("--ql-stub-output", + help="output directory for QL stub/customization files. Defines also the " + "generated qll file importing every class file"), + p.add_argument("--ql-test-output", + help="output directory for QL generated extractor test files"), + p.add_argument("--cpp-output", + help="output directory for generated C++ files, required if trap or cpp is provided to " + "--generate"), + p.add_argument("--generated-registry", + help="registry file containing information about checked-in generated code"), + ] + p.add_argument("--script-name", + help="script name to put in header comments of generated files. By default, the path of this " + "script relative to the root directory") + p.add_argument("--trap-library", + help="path to the trap library from an include directory, required if generating C++ trap bindings"), + p.add_argument("--ql-format", action="store_true", default=True, + help="use codeql to autoformat QL files (which is the default)") + p.add_argument("--no-ql-format", action="store_false", dest="ql_format", help="do not format QL files") + p.add_argument("--codeql-binary", default="codeql", help="command to use for QL formatting (default %(default)s)") + p.add_argument("--force", "-f", action="store_true", + help="generate all files without skipping unchanged files and overwriting modified ones") + p.add_argument("--use-current-directory", action="store_true", + help="do not consider paths as relative to --root-dir or the configuration directory") + opts = p.parse_args() + if opts.configuration_file is not None: + with open(opts.configuration_file) as config: + defaults = p.parse_args(shlex.split(config.read(), comments=True)) + for flag, value in opts._get_kwargs(): + if value is None: + setattr(opts, flag, getattr(defaults, flag)) + if opts.root_dir is None: + opts.root_dir = opts.configuration_file.parent + if not opts.generate: + p.error("Nothing to do, specify --generate") + # absolutize all paths + for arg in path_arguments: + path = getattr(opts, arg.dest) + if path is not None: + setattr(opts, arg.dest, _abspath(path) if opts.use_current_directory else (opts.root_dir / path)) + if not opts.script_name: + opts.script_name = paths.exe_file.relative_to(opts.root_dir) + return opts + + +def _abspath(x: str) -> typing.Optional[pathlib.Path]: + return pathlib.Path(x).resolve() if x else None + + +def run(): + opts = _parse_args() + if opts.verbose: + log_level = logging.DEBUG + elif opts.quiet: + log_level = logging.ERROR + else: + log_level = logging.INFO + logging.basicConfig(format="{levelname} {message}", style='{', level=log_level) + for target in opts.generate: + generate(target, opts, render.Renderer(opts.script_name, opts.root_dir)) + + +if __name__ == "__main__": + run() diff --git a/misc/codegen/generators/BUILD.bazel b/misc/codegen/generators/BUILD.bazel new file mode 100644 index 00000000000..df328a7df7f --- /dev/null +++ b/misc/codegen/generators/BUILD.bazel @@ -0,0 +1,11 @@ +load("@codegen_deps//:requirements.bzl", "requirement") + +py_library( + name = "generators", + srcs = glob(["*.py"]), + visibility = ["//misc/codegen:__subpackages__"], + deps = [ + "//misc/codegen/lib", + "//misc/codegen/loaders", + ], +) diff --git a/swift/codegen/generators/__init__.py b/misc/codegen/generators/__init__.py similarity index 100% rename from swift/codegen/generators/__init__.py rename to misc/codegen/generators/__init__.py diff --git a/swift/codegen/generators/cppgen.py b/misc/codegen/generators/cppgen.py similarity index 90% rename from swift/codegen/generators/cppgen.py rename to misc/codegen/generators/cppgen.py index 16f997efacb..f6a7f8d792c 100644 --- a/swift/codegen/generators/cppgen.py +++ b/misc/codegen/generators/cppgen.py @@ -16,7 +16,8 @@ import typing import inflection -from swift.codegen.lib import cpp, schema +from misc.codegen.lib import cpp, schema +from misc.codegen.loaders import schemaloader def _get_type(t: str, add_or_none_except: typing.Optional[str] = None) -> str: @@ -90,8 +91,9 @@ class Processor: def generate(opts, renderer): assert opts.cpp_output - processor = Processor(schema.load_file(opts.schema)) + processor = Processor(schemaloader.load_file(opts.schema)) out = opts.cpp_output for dir, classes in processor.get_classes().items(): renderer.render(cpp.ClassList(classes, opts.schema, - include_parent=bool(dir)), out / dir / "TrapClasses") + include_parent=bool(dir), + trap_library=opts.trap_library), out / dir / "TrapClasses") diff --git a/swift/codegen/generators/dbschemegen.py b/misc/codegen/generators/dbschemegen.py similarity index 92% rename from swift/codegen/generators/dbschemegen.py rename to misc/codegen/generators/dbschemegen.py index 58cb40a3335..05483748db5 100755 --- a/swift/codegen/generators/dbschemegen.py +++ b/misc/codegen/generators/dbschemegen.py @@ -17,9 +17,9 @@ import typing import inflection -from swift.codegen.lib import schema -from swift.codegen.lib.dbscheme import * -from typing import Set, List +from misc.codegen.lib import schema +from misc.codegen.loaders import schemaloader +from misc.codegen.lib.dbscheme import * log = logging.getLogger(__name__) @@ -110,12 +110,12 @@ def get_declarations(data: schema.Schema): return declarations -def get_includes(data: schema.Schema, include_dir: pathlib.Path, swift_dir: pathlib.Path): +def get_includes(data: schema.Schema, include_dir: pathlib.Path, root_dir: pathlib.Path): includes = [] for inc in data.includes: inc = include_dir / inc with open(inc) as inclusion: - includes.append(SchemeInclude(src=inc.relative_to(swift_dir), data=inclusion.read())) + includes.append(SchemeInclude(src=inc.relative_to(root_dir), data=inclusion.read())) return includes @@ -123,10 +123,10 @@ def generate(opts, renderer): input = opts.schema out = opts.dbscheme - data = schema.load_file(input) + data = schemaloader.load_file(input) - dbscheme = Scheme(src=input.relative_to(opts.swift_dir), - includes=get_includes(data, include_dir=input.parent, swift_dir=opts.swift_dir), + dbscheme = Scheme(src=input.name, + includes=get_includes(data, include_dir=input.parent, root_dir=input.parent), declarations=get_declarations(data)) renderer.render(dbscheme, out) diff --git a/swift/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py similarity index 76% rename from swift/codegen/generators/qlgen.py rename to misc/codegen/generators/qlgen.py index 1d86518696a..68b3a6d7ef3 100755 --- a/swift/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -14,7 +14,7 @@ QL code generation corresponding to raw types) Moreover in the test directory for each in it will generate beneath the extractor-tests/generated// directory either - * a `MISSING_SOURCE.txt` explanation file if no `swift` source is present, or + * a `MISSING_SOURCE.txt` explanation file if no source is present, or * one `.ql` test query for all single properties and on `_.ql` test query for each optional or repeated property """ @@ -29,7 +29,8 @@ import itertools import inflection -from swift.codegen.lib import schema, ql +from misc.codegen.lib import schema, ql +from misc.codegen.loaders import schemaloader log = logging.getLogger(__name__) @@ -145,7 +146,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str = return ql.Property(**args) -def get_ql_class(cls: schema.Class): +def get_ql_class(cls: schema.Class) -> ql.Class: pragmas = {k: True for k in cls.pragmas if k.startswith("ql")} prev_child = "" properties = [] @@ -197,8 +198,8 @@ def get_ql_ipa_class(cls: schema.Class): return get_ql_ipa_class_db(cls.name) -def get_import(file: pathlib.Path, swift_dir: pathlib.Path): - stem = file.relative_to(swift_dir / "ql/lib").with_suffix("") +def get_import(file: pathlib.Path, root_dir: pathlib.Path): + stem = file.relative_to(root_dir / "ql/lib").with_suffix("") return str(stem).replace("/", ".") @@ -227,6 +228,10 @@ def format(codeql, files): log.debug(line.strip()) +def _get_path(cls: schema.Class) -> pathlib.Path: + return pathlib.Path(cls.group or "", cls.name).with_suffix(".qll") + + def _get_all_properties(cls: schema.Class, lookup: typing.Dict[str, schema.Class], already_seen: typing.Optional[typing.Set[int]] = None) -> \ typing.Iterable[typing.Tuple[schema.Class, schema.Property]]: @@ -282,6 +287,29 @@ def _should_skip_qltest(cls: schema.Class, lookup: typing.Dict[str, schema.Class cls, lookup) +def _get_stub(cls: schema.Class, base_import: str, generated_import_prefix: str) -> ql.Stub: + if isinstance(cls.ipa, schema.IpaInfo): + if cls.ipa.from_class is not None: + accessors = [ + ql.IpaUnderlyingAccessor( + argument="Entity", + type=_to_db_type(cls.ipa.from_class), + constructorparams=["result"] + ) + ] + elif cls.ipa.on_arguments is not None: + accessors = [ + ql.IpaUnderlyingAccessor( + argument=inflection.camelize(arg), + type=_to_db_type(type), + constructorparams=["result" if a == arg else "_" for a in cls.ipa.on_arguments] + ) for arg, type in cls.ipa.on_arguments.items() + ] + else: + accessors = [] + return ql.Stub(name=cls.name, base_import=base_import, import_prefix=generated_import_prefix, ipa_accessors=accessors) + + def generate(opts, renderer): input = opts.schema out = opts.ql_output @@ -292,12 +320,13 @@ def generate(opts, renderer): generated = {q for q in out.rglob("*.qll")} generated.add(include_file) - generated.update(q for q in test_out.rglob("*.ql")) - generated.update(q for q in test_out.rglob(missing_test_source_filename)) + if test_out: + generated.update(q for q in test_out.rglob("*.ql")) + generated.update(q for q in test_out.rglob(missing_test_source_filename)) stubs = {q for q in stub_out.rglob("*.qll")} - data = schema.load_file(input) + data = schemaloader.load_file(input) classes = {name: get_ql_class(cls) for name, cls in data.classes.items()} if not classes: @@ -307,6 +336,7 @@ def generate(opts, renderer): raise RootElementHasChildren(root) imports = {} + generated_import_prefix = get_import(out, opts.root_dir) with renderer.manage(generated=generated, stubs=stubs, registry=opts.generated_registry, force=opts.force) as renderer: @@ -316,48 +346,57 @@ def generate(opts, renderer): classes_by_dir_and_name = sorted(classes.values(), key=lambda cls: (cls.dir, cls.name)) for c in classes_by_dir_and_name: - imports[c.name] = get_import(stub_out / c.path, opts.swift_dir) + imports[c.name] = get_import(stub_out / c.path, opts.root_dir) for c in classes.values(): qll = out / c.path.with_suffix(".qll") c.imports = [imports[t] for t in get_classes_used_by(c)] + c.import_prefix = generated_import_prefix renderer.render(c, qll) - stub_file = stub_out / c.path.with_suffix(".qll") + + for c in data.classes.values(): + path = _get_path(c) + stub_file = stub_out / path if not renderer.is_customized_stub(stub_file): - stub = ql.Stub(name=c.name, base_import=get_import(qll, opts.swift_dir)) - renderer.render(stub, stub_file) + base_import = get_import(out / path, opts.root_dir) + renderer.render(_get_stub(c, base_import, generated_import_prefix), stub_file) # for example path/to/elements -> path/to/elements.qll renderer.render(ql.ImportList([i for name, i in imports.items() if not classes[name].ql_internal]), include_file) + elements_module = get_import(include_file, opts.root_dir) + renderer.render( ql.GetParentImplementation( classes=list(classes.values()), - additional_imports=[i for name, i in imports.items() if classes[name].ql_internal], + imports=[elements_module] + [i for name, i in imports.items() if classes[name].ql_internal], ), out / 'ParentChild.qll') - for c in data.classes.values(): - if _should_skip_qltest(c, data.classes): - continue - test_dir = test_out / c.group / c.name - test_dir.mkdir(parents=True, exist_ok=True) - if not any(test_dir.glob("*.swift")): - log.warning(f"no test source in {test_dir.relative_to(test_out)}") - renderer.render(ql.MissingTestInstructions(), - test_dir / missing_test_source_filename) - continue - total_props, partial_props = _partition(_get_all_properties_to_be_tested(c, data.classes), - lambda p: p.is_total) - renderer.render(ql.ClassTester(class_name=c.name, - properties=total_props, - # in case of collapsed hierarchies we want to see the actual QL class in results - show_ql_class="qltest_collapse_hierarchy" in c.pragmas), - test_dir / f"{c.name}.ql") - for p in partial_props: - renderer.render(ql.PropertyTester(class_name=c.name, - property=p), test_dir / f"{c.name}_{p.getter}.ql") + if test_out: + for c in data.classes.values(): + if _should_skip_qltest(c, data.classes): + continue + test_dir = test_out / c.group / c.name + test_dir.mkdir(parents=True, exist_ok=True) + if all(f.suffix in (".txt", ".ql", ".actual", ".expected") for f in test_dir.glob("*.*")): + log.warning(f"no test source in {test_dir.relative_to(test_out)}") + renderer.render(ql.MissingTestInstructions(), + test_dir / missing_test_source_filename) + continue + total_props, partial_props = _partition(_get_all_properties_to_be_tested(c, data.classes), + lambda p: p.is_total) + renderer.render(ql.ClassTester(class_name=c.name, + properties=total_props, + elements_module=elements_module, + # in case of collapsed hierarchies we want to see the actual QL class in results + show_ql_class="qltest_collapse_hierarchy" in c.pragmas), + test_dir / f"{c.name}.ql") + for p in partial_props: + renderer.render(ql.PropertyTester(class_name=c.name, + elements_module=elements_module, + property=p), test_dir / f"{c.name}_{p.getter}.ql") final_ipa_types = [] non_final_ipa_types = [] @@ -372,8 +411,8 @@ def generate(opts, renderer): stub_file = stub_out / cls.group / f"{cls.name}Constructor.qll" if not renderer.is_customized_stub(stub_file): # stub rendering must be postponed as we might not have yet all subtracted ipa types in `ipa_type` - stubs[stub_file] = ql.Synth.ConstructorStub(ipa_type) - constructor_import = get_import(stub_file, opts.swift_dir) + stubs[stub_file] = ql.Synth.ConstructorStub(ipa_type, import_prefix=generated_import_prefix) + constructor_import = get_import(stub_file, opts.root_dir) constructor_imports.append(constructor_import) if ipa_type.is_ipa: ipa_constructor_imports.append(constructor_import) @@ -382,7 +421,8 @@ def generate(opts, renderer): for stub_file, data in stubs.items(): renderer.render(data, stub_file) - renderer.render(ql.Synth.Types(root.name, final_ipa_types, non_final_ipa_types), out / "Synth.qll") + renderer.render(ql.Synth.Types(root.name, generated_import_prefix, + final_ipa_types, non_final_ipa_types), out / "Synth.qll") renderer.render(ql.ImportList(constructor_imports), out / "SynthConstructors.qll") renderer.render(ql.ImportList(ipa_constructor_imports), out / "PureSynthConstructors.qll") if opts.ql_format: diff --git a/swift/codegen/generators/trapgen.py b/misc/codegen/generators/trapgen.py similarity index 86% rename from swift/codegen/generators/trapgen.py rename to misc/codegen/generators/trapgen.py index f01203e9272..e22b3e4e0e7 100755 --- a/swift/codegen/generators/trapgen.py +++ b/misc/codegen/generators/trapgen.py @@ -17,7 +17,8 @@ import pathlib import inflection from toposort import toposort_flatten -from swift.codegen.lib import dbscheme, cpp +from misc.codegen.lib import dbscheme, cpp +from misc.codegen.loaders import dbschemeloader log = logging.getLogger(__name__) @@ -71,9 +72,10 @@ def generate(opts, renderer): assert opts.cpp_output tag_graph = {} out = opts.cpp_output + trap_library = opts.trap_library traps = {pathlib.Path(): []} - for e in dbscheme.iterload(opts.dbscheme): + for e in dbschemeloader.iterload(opts.dbscheme): if e.is_table: traps.setdefault(e.dir, []).append(get_trap(e)) elif e.is_union: @@ -83,7 +85,8 @@ def generate(opts, renderer): for dir, entries in traps.items(): dir = dir or pathlib.Path() - renderer.render(cpp.TrapList(entries, opts.dbscheme), out / dir / "TrapEntries") + relative_gen_dir = pathlib.Path(*[".." for _ in dir.parents]) + renderer.render(cpp.TrapList(entries, opts.dbscheme, trap_library, relative_gen_dir), out / dir / "TrapEntries") tags = [] for tag in toposort_flatten(tag_graph): diff --git a/misc/codegen/lib/BUILD.bazel b/misc/codegen/lib/BUILD.bazel new file mode 100644 index 00000000000..482d1ac178f --- /dev/null +++ b/misc/codegen/lib/BUILD.bazel @@ -0,0 +1,11 @@ +load("@codegen_deps//:requirements.bzl", "requirement") + +py_library( + name = "lib", + srcs = glob(["*.py"]), + visibility = ["//misc/codegen:__subpackages__"], + deps = [ + requirement("pystache"), + requirement("inflection"), + ], +) diff --git a/swift/codegen/lib/cpp.py b/misc/codegen/lib/cpp.py similarity index 97% rename from swift/codegen/lib/cpp.py rename to misc/codegen/lib/cpp.py index 27bac12231b..9ca2d8e2ebc 100644 --- a/swift/codegen/lib/cpp.py +++ b/misc/codegen/lib/cpp.py @@ -1,3 +1,4 @@ +import pathlib import re from dataclasses import dataclass, field from typing import List, ClassVar @@ -110,6 +111,8 @@ class TrapList: extensions = ["h", "cpp"] traps: List[Trap] source: str + trap_library_dir: pathlib.Path + gen_dir: pathlib.Path @dataclass @@ -156,4 +159,5 @@ class ClassList: classes: List[Class] source: str + trap_library: str include_parent: bool = False diff --git a/swift/codegen/lib/dbscheme.py b/misc/codegen/lib/dbscheme.py similarity index 56% rename from swift/codegen/lib/dbscheme.py rename to misc/codegen/lib/dbscheme.py index 4883b0deaf5..eee0191b678 100644 --- a/swift/codegen/lib/dbscheme.py +++ b/misc/codegen/lib/dbscheme.py @@ -105,54 +105,3 @@ class Scheme: src: str includes: List[SchemeInclude] declarations: List[Decl] - - -class Re: - entity = re.compile( - "(?m)" - r"(?:^#keyset\[(?P[\w\s,]+)\][\s\n]*)?^(?P\w+)\(" - r"(?:\s*//dir=(?P\S*))?(?P[^\)]*)" - r"\);?" - "|" - r"^(?P@\w+)\s*=\s*(?P@\w+(?:\s*\|\s*@\w+)*)\s*;?" - ) - field = re.compile(r"(?m)[\w\s]*\s(?P\w+)\s*:\s*(?P@?\w+)(?P\s+ref)?") - key = re.compile(r"@\w+") - comment = re.compile(r"(?m)(?s)/\*.*?\*/|//(?!dir=)[^\n]*$") # lookahead avoid ignoring metadata like //dir=foo - - -def get_column(match): - return Column( - schema_name=match["field"].rstrip("_"), - type=match["type"], - binding=not match["ref"], - ) - - -def get_table(match): - keyset = None - if match["tablekeys"]: - keyset = KeySet(k.strip() for k in match["tablekeys"].split(",")) - return Table( - name=match["table"], - columns=[get_column(f) for f in Re.field.finditer(match["tablebody"])], - keyset=keyset, - dir=pathlib.PosixPath(match["tabledir"]) if match["tabledir"] else None, - ) - - -def get_union(match): - return Union( - lhs=match["union"], - rhs=(d[0] for d in Re.key.finditer(match["unionbody"])), - ) - - -def iterload(file): - with open(file) as file: - data = Re.comment.sub("", file.read()) - for e in Re.entity.finditer(data): - if e["table"]: - yield get_table(e) - elif e["union"]: - yield get_union(e) diff --git a/swift/codegen/lib/paths.py b/misc/codegen/lib/paths.py similarity index 50% rename from swift/codegen/lib/paths.py rename to misc/codegen/lib/paths.py index 2ad1284b17b..b102987a226 100644 --- a/swift/codegen/lib/paths.py +++ b/misc/codegen/lib/paths.py @@ -4,15 +4,16 @@ import pathlib import sys import os +_this_file = pathlib.Path(__file__).resolve() + try: workspace_dir = pathlib.Path(os.environ['BUILD_WORKSPACE_DIRECTORY']).resolve() # <- means we are using bazel run - swift_dir = workspace_dir / 'swift' + root_dir = workspace_dir / 'swift' except KeyError: - _this_file = pathlib.Path(__file__).resolve() - swift_dir = _this_file.parents[2] - workspace_dir = swift_dir.parent + root_dir = _this_file.parents[2] + workspace_dir = root_dir.parent -lib_dir = swift_dir / 'codegen' / 'lib' -templates_dir = swift_dir / 'codegen' / 'templates' +lib_dir = _this_file.parents[2] / 'codegen' / 'lib' +templates_dir = _this_file.parents[2] / 'codegen' / 'templates' exe_file = pathlib.Path(sys.argv[0]).resolve() diff --git a/swift/codegen/lib/ql.py b/misc/codegen/lib/ql.py similarity index 90% rename from swift/codegen/lib/ql.py rename to misc/codegen/lib/ql.py index c40c42aa33f..ace39a61e0e 100644 --- a/swift/codegen/lib/ql.py +++ b/misc/codegen/lib/ql.py @@ -97,6 +97,7 @@ class Class: properties: List[Property] = field(default_factory=list) dir: pathlib.Path = pathlib.Path() imports: List[str] = field(default_factory=list) + import_prefix: Optional[str] = None qltest_skip: bool = False qltest_collapse_hierarchy: bool = False qltest_uncollapse_hierarchy: bool = False @@ -134,12 +135,30 @@ class Class: return bool(self.doc) or self.ql_internal +@dataclass +class IpaUnderlyingAccessor: + argument: str + type: str + constructorparams: List[Param] + + def __post_init__(self): + if self.constructorparams: + self.constructorparams = [Param(x) for x in self.constructorparams] + self.constructorparams[0].first = True + + @dataclass class Stub: template: ClassVar = 'ql_stub' name: str base_import: str + import_prefix: str + ipa_accessors: List[IpaUnderlyingAccessor] = field(default_factory=list) + + @property + def has_ipa_accessors(self) -> bool: + return bool(self.ipa_accessors) @dataclass @@ -161,7 +180,7 @@ class GetParentImplementation: template: ClassVar = 'ql_parent' classes: List[Class] = field(default_factory=list) - additional_imports: List[str] = field(default_factory=list) + imports: List[str] = field(default_factory=list) @dataclass @@ -173,19 +192,23 @@ class PropertyForTest: @dataclass -class ClassTester: +class TesterBase: + class_name: str + elements_module: str + + +@dataclass +class ClassTester(TesterBase): template: ClassVar = 'ql_test_class' - class_name: str properties: List[PropertyForTest] = field(default_factory=list) show_ql_class: bool = False @dataclass -class PropertyTester: +class PropertyTester(TesterBase): template: ClassVar = 'ql_test_property' - class_name: str property: PropertyForTest @@ -273,6 +296,7 @@ class Synth: template: ClassVar = "ql_ipa_types" root: str + import_prefix: str final_classes: List["Synth.FinalClass"] = field(default_factory=list) non_final_classes: List["Synth.NonFinalClass"] = field(default_factory=list) @@ -285,3 +309,4 @@ class Synth: template: ClassVar = "ql_ipa_constructor_stub" cls: "Synth.FinalClass" + import_prefix: str diff --git a/swift/codegen/lib/render.py b/misc/codegen/lib/render.py similarity index 91% rename from swift/codegen/lib/render.py rename to misc/codegen/lib/render.py index 65014a42fa2..697c2f8c2c9 100644 --- a/swift/codegen/lib/render.py +++ b/misc/codegen/lib/render.py @@ -25,13 +25,13 @@ class Error(Exception): class Renderer: """ Template renderer using mustache templates in the `templates` directory """ - def __init__(self, swift_dir: pathlib.Path): + def __init__(self, generator: pathlib.Path, root_dir: pathlib.Path): self._r = pystache.Renderer(search_dirs=str(paths.templates_dir), escape=lambda u: u) - self._swift_dir = swift_dir - self._generator = self._get_path(paths.exe_file) + self._root_dir = root_dir + self._generator = generator def _get_path(self, file: pathlib.Path): - return file.relative_to(self._swift_dir) + return file.relative_to(self._root_dir) def render(self, data: object, output: pathlib.Path): """ Render `data` to `output`. @@ -60,7 +60,7 @@ class Renderer: def manage(self, generated: typing.Iterable[pathlib.Path], stubs: typing.Iterable[pathlib.Path], registry: pathlib.Path, force: bool = False) -> "RenderManager": - return RenderManager(self._swift_dir, generated, stubs, registry, force) + return RenderManager(self._generator, self._root_dir, generated, stubs, registry, force) class RenderManager(Renderer): @@ -85,10 +85,10 @@ class RenderManager(Renderer): pre: str post: typing.Optional[str] = None - def __init__(self, swift_dir: pathlib.Path, generated: typing.Iterable[pathlib.Path], + def __init__(self, generator: pathlib.Path, root_dir: pathlib.Path, generated: typing.Iterable[pathlib.Path], stubs: typing.Iterable[pathlib.Path], registry: pathlib.Path, force: bool = False): - super().__init__(swift_dir) + super().__init__(generator, root_dir) self._registry_path = registry self._force = force self._hashes = {} @@ -106,7 +106,6 @@ class RenderManager(Renderer): def __exit__(self, exc_type, exc_val, exc_tb): if exc_val is None: for f in self._existing - self._skipped - self.written: - self._hashes.pop(self._get_path(f), None) f.unlink(missing_ok=True) log.info(f"removed {f.name}") for f in self.written: @@ -116,6 +115,10 @@ class RenderManager(Renderer): # so that they get the chance to be regenerated again during the next run for f in self.written: self._hashes.pop(self._get_path(f), None) + # clean up the registry from files that do not exist any more + for f in list(self._hashes): + if not (self._root_dir / f).exists(): + self._hashes.pop(f) self._dump_registry() def _do_write(self, mnemonic: str, contents: str, output: pathlib.Path): diff --git a/swift/codegen/lib/schema/schema.py b/misc/codegen/lib/schema.py similarity index 53% rename from swift/codegen/lib/schema/schema.py rename to misc/codegen/lib/schema.py index a2a1de0c05a..5e2974ae87d 100644 --- a/swift/codegen/lib/schema/schema.py +++ b/misc/codegen/lib/schema.py @@ -1,15 +1,9 @@ -""" schema.yml format representation """ -import pathlib -import re -import types +""" schema format representation """ import typing from dataclasses import dataclass, field from typing import List, Set, Union, Dict, Optional from enum import Enum, auto import functools -import importlib.util -from toposort import toposort_flatten -import inflection class Error(Exception): @@ -198,125 +192,3 @@ def split_doc(doc): while trimmed and not trimmed[0]: trimmed.pop(0) return trimmed - - -@dataclass -class _PropertyNamer(PropertyModifier): - name: str - - def modify(self, prop: Property): - prop.name = self.name.rstrip("_") - - -def _get_class(cls: type) -> Class: - if not isinstance(cls, type): - raise Error(f"Only class definitions allowed in schema, found {cls}") - # we must check that going to dbscheme names and back is preserved - # In particular this will not happen if uppercase acronyms are included in the name - to_underscore_and_back = inflection.camelize(inflection.underscore(cls.__name__), uppercase_first_letter=True) - if cls.__name__ != to_underscore_and_back: - raise Error(f"Class name must be upper camel-case, without capitalized acronyms, found {cls.__name__} " - f"instead of {to_underscore_and_back}") - if len({b._group for b in cls.__bases__ if hasattr(b, "_group")}) > 1: - raise Error(f"Bases with mixed groups for {cls.__name__}") - if any(getattr(b, "_null", False) for b in cls.__bases__): - raise Error(f"Null class cannot be derived") - return Class(name=cls.__name__, - bases=[b.__name__ for b in cls.__bases__ if b is not object], - derived={d.__name__ for d in cls.__subclasses__()}, - # getattr to inherit from bases - group=getattr(cls, "_group", ""), - # in the following we don't use `getattr` to avoid inheriting - pragmas=cls.__dict__.get("_pragmas", []), - ipa=cls.__dict__.get("_ipa", None), - properties=[ - a | _PropertyNamer(n) - for n, a in cls.__dict__.get("__annotations__", {}).items() - ], - doc=split_doc(cls.__doc__), - default_doc_name=cls.__dict__.get("_doc_name"), - ) - - -def _toposort_classes_by_group(classes: typing.Dict[str, Class]) -> typing.Dict[str, Class]: - groups = {} - ret = {} - - for name, cls in classes.items(): - groups.setdefault(cls.group, []).append(name) - - for group, grouped in sorted(groups.items()): - inheritance = {name: classes[name].bases for name in grouped} - for name in toposort_flatten(inheritance): - ret[name] = classes[name] - - return ret - - -def _fill_ipa_information(classes: typing.Dict[str, Class]): - """ Take a dictionary where the `ipa` field is filled for all explicitly synthesized classes - and update it so that all non-final classes that have only synthesized final descendants - get `True` as` value for the `ipa` field - """ - if not classes: - return - - is_ipa: typing.Dict[str, bool] = {} - - def fill_is_ipa(name: str): - if name not in is_ipa: - cls = classes[name] - for d in cls.derived: - fill_is_ipa(d) - if cls.ipa is not None: - is_ipa[name] = True - elif not cls.derived: - is_ipa[name] = False - else: - is_ipa[name] = all(is_ipa[d] for d in cls.derived) - - root = next(iter(classes)) - fill_is_ipa(root) - - for name, cls in classes.items(): - if cls.ipa is None and is_ipa[name]: - cls.ipa = True - - -def load(m: types.ModuleType) -> Schema: - includes = set() - classes = {} - known = {"int", "string", "boolean"} - known.update(n for n in m.__dict__ if not n.startswith("__")) - import swift.codegen.lib.schema.defs as defs - null = None - for name, data in m.__dict__.items(): - if hasattr(defs, name): - continue - if name == "__includes": - includes = set(data) - continue - if name.startswith("__"): - continue - cls = _get_class(data) - if classes and not cls.bases: - raise Error( - f"Only one root class allowed, found second root {name}") - cls.check_types(known) - classes[name] = cls - if getattr(data, "_null", False): - if null is not None: - raise Error(f"Null class {null} already defined, second null class {name} not allowed") - null = name - cls.is_null_class = True - - _fill_ipa_information(classes) - - return Schema(includes=includes, classes=_toposort_classes_by_group(classes), null=null) - - -def load_file(path: pathlib.Path) -> Schema: - spec = importlib.util.spec_from_file_location("schema", path) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - return load(module) diff --git a/swift/codegen/lib/schema/defs.py b/misc/codegen/lib/schemadefs.py similarity index 98% rename from swift/codegen/lib/schema/defs.py rename to misc/codegen/lib/schemadefs.py index d972e5a63e5..6c9457490e7 100644 --- a/swift/codegen/lib/schema/defs.py +++ b/misc/codegen/lib/schemadefs.py @@ -1,5 +1,5 @@ from typing import Callable as _Callable -from swift.codegen.lib import schema as _schema +from misc.codegen.lib import schema as _schema import inspect as _inspect from dataclasses import dataclass as _dataclass diff --git a/misc/codegen/loaders/BUILD.bazel b/misc/codegen/loaders/BUILD.bazel new file mode 100644 index 00000000000..be07c6d884b --- /dev/null +++ b/misc/codegen/loaders/BUILD.bazel @@ -0,0 +1,11 @@ +load("@codegen_deps//:requirements.bzl", "requirement") + +py_library( + name = "loaders", + srcs = glob(["*.py"]), + visibility = ["//misc/codegen:__subpackages__"], + deps = [ + requirement("toposort"), + requirement("inflection"), + ], +) diff --git a/misc/codegen/loaders/dbschemeloader.py b/misc/codegen/loaders/dbschemeloader.py new file mode 100644 index 00000000000..51e362362a7 --- /dev/null +++ b/misc/codegen/loaders/dbschemeloader.py @@ -0,0 +1,54 @@ +import pathlib +import re +from misc.codegen.lib import dbscheme + + +class _Re: + entity = re.compile( + "(?m)" + r"(?:^#keyset\[(?P[\w\s,]+)\][\s\n]*)?^(?P
\w+)\(" + r"(?:\s*//dir=(?P\S*))?(?P[^\)]*)" + r"\);?" + "|" + r"^(?P@\w+)\s*=\s*(?P@\w+(?:\s*\|\s*@\w+)*)\s*;?" + ) + field = re.compile(r"(?m)[\w\s]*\s(?P\w+)\s*:\s*(?P@?\w+)(?P\s+ref)?") + key = re.compile(r"@\w+") + comment = re.compile(r"(?m)(?s)/\*.*?\*/|//(?!dir=)[^\n]*$") # lookahead avoid ignoring metadata like //dir=foo + + +def _get_column(match): + return dbscheme.Column( + schema_name=match["field"].rstrip("_"), + type=match["type"], + binding=not match["ref"], + ) + + +def _get_table(match): + keyset = None + if match["tablekeys"]: + keyset = dbscheme.KeySet(k.strip() for k in match["tablekeys"].split(",")) + return dbscheme.Table( + name=match["table"], + columns=[_get_column(f) for f in _Re.field.finditer(match["tablebody"])], + keyset=keyset, + dir=pathlib.PosixPath(match["tabledir"]) if match["tabledir"] else None, + ) + + +def _get_union(match): + return dbscheme.Union( + lhs=match["union"], + rhs=(d[0] for d in _Re.key.finditer(match["unionbody"])), + ) + + +def iterload(file): + with open(file) as file: + data = _Re.comment.sub("", file.read()) + for e in _Re.entity.finditer(data): + if e["table"]: + yield _get_table(e) + elif e["union"]: + yield _get_union(e) diff --git a/misc/codegen/loaders/schemaloader.py b/misc/codegen/loaders/schemaloader.py new file mode 100644 index 00000000000..5fd392b112d --- /dev/null +++ b/misc/codegen/loaders/schemaloader.py @@ -0,0 +1,133 @@ +""" schema loader """ + +import inflection +import typing +import types +import pathlib +import importlib.util +from dataclasses import dataclass +from toposort import toposort_flatten + +from misc.codegen.lib import schema, schemadefs + + +@dataclass +class _PropertyNamer(schema.PropertyModifier): + name: str + + def modify(self, prop: schema.Property): + prop.name = self.name.rstrip("_") + + +def _get_class(cls: type) -> schema.Class: + if not isinstance(cls, type): + raise schema.Error(f"Only class definitions allowed in schema, found {cls}") + # we must check that going to dbscheme names and back is preserved + # In particular this will not happen if uppercase acronyms are included in the name + to_underscore_and_back = inflection.camelize(inflection.underscore(cls.__name__), uppercase_first_letter=True) + if cls.__name__ != to_underscore_and_back: + raise schema.Error(f"Class name must be upper camel-case, without capitalized acronyms, found {cls.__name__} " + f"instead of {to_underscore_and_back}") + if len({b._group for b in cls.__bases__ if hasattr(b, "_group")}) > 1: + raise schema.Error(f"Bases with mixed groups for {cls.__name__}") + if any(getattr(b, "_null", False) for b in cls.__bases__): + raise schema.Error(f"Null class cannot be derived") + return schema.Class(name=cls.__name__, + bases=[b.__name__ for b in cls.__bases__ if b is not object], + derived={d.__name__ for d in cls.__subclasses__()}, + # getattr to inherit from bases + group=getattr(cls, "_group", ""), + # in the following we don't use `getattr` to avoid inheriting + pragmas=cls.__dict__.get("_pragmas", []), + ipa=cls.__dict__.get("_ipa", None), + properties=[ + a | _PropertyNamer(n) + for n, a in cls.__dict__.get("__annotations__", {}).items() + ], + doc=schema.split_doc(cls.__doc__), + default_doc_name=cls.__dict__.get("_doc_name"), + ) + + +def _toposort_classes_by_group(classes: typing.Dict[str, schema.Class]) -> typing.Dict[str, schema.Class]: + groups = {} + ret = {} + + for name, cls in classes.items(): + groups.setdefault(cls.group, []).append(name) + + for group, grouped in sorted(groups.items()): + inheritance = {name: classes[name].bases for name in grouped} + for name in toposort_flatten(inheritance): + ret[name] = classes[name] + + return ret + + +def _fill_ipa_information(classes: typing.Dict[str, schema.Class]): + """ Take a dictionary where the `ipa` field is filled for all explicitly synthesized classes + and update it so that all non-final classes that have only synthesized final descendants + get `True` as` value for the `ipa` field + """ + if not classes: + return + + is_ipa: typing.Dict[str, bool] = {} + + def fill_is_ipa(name: str): + if name not in is_ipa: + cls = classes[name] + for d in cls.derived: + fill_is_ipa(d) + if cls.ipa is not None: + is_ipa[name] = True + elif not cls.derived: + is_ipa[name] = False + else: + is_ipa[name] = all(is_ipa[d] for d in cls.derived) + + root = next(iter(classes)) + fill_is_ipa(root) + + for name, cls in classes.items(): + if cls.ipa is None and is_ipa[name]: + cls.ipa = True + + +def load(m: types.ModuleType) -> schema.Schema: + includes = set() + classes = {} + known = {"int", "string", "boolean"} + known.update(n for n in m.__dict__ if not n.startswith("__")) + import misc.codegen.lib.schemadefs as defs + null = None + for name, data in m.__dict__.items(): + if hasattr(defs, name): + continue + if name == "__includes": + includes = set(data) + continue + if name.startswith("__"): + continue + cls = _get_class(data) + if classes and not cls.bases: + raise schema.Error( + f"Only one root class allowed, found second root {name}") + cls.check_types(known) + classes[name] = cls + if getattr(data, "_null", False): + if null is not None: + raise schema.Error(f"Null class {null} already defined, second null class {name} not allowed") + null = name + cls.is_null_class = True + + _fill_ipa_information(classes) + + return schema.Schema(includes=includes, classes=_toposort_classes_by_group(classes), null=null) + + +def load_file(path: pathlib.Path) -> schema.Schema: + spec = importlib.util.spec_from_file_location("schema", path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return load(module) diff --git a/swift/codegen/requirements.txt b/misc/codegen/requirements.txt similarity index 100% rename from swift/codegen/requirements.txt rename to misc/codegen/requirements.txt diff --git a/misc/codegen/schemadefs.py b/misc/codegen/schemadefs.py new file mode 100644 index 00000000000..6c9457490e7 --- /dev/null +++ b/misc/codegen/schemadefs.py @@ -0,0 +1,149 @@ +from typing import Callable as _Callable +from misc.codegen.lib import schema as _schema +import inspect as _inspect +from dataclasses import dataclass as _dataclass + + +class _ChildModifier(_schema.PropertyModifier): + def modify(self, prop: _schema.Property): + if prop.type is None or prop.type[0].islower(): + raise _schema.Error("Non-class properties cannot be children") + prop.is_child = True + + +@_dataclass +class _DocModifier(_schema.PropertyModifier): + doc: str + + def modify(self, prop: _schema.Property): + if "\n" in self.doc or self.doc[-1] == ".": + raise _schema.Error("No newlines or trailing dots are allowed in doc, did you intend to use desc?") + prop.doc = self.doc + + +@_dataclass +class _DescModifier(_schema.PropertyModifier): + description: str + + def modify(self, prop: _schema.Property): + prop.description = _schema.split_doc(self.description) + + +def include(source: str): + # add to `includes` variable in calling context + _inspect.currentframe().f_back.f_locals.setdefault( + "__includes", []).append(source) + + +class _Namespace: + """ simple namespacing mechanism """ + + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +qltest = _Namespace() +ql = _Namespace() +cpp = _Namespace() +synth = _Namespace() + + +@_dataclass +class _Pragma(_schema.PropertyModifier): + """ A class or property pragma. + For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma. + For schema classes it acts as a python decorator with `@`. + """ + pragma: str + + def __post_init__(self): + namespace, _, name = self.pragma.partition('_') + setattr(globals()[namespace], name, self) + + def modify(self, prop: _schema.Property): + prop.pragmas.append(self.pragma) + + def __call__(self, cls: type) -> type: + """ use this pragma as a decorator on classes """ + if "_pragmas" in cls.__dict__: # not using hasattr as we don't want to land on inherited pragmas + cls._pragmas.append(self.pragma) + else: + cls._pragmas = [self.pragma] + return cls + + +class _Optionalizer(_schema.PropertyModifier): + def modify(self, prop: _schema.Property): + K = _schema.Property.Kind + if prop.kind != K.SINGLE: + raise _schema.Error( + "Optional should only be applied to simple property types") + prop.kind = K.OPTIONAL + + +class _Listifier(_schema.PropertyModifier): + def modify(self, prop: _schema.Property): + K = _schema.Property.Kind + if prop.kind == K.SINGLE: + prop.kind = K.REPEATED + elif prop.kind == K.OPTIONAL: + prop.kind = K.REPEATED_OPTIONAL + else: + raise _schema.Error( + "Repeated should only be applied to simple or optional property types") + + +class _TypeModifier: + """ Modifies types using get item notation """ + + def __init__(self, modifier: _schema.PropertyModifier): + self.modifier = modifier + + def __getitem__(self, item): + return item | self.modifier + + +_ClassDecorator = _Callable[[type], type] + + +def _annotate(**kwargs) -> _ClassDecorator: + def f(cls: type) -> type: + for k, v in kwargs.items(): + setattr(cls, f"_{k}", v) + return cls + + return f + + +boolean = "boolean" +int = "int" +string = "string" + +predicate = _schema.predicate_marker +optional = _TypeModifier(_Optionalizer()) +list = _TypeModifier(_Listifier()) + +child = _ChildModifier() +doc = _DocModifier +desc = _DescModifier + +use_for_null = _annotate(null=True) + +_Pragma("qltest_skip") +_Pragma("qltest_collapse_hierarchy") +_Pragma("qltest_uncollapse_hierarchy") + +ql.default_doc_name = lambda doc: _annotate(doc_name=doc) +_Pragma("ql_internal") + +_Pragma("cpp_skip") + + +def group(name: str = "") -> _ClassDecorator: + return _annotate(group=name) + + +synth.from_class = lambda ref: _annotate(ipa=_schema.IpaInfo( + from_class=_schema.get_type_name(ref))) +synth.on_arguments = lambda **kwargs: _annotate( + ipa=_schema.IpaInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})) diff --git a/swift/codegen/templates/BUILD.bazel b/misc/codegen/templates/BUILD.bazel similarity index 68% rename from swift/codegen/templates/BUILD.bazel rename to misc/codegen/templates/BUILD.bazel index 7745e7ea2ac..a86346245af 100644 --- a/swift/codegen/templates/BUILD.bazel +++ b/misc/codegen/templates/BUILD.bazel @@ -1,4 +1,4 @@ -package(default_visibility = ["//swift:__subpackages__"]) +package(default_visibility = ["//misc/codegen:__subpackages__"]) filegroup( name = "trap", diff --git a/swift/codegen/templates/cpp_classes_cpp.mustache b/misc/codegen/templates/cpp_classes_cpp.mustache similarity index 100% rename from swift/codegen/templates/cpp_classes_cpp.mustache rename to misc/codegen/templates/cpp_classes_cpp.mustache diff --git a/swift/codegen/templates/cpp_classes_h.mustache b/misc/codegen/templates/cpp_classes_h.mustache similarity index 95% rename from swift/codegen/templates/cpp_classes_h.mustache rename to misc/codegen/templates/cpp_classes_h.mustache index a4a22170b2f..157bbc31217 100644 --- a/swift/codegen/templates/cpp_classes_h.mustache +++ b/misc/codegen/templates/cpp_classes_h.mustache @@ -6,8 +6,8 @@ #include #include -#include "swift/extractor/trap/TrapLabel.h" -#include "swift/extractor/trap/TrapTagTraits.h" +#include "{{trap_library}}/TrapLabel.h" +#include "{{trap_library}}/TrapTagTraits.h" #include "./TrapEntries.h" {{#include_parent}} #include "../TrapClasses.h" diff --git a/swift/codegen/templates/dbscheme.mustache b/misc/codegen/templates/dbscheme.mustache similarity index 100% rename from swift/codegen/templates/dbscheme.mustache rename to misc/codegen/templates/dbscheme.mustache diff --git a/swift/codegen/templates/ql_class.mustache b/misc/codegen/templates/ql_class.mustache similarity index 97% rename from swift/codegen/templates/ql_class.mustache rename to misc/codegen/templates/ql_class.mustache index cd0b3ac2355..173df3a75b9 100644 --- a/swift/codegen/templates/ql_class.mustache +++ b/misc/codegen/templates/ql_class.mustache @@ -1,6 +1,6 @@ // generated by {{generator}} -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw +private import {{import_prefix}}.Synth +private import {{import_prefix}}.Raw {{#imports}} import {{.}} {{/imports}} diff --git a/swift/codegen/templates/ql_db.mustache b/misc/codegen/templates/ql_db.mustache similarity index 100% rename from swift/codegen/templates/ql_db.mustache rename to misc/codegen/templates/ql_db.mustache diff --git a/swift/codegen/templates/ql_imports.mustache b/misc/codegen/templates/ql_imports.mustache similarity index 100% rename from swift/codegen/templates/ql_imports.mustache rename to misc/codegen/templates/ql_imports.mustache diff --git a/swift/codegen/templates/ql_ipa_constructor_stub.mustache b/misc/codegen/templates/ql_ipa_constructor_stub.mustache similarity index 83% rename from swift/codegen/templates/ql_ipa_constructor_stub.mustache rename to misc/codegen/templates/ql_ipa_constructor_stub.mustache index f207db66d21..e5e525417d3 100644 --- a/swift/codegen/templates/ql_ipa_constructor_stub.mustache +++ b/misc/codegen/templates/ql_ipa_constructor_stub.mustache @@ -1,9 +1,9 @@ // generated by {{generator}}, remove this comment if you wish to edit this file -private import codeql.swift.generated.Raw +private import {{import_prefix}}.Raw {{#cls}} {{#is_db}} {{#has_subtracted_ipa_types}} -private import codeql.swift.generated.PureSynthConstructors +private import {{import_prefix}}.PureSynthConstructors {{/has_subtracted_ipa_types}} {{/is_db}} diff --git a/swift/codegen/templates/ql_ipa_types.mustache b/misc/codegen/templates/ql_ipa_types.mustache similarity index 93% rename from swift/codegen/templates/ql_ipa_types.mustache rename to misc/codegen/templates/ql_ipa_types.mustache index 9a4eef5e6b5..430361f6776 100644 --- a/swift/codegen/templates/ql_ipa_types.mustache +++ b/misc/codegen/templates/ql_ipa_types.mustache @@ -1,5 +1,5 @@ -private import codeql.swift.generated.SynthConstructors -private import codeql.swift.generated.Raw +private import {{import_prefix}}.SynthConstructors +private import {{import_prefix}}.Raw cached module Synth { cached newtype T{{root}} = diff --git a/swift/codegen/templates/ql_parent.mustache b/misc/codegen/templates/ql_parent.mustache similarity index 98% rename from swift/codegen/templates/ql_parent.mustache rename to misc/codegen/templates/ql_parent.mustache index 53f80712aac..6777d366ddf 100644 --- a/swift/codegen/templates/ql_parent.mustache +++ b/misc/codegen/templates/ql_parent.mustache @@ -1,9 +1,8 @@ // generated by {{generator}} -import codeql.swift.elements -{{#additional_imports}} +{{#imports}} import {{.}} -{{/additional_imports}} +{{/imports}} private module Impl { {{#classes}} diff --git a/swift/codegen/templates/ql_property_doc.mustache b/misc/codegen/templates/ql_property_doc.mustache similarity index 100% rename from swift/codegen/templates/ql_property_doc.mustache rename to misc/codegen/templates/ql_property_doc.mustache diff --git a/misc/codegen/templates/ql_stub.mustache b/misc/codegen/templates/ql_stub.mustache new file mode 100644 index 00000000000..7e17efc6d46 --- /dev/null +++ b/misc/codegen/templates/ql_stub.mustache @@ -0,0 +1,18 @@ +// generated by {{generator}}, remove this comment if you wish to edit this file +private import {{base_import}} +{{#has_ipa_accessors}} +private import {{import_prefix}}.Raw +private import {{import_prefix}}.Synth +{{/has_ipa_accessors}} + +{{#ql_internal}} +/** + * INTERNAL: Do not use. + */ +{{/ql_internal}} +class {{name}} extends Generated::{{name}} { + {{#ipa_accessors}} + private + cached {{type}} getUnderlying{{argument}}() { this = Synth::T{{name}}({{#constructorparams}}{{^first}},{{/first}}{{param}}{{/constructorparams}})} + {{/ipa_accessors}} +} diff --git a/swift/codegen/templates/ql_test_class.mustache b/misc/codegen/templates/ql_test_class.mustache similarity index 94% rename from swift/codegen/templates/ql_test_class.mustache rename to misc/codegen/templates/ql_test_class.mustache index adaf80de867..d689753cfd3 100644 --- a/swift/codegen/templates/ql_test_class.mustache +++ b/misc/codegen/templates/ql_test_class.mustache @@ -1,6 +1,6 @@ // generated by {{generator}} -import codeql.swift.elements +import {{elements_module}} import TestUtils from {{class_name}} x{{#properties}}, {{#type}}{{.}}{{/type}}{{^type}}string{{/type}} {{getter}}{{/properties}} diff --git a/misc/codegen/templates/ql_test_missing.mustache b/misc/codegen/templates/ql_test_missing.mustache new file mode 100644 index 00000000000..5a714744ef2 --- /dev/null +++ b/misc/codegen/templates/ql_test_missing.mustache @@ -0,0 +1,4 @@ +// generated by {{generator}} + +After a source file is added in this directory and {{generator}} is run again, test queries +will appear and this file will be deleted diff --git a/swift/codegen/templates/ql_test_property.mustache b/misc/codegen/templates/ql_test_property.mustache similarity index 90% rename from swift/codegen/templates/ql_test_property.mustache rename to misc/codegen/templates/ql_test_property.mustache index 46887384159..5e81298089d 100644 --- a/swift/codegen/templates/ql_test_property.mustache +++ b/misc/codegen/templates/ql_test_property.mustache @@ -1,6 +1,6 @@ // generated by {{generator}} -import codeql.swift.elements +import {{elements_module}} import TestUtils {{#property}} diff --git a/swift/codegen/templates/trap_tags_h.mustache b/misc/codegen/templates/trap_tags_h.mustache similarity index 100% rename from swift/codegen/templates/trap_tags_h.mustache rename to misc/codegen/templates/trap_tags_h.mustache diff --git a/swift/codegen/templates/trap_traps_cpp.mustache b/misc/codegen/templates/trap_traps_cpp.mustache similarity index 100% rename from swift/codegen/templates/trap_traps_cpp.mustache rename to misc/codegen/templates/trap_traps_cpp.mustache diff --git a/swift/codegen/templates/trap_traps_h.mustache b/misc/codegen/templates/trap_traps_h.mustache similarity index 82% rename from swift/codegen/templates/trap_traps_h.mustache rename to misc/codegen/templates/trap_traps_h.mustache index d3bf7769bd7..987e980d24b 100644 --- a/swift/codegen/templates/trap_traps_h.mustache +++ b/misc/codegen/templates/trap_traps_h.mustache @@ -5,9 +5,9 @@ #include #include -#include "swift/extractor/trap/TrapLabel.h" -#include "swift/extractor/trap/TrapTagTraits.h" -#include "swift/extractor/trap/generated/TrapTags.h" +#include "{{trap_library_dir}}/TrapLabel.h" +#include "{{trap_library_dir}}/TrapTagTraits.h" +#include "{{gen_dir}}/TrapTags.h" namespace codeql { {{#traps}} diff --git a/swift/codegen/test/BUILD.bazel b/misc/codegen/test/BUILD.bazel similarity index 72% rename from swift/codegen/test/BUILD.bazel rename to misc/codegen/test/BUILD.bazel index 9ae41c14941..dde67283335 100644 --- a/swift/codegen/test/BUILD.bazel +++ b/misc/codegen/test/BUILD.bazel @@ -1,11 +1,11 @@ -load("@swift_codegen_deps//:requirements.bzl", "requirement") +load("@codegen_deps//:requirements.bzl", "requirement") py_library( name = "utils", testonly = True, srcs = ["utils.py"], deps = [ - "//swift/codegen/lib", + "//misc/codegen/lib", requirement("pytest"), ], ) @@ -17,7 +17,7 @@ py_library( srcs = [src], deps = [ ":utils", - "//swift/codegen/generators", + "//misc/codegen/generators", ], ) for src in glob(["test_*.py"]) diff --git a/swift/codegen/test/test_cpp.py b/misc/codegen/test/test_cpp.py similarity index 98% rename from swift/codegen/test/test_cpp.py rename to misc/codegen/test/test_cpp.py index d04877e38c4..c4bee337a4f 100644 --- a/swift/codegen/test/test_cpp.py +++ b/misc/codegen/test/test_cpp.py @@ -3,7 +3,7 @@ from copy import deepcopy import pytest -from swift.codegen.lib import cpp +from misc.codegen.lib import cpp @pytest.mark.parametrize("keyword", cpp.cpp_keywords) diff --git a/swift/codegen/test/test_cppgen.py b/misc/codegen/test/test_cppgen.py similarity index 98% rename from swift/codegen/test/test_cppgen.py rename to misc/codegen/test/test_cppgen.py index 3c62143e86a..278f184fcbc 100644 --- a/swift/codegen/test/test_cppgen.py +++ b/misc/codegen/test/test_cppgen.py @@ -1,8 +1,8 @@ import sys -from swift.codegen.generators import cppgen -from swift.codegen.lib import cpp -from swift.codegen.test.utils import * +from misc.codegen.generators import cppgen +from misc.codegen.lib import cpp +from misc.codegen.test.utils import * output_dir = pathlib.Path("path", "to", "output") diff --git a/misc/codegen/test/test_dbscheme.py b/misc/codegen/test/test_dbscheme.py new file mode 100644 index 00000000000..e2635ecee5a --- /dev/null +++ b/misc/codegen/test/test_dbscheme.py @@ -0,0 +1,52 @@ +import sys +from copy import deepcopy + +from misc.codegen.lib import dbscheme +from misc.codegen.test.utils import * + + +def test_dbcolumn_name(): + assert dbscheme.Column("foo", "some_type").name == "foo" + + +@pytest.mark.parametrize("keyword", dbscheme.dbscheme_keywords) +def test_dbcolumn_keyword_name(keyword): + assert dbscheme.Column(keyword, "some_type").name == keyword + "_" + + +@pytest.mark.parametrize("type,binding,lhstype,rhstype", [ + ("builtin_type", False, "builtin_type", "builtin_type ref"), + ("builtin_type", True, "builtin_type", "builtin_type ref"), + ("@at_type", False, "int", "@at_type ref"), + ("@at_type", True, "unique int", "@at_type"), +]) +def test_dbcolumn_types(type, binding, lhstype, rhstype): + col = dbscheme.Column("foo", type, binding) + assert col.lhstype == lhstype + assert col.rhstype == rhstype + + +def test_keyset_has_first_id_marked(): + ids = ["a", "b", "c"] + ks = dbscheme.KeySet(ids) + assert ks.ids[0].first + assert [id.id for id in ks.ids] == ids + + +def test_table_has_first_column_marked(): + columns = [dbscheme.Column("a", "x"), dbscheme.Column("b", "y", binding=True), dbscheme.Column("c", "z")] + expected = deepcopy(columns) + table = dbscheme.Table("foo", columns) + expected[0].first = True + assert table.columns == expected + + +def test_union_has_first_case_marked(): + rhs = ["a", "b", "c"] + u = dbscheme.Union(lhs="x", rhs=rhs) + assert u.rhs[0].first + assert [c.type for c in u.rhs] == rhs + + +if __name__ == '__main__': + sys.exit(pytest.main([__file__] + sys.argv[1:])) diff --git a/swift/codegen/test/test_dbschemegen.py b/misc/codegen/test/test_dbschemegen.py similarity index 96% rename from swift/codegen/test/test_dbschemegen.py rename to misc/codegen/test/test_dbschemegen.py index 4e560e8208e..7a986538b06 100644 --- a/swift/codegen/test/test_dbschemegen.py +++ b/misc/codegen/test/test_dbschemegen.py @@ -1,9 +1,9 @@ import collections import sys -from swift.codegen.generators import dbschemegen -from swift.codegen.lib import dbscheme -from swift.codegen.test.utils import * +from misc.codegen.generators import dbschemegen +from misc.codegen.lib import dbscheme +from misc.codegen.test.utils import * InputExpectedPair = collections.namedtuple("InputExpectedPair", ("input", "expected")) @@ -30,7 +30,7 @@ def generate(opts, input, renderer): def test_empty(generate): assert generate([]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[], ) @@ -43,10 +43,10 @@ def test_includes(input, opts, generate): write(opts.schema.parent / i, i + " data") assert generate([]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[ dbscheme.SchemeInclude( - src=schema_dir / i, + src=pathlib.Path(i), data=i + " data", ) for i in includes ], @@ -58,7 +58,7 @@ def test_empty_final_class(generate, dir_param): assert generate([ schema.Class("Object", group=dir_param.input), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -78,7 +78,7 @@ def test_final_class_with_single_scalar_field(generate, dir_param): schema.SingleProperty("foo", "bar"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -98,7 +98,7 @@ def test_final_class_with_single_class_field(generate, dir_param): schema.SingleProperty("foo", "Bar"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -118,7 +118,7 @@ def test_final_class_with_optional_field(generate, dir_param): schema.OptionalProperty("foo", "bar"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -146,7 +146,7 @@ def test_final_class_with_repeated_field(generate, property_cls, dir_param): property_cls("foo", "bar"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -174,7 +174,7 @@ def test_final_class_with_predicate_field(generate, dir_param): schema.PredicateProperty("foo"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -205,7 +205,7 @@ def test_final_class_with_more_fields(generate, dir_param): schema.PredicateProperty("six"), ]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Table( @@ -259,7 +259,7 @@ def test_empty_class_with_derived(generate): schema.Class(name="Left", bases=["Base"]), schema.Class(name="Right", bases=["Base"]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union( @@ -290,7 +290,7 @@ def test_class_with_derived_and_single_property(generate, dir_param): schema.Class(name="Left", bases=["Base"]), schema.Class(name="Right", bases=["Base"]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union( @@ -330,7 +330,7 @@ def test_class_with_derived_and_optional_property(generate, dir_param): schema.Class(name="Left", bases=["Base"]), schema.Class(name="Right", bases=["Base"]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union( @@ -370,7 +370,7 @@ def test_class_with_derived_and_repeated_property(generate, dir_param): schema.Class(name="Left", bases=["Base"]), schema.Class(name="Right", bases=["Base"]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union( @@ -432,7 +432,7 @@ def test_null_class(generate): bases=["Base"], ), ], null="Null") == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union( @@ -514,7 +514,7 @@ def test_ipa_classes_ignored(generate): schema.Class(name="B", ipa=schema.IpaInfo(from_class="A")), schema.Class(name="C", ipa=schema.IpaInfo(on_arguments={"x": "A"})), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[], ) @@ -526,7 +526,7 @@ def test_ipa_derived_classes_ignored(generate): schema.Class(name="B", bases=["A"], ipa=schema.IpaInfo()), schema.Class(name="C", bases=["A"]), ]) == dbscheme.Scheme( - src=schema_file, + src=schema_file.name, includes=[], declarations=[ dbscheme.Union("@a", ["@c"]), diff --git a/swift/codegen/test/test_dbscheme.py b/misc/codegen/test/test_dbschemelaoder.py similarity index 67% rename from swift/codegen/test/test_dbscheme.py rename to misc/codegen/test/test_dbschemelaoder.py index 9d9184ea954..ab4efbff75a 100644 --- a/swift/codegen/test/test_dbscheme.py +++ b/misc/codegen/test/test_dbschemelaoder.py @@ -1,61 +1,18 @@ import sys from copy import deepcopy -from swift.codegen.lib import dbscheme -from swift.codegen.test.utils import * +from misc.codegen.lib import dbscheme +from misc.codegen.loaders.dbschemeloader import iterload +from misc.codegen.test.utils import * -def test_dbcolumn_name(): - assert dbscheme.Column("foo", "some_type").name == "foo" - - -@pytest.mark.parametrize("keyword", dbscheme.dbscheme_keywords) -def test_dbcolumn_keyword_name(keyword): - assert dbscheme.Column(keyword, "some_type").name == keyword + "_" - - -@pytest.mark.parametrize("type,binding,lhstype,rhstype", [ - ("builtin_type", False, "builtin_type", "builtin_type ref"), - ("builtin_type", True, "builtin_type", "builtin_type ref"), - ("@at_type", False, "int", "@at_type ref"), - ("@at_type", True, "unique int", "@at_type"), -]) -def test_dbcolumn_types(type, binding, lhstype, rhstype): - col = dbscheme.Column("foo", type, binding) - assert col.lhstype == lhstype - assert col.rhstype == rhstype - - -def test_keyset_has_first_id_marked(): - ids = ["a", "b", "c"] - ks = dbscheme.KeySet(ids) - assert ks.ids[0].first - assert [id.id for id in ks.ids] == ids - - -def test_table_has_first_column_marked(): - columns = [dbscheme.Column("a", "x"), dbscheme.Column("b", "y", binding=True), dbscheme.Column("c", "z")] - expected = deepcopy(columns) - table = dbscheme.Table("foo", columns) - expected[0].first = True - assert table.columns == expected - - -def test_union_has_first_case_marked(): - rhs = ["a", "b", "c"] - u = dbscheme.Union(lhs="x", rhs=rhs) - assert u.rhs[0].first - assert [c.type for c in u.rhs] == rhs - - -# load tests @pytest.fixture def load(tmp_path): file = tmp_path / "test.dbscheme" def ret(yml): write(file, yml) - return list(dbscheme.iterload(file)) + return list(iterload(file)) return ret diff --git a/swift/codegen/test/test_ql.py b/misc/codegen/test/test_ql.py similarity index 93% rename from swift/codegen/test/test_ql.py rename to misc/codegen/test/test_ql.py index 5f5b1aebd73..0006bbb96e4 100644 --- a/swift/codegen/test/test_ql.py +++ b/misc/codegen/test/test_ql.py @@ -1,8 +1,8 @@ import sys from copy import deepcopy -from swift.codegen.lib import ql -from swift.codegen.test.utils import * +from misc.codegen.lib import ql +from misc.codegen.test.utils import * def test_property_has_first_table_param_marked(): @@ -149,5 +149,12 @@ def test_class_without_description(): assert prop.has_description is False +def test_ipa_accessor_has_first_constructor_param_marked(): + params = ["a", "b", "c"] + x = ql.IpaUnderlyingAccessor("foo", "bar", params) + assert x.constructorparams[0].first + assert [p.param for p in x.constructorparams] == params + + if __name__ == '__main__': sys.exit(pytest.main([__file__] + sys.argv[1:])) diff --git a/swift/codegen/test/test_qlgen.py b/misc/codegen/test/test_qlgen.py similarity index 50% rename from swift/codegen/test/test_qlgen.py rename to misc/codegen/test/test_qlgen.py index 7a290ba76b8..f16b1404c2e 100644 --- a/swift/codegen/test/test_qlgen.py +++ b/misc/codegen/test/test_qlgen.py @@ -4,9 +4,9 @@ import sys import pytest -from swift.codegen.generators import qlgen -from swift.codegen.lib import ql -from swift.codegen.test.utils import * +from misc.codegen.generators import qlgen +from misc.codegen.lib import ql +from misc.codegen.test.utils import * @pytest.fixture(autouse=True) @@ -17,16 +17,16 @@ def run_mock(): # these are lambdas so that they will use patched paths when called -def stub_path(): return paths.swift_dir / "ql/lib/stub/path" +def stub_path(): return paths.root_dir / "ql/lib/stub/path" -def ql_output_path(): return paths.swift_dir / "ql/lib/other/path" +def ql_output_path(): return paths.root_dir / "ql/lib/other/path" -def ql_test_output_path(): return paths.swift_dir / "ql/test/path" +def ql_test_output_path(): return paths.root_dir / "ql/test/path" -def generated_registry_path(): return paths.swift_dir / "registry.list" +def generated_registry_path(): return paths.root_dir / "registry.list" def import_file(): return stub_path().with_suffix(".qll") @@ -35,9 +35,11 @@ def import_file(): return stub_path().with_suffix(".qll") def children_file(): return ql_output_path() / "ParentChild.qll" -stub_import_prefix = "stub.path." +stub_import = "stub.path" +stub_import_prefix = stub_import + "." root_import = stub_import_prefix + "Element" -gen_import_prefix = "other.path." +gen_import = "other.path" +gen_import_prefix = gen_import + "." @pytest.fixture @@ -47,7 +49,7 @@ def qlgen_opts(opts): opts.ql_test_output = ql_test_output_path() opts.generated_registry = generated_registry_path() opts.ql_format = True - opts.swift_dir = paths.swift_dir + opts.root_dir = paths.root_dir opts.force = False return opts @@ -133,12 +135,20 @@ def generate_tests(generate): return func +def a_ql_class(**kwargs): + return ql.Class(**kwargs, import_prefix=gen_import) + + +def a_ql_stub(**kwargs): + return ql.Stub(**kwargs, import_prefix=gen_import) + + def test_one_empty_class(generate_classes): assert generate_classes([ schema.Class("A") ]) == { - "A.qll": (ql.Stub(name="A", base_import=gen_import_prefix + "A"), - ql.Class(name="A", final=True)), + "A.qll": (a_ql_stub(name="A", base_import=gen_import_prefix + "A"), + a_ql_class(name="A", final=True)), } @@ -149,15 +159,15 @@ def test_hierarchy(generate_classes): schema.Class("B", bases=["A"], derived={"D"}), schema.Class("A", derived={"B", "C"}), ]) == { - "A.qll": (ql.Stub(name="A", base_import=gen_import_prefix + "A"), - ql.Class(name="A")), - "B.qll": (ql.Stub(name="B", base_import=gen_import_prefix + "B"), - ql.Class(name="B", bases=["A"], imports=[stub_import_prefix + "A"])), - "C.qll": (ql.Stub(name="C", base_import=gen_import_prefix + "C"), - ql.Class(name="C", bases=["A"], imports=[stub_import_prefix + "A"])), - "D.qll": (ql.Stub(name="D", base_import=gen_import_prefix + "D"), - ql.Class(name="D", final=True, bases=["B", "C"], - imports=[stub_import_prefix + cls for cls in "BC"])), + "A.qll": (a_ql_stub(name="A", base_import=gen_import_prefix + "A"), + a_ql_class(name="A")), + "B.qll": (a_ql_stub(name="B", base_import=gen_import_prefix + "B"), + a_ql_class(name="B", bases=["A"], imports=[stub_import_prefix + "A"])), + "C.qll": (a_ql_stub(name="C", base_import=gen_import_prefix + "C"), + a_ql_class(name="C", bases=["A"], imports=[stub_import_prefix + "A"])), + "D.qll": (a_ql_stub(name="D", base_import=gen_import_prefix + "D"), + a_ql_class(name="D", final=True, bases=["B", "C"], + imports=[stub_import_prefix + cls for cls in "BC"])), } @@ -186,15 +196,15 @@ def test_hierarchy_children(generate_children_implementations): schema.Class("C", bases=["A"], derived={"D"}, pragmas=["ql_internal"]), schema.Class("D", bases=["B", "C"]), ]) == ql.GetParentImplementation( - classes=[ql.Class(name="A", ql_internal=True), - ql.Class(name="B", bases=["A"], imports=[ + classes=[a_ql_class(name="A", ql_internal=True), + a_ql_class(name="B", bases=["A"], imports=[ stub_import_prefix + "A"]), - ql.Class(name="C", bases=["A"], imports=[ + a_ql_class(name="C", bases=["A"], imports=[ stub_import_prefix + "A"], ql_internal=True), - ql.Class(name="D", final=True, bases=["B", "C"], - imports=[stub_import_prefix + cls for cls in "BC"]), + a_ql_class(name="D", final=True, bases=["B", "C"], + imports=[stub_import_prefix + cls for cls in "BC"]), ], - additional_imports=[stub_import_prefix + cls for cls in "AC"], + imports=[stub_import] + [stub_import_prefix + cls for cls in "AC"], ) @@ -203,12 +213,12 @@ def test_single_property(generate_classes): schema.Class("MyObject", properties=[ schema.SingleProperty("foo", "bar")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_objects", - tableparams=["this", "result"], doc="foo of this my object"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_objects", + tableparams=["this", "result"], doc="foo of this my object"), + ])), } @@ -226,42 +236,45 @@ def test_children(generate_classes): schema.RepeatedOptionalProperty("child_4", "int", is_child=True), ]), ]) == { - "FakeRoot.qll": (ql.Stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), - ql.Class(name="FakeRoot", final=True)), - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="A", type="int", tablename="my_objects", - tableparams=["this", "result", "_"], - doc="a of this my object"), - ql.Property(singular="Child1", type="int", tablename="my_objects", - tableparams=["this", "_", "result"], prev_child="", - doc="child 1 of this my object"), - ql.Property(singular="B", plural="Bs", type="int", - tablename="my_object_bs", - tableparams=["this", "index", "result"], - doc="b of this my object", doc_plural="bs of this my object"), - ql.Property(singular="Child", plural="Children", type="int", - tablename="my_object_children", - tableparams=["this", "index", "result"], prev_child="Child1", - doc="child of this my object", - doc_plural="children of this my object"), - ql.Property(singular="C", type="int", tablename="my_object_cs", - tableparams=["this", "result"], is_optional=True, - doc="c of this my object"), - ql.Property(singular="Child3", type="int", tablename="my_object_child_3s", - tableparams=["this", "result"], is_optional=True, - prev_child="Child", doc="child 3 of this my object"), - ql.Property(singular="D", plural="Ds", type="int", - tablename="my_object_ds", - tableparams=["this", "index", "result"], is_optional=True, - doc="d of this my object", doc_plural="ds of this my object"), - ql.Property(singular="Child4", plural="Child4s", type="int", - tablename="my_object_child_4s", - tableparams=["this", "index", "result"], is_optional=True, - prev_child="Child3", doc="child 4 of this my object", - doc_plural="child 4s of this my object"), - ])), + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="A", type="int", tablename="my_objects", + tableparams=["this", "result", "_"], + doc="a of this my object"), + ql.Property(singular="Child1", type="int", tablename="my_objects", + tableparams=["this", "_", "result"], prev_child="", + doc="child 1 of this my object"), + ql.Property(singular="B", plural="Bs", type="int", + tablename="my_object_bs", + tableparams=["this", "index", "result"], + doc="b of this my object", + doc_plural="bs of this my object"), + ql.Property(singular="Child", plural="Children", type="int", + tablename="my_object_children", + tableparams=["this", "index", "result"], prev_child="Child1", + doc="child of this my object", + doc_plural="children of this my object"), + ql.Property(singular="C", type="int", tablename="my_object_cs", + tableparams=["this", "result"], is_optional=True, + doc="c of this my object"), + ql.Property(singular="Child3", type="int", + tablename="my_object_child_3s", + tableparams=["this", "result"], is_optional=True, + prev_child="Child", doc="child 3 of this my object"), + ql.Property(singular="D", plural="Ds", type="int", + tablename="my_object_ds", + tableparams=["this", "index", "result"], is_optional=True, + doc="d of this my object", + doc_plural="ds of this my object"), + ql.Property(singular="Child4", plural="Child4s", type="int", + tablename="my_object_child_4s", + tableparams=["this", "index", "result"], is_optional=True, + prev_child="Child3", doc="child 4 of this my object", + doc_plural="child 4s of this my object"), + ])), } @@ -273,19 +286,19 @@ def test_single_properties(generate_classes): schema.SingleProperty("three", "z"), ]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="One", type="x", tablename="my_objects", - tableparams=["this", "result", "_", "_"], - doc="one of this my object"), - ql.Property(singular="Two", type="y", tablename="my_objects", - tableparams=["this", "_", "result", "_"], - doc="two of this my object"), - ql.Property(singular="Three", type="z", tablename="my_objects", - tableparams=["this", "_", "_", "result"], - doc="three of this my object"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="One", type="x", tablename="my_objects", + tableparams=["this", "result", "_", "_"], + doc="one of this my object"), + ql.Property(singular="Two", type="y", tablename="my_objects", + tableparams=["this", "_", "result", "_"], + doc="two of this my object"), + ql.Property(singular="Three", type="z", tablename="my_objects", + tableparams=["this", "_", "_", "result"], + doc="three of this my object"), + ])), } @@ -296,14 +309,14 @@ def test_optional_property(generate_classes, is_child, prev_child): schema.Class("MyObject", properties=[ schema.OptionalProperty("foo", "bar", is_child=is_child)]), ]) == { - "FakeRoot.qll": (ql.Stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), - ql.Class(name="FakeRoot", final=True)), - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_object_foos", - tableparams=["this", "result"], - is_optional=True, prev_child=prev_child, doc="foo of this my object"), - ])), + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_object_foos", + tableparams=["this", "result"], + is_optional=True, prev_child=prev_child, doc="foo of this my object"), + ])), } @@ -314,14 +327,14 @@ def test_repeated_property(generate_classes, is_child, prev_child): schema.Class("MyObject", properties=[ schema.RepeatedProperty("foo", "bar", is_child=is_child)]), ]) == { - "FakeRoot.qll": (ql.Stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), - ql.Class(name="FakeRoot", final=True)), - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, properties=[ - ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", - tableparams=["this", "index", "result"], prev_child=prev_child, - doc="foo of this my object", doc_plural="foos of this my object"), - ])), + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ + ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", + tableparams=["this", "index", "result"], prev_child=prev_child, + doc="foo of this my object", doc_plural="foos of this my object"), + ])), } @@ -333,15 +346,15 @@ def test_repeated_optional_property(generate_classes, is_child, prev_child): schema.RepeatedOptionalProperty("foo", "bar", is_child=is_child)]), ]) == { - "FakeRoot.qll": (ql.Stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), - ql.Class(name="FakeRoot", final=True)), - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, properties=[ - ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", - tableparams=["this", "index", "result"], is_optional=True, - prev_child=prev_child, doc="foo of this my object", - doc_plural="foos of this my object"), - ])), + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ + ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", + tableparams=["this", "index", "result"], is_optional=True, + prev_child=prev_child, doc="foo of this my object", + doc_plural="foos of this my object"), + ])), } @@ -350,11 +363,11 @@ def test_predicate_property(generate_classes): schema.Class("MyObject", properties=[ schema.PredicateProperty("is_foo")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, properties=[ - ql.Property(singular="isFoo", type="predicate", tablename="my_object_is_foo", - tableparams=["this"], is_predicate=True, doc="this my object is foo"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ + ql.Property(singular="isFoo", type="predicate", tablename="my_object_is_foo", + tableparams=["this"], is_predicate=True, doc="this my object is foo"), + ])), } @@ -365,8 +378,8 @@ def test_single_class_property(generate_classes, is_child, prev_child): schema.Class("MyObject", properties=[ schema.SingleProperty("foo", "Bar", is_child=is_child)]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class( + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class( name="MyObject", final=True, imports=[stub_import_prefix + "Bar"], properties=[ ql.Property(singular="Foo", type="Bar", tablename="my_objects", tableparams=[ @@ -374,8 +387,8 @@ def test_single_class_property(generate_classes, is_child, prev_child): prev_child=prev_child, doc="foo of this my object"), ], )), - "Bar.qll": (ql.Stub(name="Bar", base_import=gen_import_prefix + "Bar"), - ql.Class(name="Bar", final=True)), + "Bar.qll": (a_ql_stub(name="Bar", base_import=gen_import_prefix + "Bar"), + a_ql_class(name="Bar", final=True)), } @@ -384,8 +397,8 @@ def test_class_with_doc(generate_classes): assert generate_classes([ schema.Class("A", doc=doc), ]) == { - "A.qll": (ql.Stub(name="A", base_import=gen_import_prefix + "A"), - ql.Class(name="A", final=True, doc=doc)), + "A.qll": (a_ql_stub(name="A", base_import=gen_import_prefix + "A"), + a_ql_class(name="A", final=True, doc=doc)), } @@ -395,11 +408,11 @@ def test_class_dir(generate_classes): schema.Class("A", derived={"B"}, group=dir), schema.Class("B", bases=["A"]), ]) == { - f"{dir}/A.qll": (ql.Stub(name="A", base_import=gen_import_prefix + "another.rel.path.A"), - ql.Class(name="A", dir=pathlib.Path(dir))), - "B.qll": (ql.Stub(name="B", base_import=gen_import_prefix + "B"), - ql.Class(name="B", final=True, bases=["A"], - imports=[stub_import_prefix + "another.rel.path.A"])), + f"{dir}/A.qll": (a_ql_stub(name="A", base_import=gen_import_prefix + "another.rel.path.A"), + a_ql_class(name="A", dir=pathlib.Path(dir))), + "B.qll": (a_ql_stub(name="B", base_import=gen_import_prefix + "B"), + a_ql_class(name="B", final=True, bases=["A"], + imports=[stub_import_prefix + "another.rel.path.A"])), } @@ -487,12 +500,20 @@ def test_test_missing_source(generate_tests): } +def a_ql_class_tester(**kwargs): + return ql.ClassTester(**kwargs, elements_module=stub_import) + + +def a_ql_property_tester(**kwargs): + return ql.PropertyTester(**kwargs, elements_module=stub_import) + + def test_test_source_present(opts, generate_tests): write(opts.ql_test_output / "A" / "test.swift") assert generate_tests([ schema.Class("A"), ]) == { - "A/A.ql": ql.ClassTester(class_name="A"), + "A/A.ql": a_ql_class_tester(class_name="A"), } @@ -501,7 +522,7 @@ def test_test_source_present_with_dir(opts, generate_tests): assert generate_tests([ schema.Class("A", group="foo"), ]) == { - "foo/A/A.ql": ql.ClassTester(class_name="A"), + "foo/A/A.ql": a_ql_class_tester(class_name="A"), } @@ -515,7 +536,7 @@ def test_test_total_properties(opts, generate_tests): schema.PredicateProperty("y", "int"), ]), ]) == { - "B/B.ql": ql.ClassTester(class_name="B", properties=[ + "B/B.ql": a_ql_class_tester(class_name="B", properties=[ ql.PropertyForTest(getter="getX", type="string"), ql.PropertyForTest(getter="y"), ]) @@ -533,21 +554,21 @@ def test_test_partial_properties(opts, generate_tests): schema.RepeatedOptionalProperty("z", "int"), ]), ]) == { - "B/B.ql": ql.ClassTester(class_name="B", properties=[ + "B/B.ql": a_ql_class_tester(class_name="B", properties=[ ql.PropertyForTest(getter="hasX"), ql.PropertyForTest(getter="getNumberOfYs", type="int"), ]), - "B/B_getX.ql": ql.PropertyTester(class_name="B", - property=ql.PropertyForTest(getter="getX", is_total=False, - type="string")), - "B/B_getY.ql": ql.PropertyTester(class_name="B", - property=ql.PropertyForTest(getter="getY", is_total=False, - is_repeated=True, - type="bool")), - "B/B_getZ.ql": ql.PropertyTester(class_name="B", - property=ql.PropertyForTest(getter="getZ", is_total=False, - is_repeated=True, - type="int")), + "B/B_getX.ql": a_ql_property_tester(class_name="B", + property=ql.PropertyForTest(getter="getX", is_total=False, + type="string")), + "B/B_getY.ql": a_ql_property_tester(class_name="B", + property=ql.PropertyForTest(getter="getY", is_total=False, + is_repeated=True, + type="bool")), + "B/B_getZ.ql": a_ql_property_tester(class_name="B", + property=ql.PropertyForTest(getter="getZ", is_total=False, + is_repeated=True, + type="int")), } @@ -562,14 +583,14 @@ def test_test_properties_deduplicated(opts, generate_tests): schema.Class("B", bases=["Base"], derived={"Final"}), schema.Class("Final", bases=["A", "B"]), ]) == { - "Final/Final.ql": ql.ClassTester(class_name="Final", properties=[ + "Final/Final.ql": a_ql_class_tester(class_name="Final", properties=[ ql.PropertyForTest(getter="getX", type="string"), ql.PropertyForTest(getter="getNumberOfYs", type="int"), ]), - "Final/Final_getY.ql": ql.PropertyTester(class_name="Final", - property=ql.PropertyForTest(getter="getY", is_total=False, - is_repeated=True, - type="bool")), + "Final/Final_getY.ql": a_ql_property_tester(class_name="Final", + property=ql.PropertyForTest(getter="getY", is_total=False, + is_repeated=True, + type="bool")), } @@ -586,7 +607,7 @@ def test_test_properties_skipped(opts, generate_tests): "b", "int", pragmas=["bar", "qltest_skip", "baz"]), ]), ]) == { - "Derived/Derived.ql": ql.ClassTester(class_name="Derived"), + "Derived/Derived.ql": a_ql_class_tester(class_name="Derived"), } @@ -599,7 +620,7 @@ def test_test_base_class_skipped(opts, generate_tests): ]), schema.Class("Derived", bases=["Base"]), ]) == { - "Derived/Derived.ql": ql.ClassTester(class_name="Derived"), + "Derived/Derived.ql": a_ql_class_tester(class_name="Derived"), } @@ -622,7 +643,7 @@ def test_test_class_hierarchy_collapse(opts, generate_tests): schema.Class("D2", bases=["Base"], derived={"D3"}, properties=[schema.SingleProperty("y", "string")]), schema.Class("D3", bases=["D2"], properties=[schema.SingleProperty("z", "string")]), ]) == { - "Base/Base.ql": ql.ClassTester(class_name="Base", show_ql_class=True), + "Base/Base.ql": a_ql_class_tester(class_name="Base", show_ql_class=True), } @@ -636,9 +657,9 @@ def test_test_class_hierarchy_uncollapse(opts, generate_tests): schema.Class("D3", bases=["D2"]), schema.Class("D4", bases=["D2"]), ]) == { - "Base/Base.ql": ql.ClassTester(class_name="Base", show_ql_class=True), - "D3/D3.ql": ql.ClassTester(class_name="D3"), - "D4/D4.ql": ql.ClassTester(class_name="D4"), + "Base/Base.ql": a_ql_class_tester(class_name="Base", show_ql_class=True), + "D3/D3.ql": a_ql_class_tester(class_name="D3"), + "D4/D4.ql": a_ql_class_tester(class_name="D4"), } @@ -651,8 +672,8 @@ def test_test_class_hierarchy_uncollapse_at_final(opts, generate_tests): schema.Class("D2", bases=["Base"], derived={"D3"}), schema.Class("D3", bases=["D2"], pragmas=["qltest_uncollapse_hierarchy", "bar"]), ]) == { - "Base/Base.ql": ql.ClassTester(class_name="Base", show_ql_class=True), - "D3/D3.ql": ql.ClassTester(class_name="D3"), + "Base/Base.ql": a_ql_class_tester(class_name="Base", show_ql_class=True), + "D3/D3.ql": a_ql_class_tester(class_name="D3"), } @@ -663,14 +684,14 @@ def test_property_description(generate_classes): schema.SingleProperty("foo", "bar", description=description), ]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_objects", - tableparams=["this", "result"], - doc="foo of this my object", - description=description), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_objects", + tableparams=["this", "result"], + doc="foo of this my object", + description=description), + ])), } @@ -679,12 +700,12 @@ def test_property_doc_override(generate_classes): schema.Class("MyObject", properties=[ schema.SingleProperty("foo", "bar", doc="baz")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_objects", - tableparams=["this", "result"], doc="baz"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_objects", + tableparams=["this", "result"], doc="baz"), + ])), } @@ -694,18 +715,18 @@ def test_repeated_property_doc_override(generate_classes): schema.RepeatedProperty("x", "int", doc="children of this"), schema.RepeatedOptionalProperty("y", "int", doc="child of this")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="X", plural="Xes", type="int", - tablename="my_object_xes", - tableparams=["this", "index", "result"], - doc="child of this", doc_plural="children of this"), - ql.Property(singular="Y", plural="Ys", type="int", - tablename="my_object_ies", is_optional=True, - tableparams=["this", "index", "result"], - doc="child of this", doc_plural="children of this"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="X", plural="Xes", type="int", + tablename="my_object_xes", + tableparams=["this", "index", "result"], + doc="child of this", doc_plural="children of this"), + ql.Property(singular="Y", plural="Ys", type="int", + tablename="my_object_ies", is_optional=True, + tableparams=["this", "index", "result"], + doc="child of this", doc_plural="children of this"), + ])), } @@ -716,13 +737,13 @@ def test_property_doc_abbreviations(generate_classes, abbr, expected): schema.Class("Object", properties=[ schema.SingleProperty(f"foo_{abbr}_bar", "baz")]), ]) == { - "Object.qll": (ql.Stub(name="Object", base_import=gen_import_prefix + "Object"), - ql.Class(name="Object", final=True, - properties=[ - ql.Property(singular=f"Foo{abbr.capitalize()}Bar", type="baz", - tablename="objects", - tableparams=["this", "result"], doc=expected_doc), - ])), + "Object.qll": (a_ql_stub(name="Object", base_import=gen_import_prefix + "Object"), + a_ql_class(name="Object", final=True, + properties=[ + ql.Property(singular=f"Foo{abbr.capitalize()}Bar", type="baz", + tablename="objects", + tableparams=["this", "result"], doc=expected_doc), + ])), } @@ -733,13 +754,13 @@ def test_property_doc_abbreviations_ignored_if_within_word(generate_classes, abb schema.Class("Object", properties=[ schema.SingleProperty(f"foo_{abbr}acadabra_bar", "baz")]), ]) == { - "Object.qll": (ql.Stub(name="Object", base_import=gen_import_prefix + "Object"), - ql.Class(name="Object", final=True, - properties=[ - ql.Property(singular=f"Foo{abbr.capitalize()}acadabraBar", type="baz", - tablename="objects", - tableparams=["this", "result"], doc=expected_doc), - ])), + "Object.qll": (a_ql_stub(name="Object", base_import=gen_import_prefix + "Object"), + a_ql_class(name="Object", final=True, + properties=[ + ql.Property(singular=f"Foo{abbr.capitalize()}acadabraBar", type="baz", + tablename="objects", + tableparams=["this", "result"], doc=expected_doc), + ])), } @@ -749,20 +770,20 @@ def test_repeated_property_doc_override_with_format(generate_classes): schema.RepeatedProperty("x", "int", doc="special {children} of this"), schema.RepeatedOptionalProperty("y", "int", doc="special {child} of this")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="X", plural="Xes", type="int", - tablename="my_object_xes", - tableparams=["this", "index", "result"], - doc="special child of this", - doc_plural="special children of this"), - ql.Property(singular="Y", plural="Ys", type="int", - tablename="my_object_ies", is_optional=True, - tableparams=["this", "index", "result"], - doc="special child of this", - doc_plural="special children of this"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="X", plural="Xes", type="int", + tablename="my_object_xes", + tableparams=["this", "index", "result"], + doc="special child of this", + doc_plural="special children of this"), + ql.Property(singular="Y", plural="Ys", type="int", + tablename="my_object_ies", is_optional=True, + tableparams=["this", "index", "result"], + doc="special child of this", + doc_plural="special children of this"), + ])), } @@ -772,18 +793,18 @@ def test_repeated_property_doc_override_with_multiple_formats(generate_classes): schema.RepeatedProperty("x", "int", doc="{cat} or {dog}"), schema.RepeatedOptionalProperty("y", "int", doc="{cats} or {dogs}")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="X", plural="Xes", type="int", - tablename="my_object_xes", - tableparams=["this", "index", "result"], - doc="cat or dog", doc_plural="cats or dogs"), - ql.Property(singular="Y", plural="Ys", type="int", - tablename="my_object_ies", is_optional=True, - tableparams=["this", "index", "result"], - doc="cat or dog", doc_plural="cats or dogs"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="X", plural="Xes", type="int", + tablename="my_object_xes", + tableparams=["this", "index", "result"], + doc="cat or dog", doc_plural="cats or dogs"), + ql.Property(singular="Y", plural="Ys", type="int", + tablename="my_object_ies", is_optional=True, + tableparams=["this", "index", "result"], + doc="cat or dog", doc_plural="cats or dogs"), + ])), } @@ -792,12 +813,12 @@ def test_property_doc_override_with_format(generate_classes): schema.Class("MyObject", properties=[ schema.SingleProperty("foo", "bar", doc="special {baz} of this")]), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_objects", - tableparams=["this", "result"], doc="special baz of this"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_objects", + tableparams=["this", "result"], doc="special baz of this"), + ])), } @@ -807,12 +828,36 @@ def test_property_on_class_with_default_doc_name(generate_classes): schema.SingleProperty("foo", "bar")], default_doc_name="baz"), ]) == { - "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - ql.Class(name="MyObject", final=True, - properties=[ - ql.Property(singular="Foo", type="bar", tablename="my_objects", - tableparams=["this", "result"], doc="foo of this baz"), - ])), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, + properties=[ + ql.Property(singular="Foo", type="bar", tablename="my_objects", + tableparams=["this", "result"], doc="foo of this baz"), + ])), + } + + +def test_stub_on_class_with_ipa_from_class(generate_classes): + assert generate_classes([ + schema.Class("MyObject", ipa=schema.IpaInfo(from_class="A")), + ]) == { + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject", ipa_accessors=[ + ql.IpaUnderlyingAccessor(argument="Entity", type="Raw::A", constructorparams=["result"]), + ]), + a_ql_class(name="MyObject", final=True, ipa=True)), + } + + +def test_stub_on_class_with_ipa_on_arguments(generate_classes): + assert generate_classes([ + schema.Class("MyObject", ipa=schema.IpaInfo(on_arguments={"base": "A", "index": "int", "label": "string"})), + ]) == { + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject", ipa_accessors=[ + ql.IpaUnderlyingAccessor(argument="Base", type="Raw::A", constructorparams=["result", "_", "_"]), + ql.IpaUnderlyingAccessor(argument="Index", type="int", constructorparams=["_", "result", "_"]), + ql.IpaUnderlyingAccessor(argument="Label", type="string", constructorparams=["_", "_", "result"]), + ]), + a_ql_class(name="MyObject", final=True, ipa=True)), } diff --git a/swift/codegen/test/test_render.py b/misc/codegen/test/test_render.py similarity index 75% rename from swift/codegen/test/test_render.py rename to misc/codegen/test/test_render.py index 950ca385e2f..f9129178f04 100644 --- a/swift/codegen/test/test_render.py +++ b/misc/codegen/test/test_render.py @@ -2,10 +2,12 @@ import sys import pytest -from swift.codegen.test.utils import * +from misc.codegen.test.utils import * import hashlib +generator = "foo" + @pytest.fixture def pystache_renderer_cls(): @@ -22,7 +24,7 @@ def pystache_renderer(pystache_renderer_cls): @pytest.fixture def sut(pystache_renderer): - return render.Renderer(paths.swift_dir) + return render.Renderer(generator, paths.root_dir) def assert_file(file, text): @@ -48,12 +50,12 @@ def test_render(pystache_renderer, sut): data = mock.Mock(spec=("template",)) text = "some text" pystache_renderer.render_name.side_effect = (text,) - output = paths.swift_dir / "some/output.txt" + output = paths.root_dir / "some/output.txt" sut.render(data, output) assert_file(output, text) assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] @@ -61,8 +63,8 @@ def test_managed_render(pystache_renderer, sut): data = mock.Mock(spec=("template",)) text = "some text" pystache_renderer.render_name.side_effect = (text,) - output = paths.swift_dir / "some/output.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + registry = paths.root_dir / "a/registry.list" write(registry) with sut.manage(generated=(), stubs=(), registry=registry) as renderer: @@ -72,7 +74,7 @@ def test_managed_render(pystache_renderer, sut): assert_file(registry, f"some/output.txt {hash(text)} {hash(text)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] @@ -80,8 +82,8 @@ def test_managed_render_with_no_registry(pystache_renderer, sut): data = mock.Mock(spec=("template",)) text = "some text" pystache_renderer.render_name.side_effect = (text,) - output = paths.swift_dir / "some/output.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + registry = paths.root_dir / "a/registry.list" with sut.manage(generated=(), stubs=(), registry=registry) as renderer: renderer.render(data, output) @@ -90,7 +92,7 @@ def test_managed_render_with_no_registry(pystache_renderer, sut): assert_file(registry, f"some/output.txt {hash(text)} {hash(text)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] @@ -99,8 +101,8 @@ def test_managed_render_with_post_processing(pystache_renderer, sut): text = "some text" postprocessed_text = "some other text" pystache_renderer.render_name.side_effect = (text,) - output = paths.swift_dir / "some/output.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + registry = paths.root_dir / "a/registry.list" write(registry) with sut.manage(generated=(), stubs=(), registry=registry) as renderer: @@ -111,14 +113,14 @@ def test_managed_render_with_post_processing(pystache_renderer, sut): assert_file(registry, f"some/output.txt {hash(text)} {hash(postprocessed_text)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] def test_managed_render_with_erasing(pystache_renderer, sut): - output = paths.swift_dir / "some/output.txt" - stub = paths.swift_dir / "some/stub.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + stub = paths.root_dir / "some/stub.txt" + registry = paths.root_dir / "a/registry.list" write(output) write(stub, "// generated bla bla") write(registry) @@ -134,9 +136,9 @@ def test_managed_render_with_erasing(pystache_renderer, sut): def test_managed_render_with_skipping_of_generated_file(pystache_renderer, sut): data = mock.Mock(spec=("template",)) - output = paths.swift_dir / "some/output.txt" + output = paths.root_dir / "some/output.txt" some_output = "some output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(output, some_output) write(registry, f"some/output.txt {hash(some_output)} {hash(some_output)}\n") @@ -149,16 +151,16 @@ def test_managed_render_with_skipping_of_generated_file(pystache_renderer, sut): assert_file(registry, f"some/output.txt {hash(some_output)} {hash(some_output)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] def test_managed_render_with_skipping_of_stub_file(pystache_renderer, sut): data = mock.Mock(spec=("template",)) - stub = paths.swift_dir / "some/stub.txt" + stub = paths.root_dir / "some/stub.txt" some_output = "// generated some output" some_processed_output = "// generated some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(stub, some_processed_output) write(registry, f"some/stub.txt {hash(some_output)} {hash(some_processed_output)}\n") @@ -171,14 +173,14 @@ def test_managed_render_with_skipping_of_stub_file(pystache_renderer, sut): assert_file(registry, f"some/stub.txt {hash(some_output)} {hash(some_processed_output)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] def test_managed_render_with_modified_generated_file(pystache_renderer, sut): - output = paths.swift_dir / "some/output.txt" + output = paths.root_dir / "some/output.txt" some_processed_output = "// some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(output, "// something else") write(registry, f"some/output.txt whatever {hash(some_processed_output)}\n") @@ -187,9 +189,9 @@ def test_managed_render_with_modified_generated_file(pystache_renderer, sut): def test_managed_render_with_modified_stub_file_still_marked_as_generated(pystache_renderer, sut): - stub = paths.swift_dir / "some/stub.txt" + stub = paths.root_dir / "some/stub.txt" some_processed_output = "// generated some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(stub, "// generated something else") write(registry, f"some/stub.txt whatever {hash(some_processed_output)}\n") @@ -198,9 +200,9 @@ def test_managed_render_with_modified_stub_file_still_marked_as_generated(pystac def test_managed_render_with_modified_stub_file_not_marked_as_generated(pystache_renderer, sut): - stub = paths.swift_dir / "some/stub.txt" + stub = paths.root_dir / "some/stub.txt" some_processed_output = "// generated some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(stub, "// no more generated") write(registry, f"some/stub.txt whatever {hash(some_processed_output)}\n") @@ -214,29 +216,46 @@ class MyError(Exception): pass -def test_managed_render_exception_drops_written_from_registry(pystache_renderer, sut): +def test_managed_render_exception_drops_written_and_inexsistent_from_registry(pystache_renderer, sut): data = mock.Mock(spec=("template",)) text = "some text" pystache_renderer.render_name.side_effect = (text,) - output = paths.swift_dir / "some/output.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + registry = paths.root_dir / "x/registry.list" write(output, text) + write(paths.root_dir / "a") + write(paths.root_dir / "c") write(registry, "a a a\n" f"some/output.txt whatever {hash(text)}\n" - "b b b") + "b b b\n" + "c c c") with pytest.raises(MyError): with sut.manage(generated=(), stubs=(), registry=registry) as renderer: renderer.render(data, output) raise MyError - assert_file(registry, "a a a\nb b b\n") + assert_file(registry, "a a a\nc c c\n") + + +def test_managed_render_drops_inexsistent_from_registry(pystache_renderer, sut): + registry = paths.root_dir / "x/registry.list" + write(paths.root_dir / "a") + write(paths.root_dir / "c") + write(registry, f"a {hash('')} {hash('')}\n" + "b b b\n" + f"c {hash('')} {hash('')}") + + with sut.manage(generated=(), stubs=(), registry=registry): + pass + + assert_file(registry, f"a {hash('')} {hash('')}\nc {hash('')} {hash('')}\n") def test_managed_render_exception_does_not_erase(pystache_renderer, sut): - output = paths.swift_dir / "some/output.txt" - stub = paths.swift_dir / "some/stub.txt" - registry = paths.swift_dir / "a/registry.list" + output = paths.root_dir / "some/output.txt" + stub = paths.root_dir / "some/stub.txt" + registry = paths.root_dir / "a/registry.list" write(output) write(stub, "// generated bla bla") write(registry) @@ -260,7 +279,7 @@ def test_render_with_extensions(pystache_renderer, sut): sut.render(data, output) expected_templates = ["test_template_foo", "test_template_bar", "test_template_baz"] assert pystache_renderer.mock_calls == [ - mock.call.render_name(t, data, generator=paths.exe_file.relative_to(paths.swift_dir)) + mock.call.render_name(t, data, generator=generator) for t in expected_templates ] for expected_output, expected_contents in zip(expected_outputs, rendered): @@ -269,9 +288,9 @@ def test_render_with_extensions(pystache_renderer, sut): def test_managed_render_with_force_not_skipping_generated_file(pystache_renderer, sut): data = mock.Mock(spec=("template",)) - output = paths.swift_dir / "some/output.txt" + output = paths.root_dir / "some/output.txt" some_output = "some output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(output, some_output) write(registry, f"some/output.txt {hash(some_output)} {hash(some_output)}\n") @@ -284,16 +303,16 @@ def test_managed_render_with_force_not_skipping_generated_file(pystache_renderer assert_file(registry, f"some/output.txt {hash(some_output)} {hash(some_output)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] def test_managed_render_with_force_not_skipping_stub_file(pystache_renderer, sut): data = mock.Mock(spec=("template",)) - stub = paths.swift_dir / "some/stub.txt" + stub = paths.root_dir / "some/stub.txt" some_output = "// generated some output" some_processed_output = "// generated some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(stub, some_processed_output) write(registry, f"some/stub.txt {hash(some_output)} {hash(some_processed_output)}\n") @@ -306,14 +325,14 @@ def test_managed_render_with_force_not_skipping_stub_file(pystache_renderer, sut assert_file(registry, f"some/stub.txt {hash(some_output)} {hash(some_output)}\n") assert pystache_renderer.mock_calls == [ - mock.call.render_name(data.template, data, generator=paths.exe_file.relative_to(paths.swift_dir)), + mock.call.render_name(data.template, data, generator=generator), ] def test_managed_render_with_force_ignores_modified_generated_file(sut): - output = paths.swift_dir / "some/output.txt" + output = paths.root_dir / "some/output.txt" some_processed_output = "// some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(output, "// something else") write(registry, f"some/output.txt whatever {hash(some_processed_output)}\n") @@ -322,9 +341,9 @@ def test_managed_render_with_force_ignores_modified_generated_file(sut): def test_managed_render_with_force_ignores_modified_stub_file_still_marked_as_generated(sut): - stub = paths.swift_dir / "some/stub.txt" + stub = paths.root_dir / "some/stub.txt" some_processed_output = "// generated some processed output" - registry = paths.swift_dir / "a/registry.list" + registry = paths.root_dir / "a/registry.list" write(stub, "// generated something else") write(registry, f"some/stub.txt whatever {hash(some_processed_output)}\n") diff --git a/swift/codegen/test/test_schema.py b/misc/codegen/test/test_schemaloader.py similarity index 94% rename from swift/codegen/test/test_schema.py rename to misc/codegen/test/test_schemaloader.py index b5f5f7d1c1a..9724a82da8f 100644 --- a/swift/codegen/test/test_schema.py +++ b/misc/codegen/test/test_schemaloader.py @@ -2,12 +2,13 @@ import sys import pytest -from swift.codegen.test.utils import * -from swift.codegen.lib.schema import defs +from misc.codegen.test.utils import * +from misc.codegen.lib import schemadefs as defs +from misc.codegen.loaders.schemaloader import load def test_empty_schema(): - @schema.load + @load class data: pass @@ -18,7 +19,7 @@ def test_empty_schema(): def test_one_empty_class(): - @schema.load + @load class data: class MyClass: pass @@ -30,7 +31,7 @@ def test_one_empty_class(): def test_two_empty_classes(): - @schema.load + @load class data: class MyClass1: pass @@ -50,7 +51,7 @@ def test_no_external_bases(): pass with pytest.raises(schema.Error): - @schema.load + @load class data: class MyClass(A): pass @@ -58,7 +59,7 @@ def test_no_external_bases(): def test_no_multiple_roots(): with pytest.raises(schema.Error): - @schema.load + @load class data: class MyClass1: pass @@ -68,7 +69,7 @@ def test_no_multiple_roots(): def test_empty_classes_diamond(): - @schema.load + @load class data: class A: pass @@ -92,7 +93,7 @@ def test_empty_classes_diamond(): # def test_group(): - @schema.load + @load class data: @defs.group("xxx") class A: @@ -104,7 +105,7 @@ def test_group(): def test_group_is_inherited(): - @schema.load + @load class data: class A: pass @@ -129,7 +130,7 @@ def test_group_is_inherited(): def test_no_mixed_groups_in_bases(): with pytest.raises(schema.Error): - @schema.load + @load class data: class A: pass @@ -151,14 +152,14 @@ def test_no_mixed_groups_in_bases(): def test_lowercase_rejected(): with pytest.raises(schema.Error): - @schema.load + @load class data: class aLowerCase: pass def test_properties(): - @schema.load + @load class data: class A: one: defs.string @@ -182,7 +183,7 @@ def test_class_properties(): class A: pass - @schema.load + @load class data: class A: pass @@ -205,7 +206,7 @@ def test_class_properties(): def test_string_reference_class_properties(): - @schema.load + @load class data: class A: one: "A" @@ -227,14 +228,14 @@ def test_string_reference_class_properties(): lambda t: defs.list[defs.optional[t]]]) def test_string_reference_dangling(spec): with pytest.raises(schema.Error): - @schema.load + @load class data: class A: x: spec("B") def test_children(): - @schema.load + @load class data: class A: one: "A" | defs.child @@ -255,7 +256,7 @@ def test_children(): @pytest.mark.parametrize("spec", [defs.string, defs.int, defs.boolean, defs.predicate]) def test_builtin_and_predicate_children_not_allowed(spec): with pytest.raises(schema.Error): - @schema.load + @load class data: class A: x: spec | defs.child @@ -271,7 +272,7 @@ _pragmas = [(defs.qltest.skip, "qltest_skip"), @pytest.mark.parametrize("pragma,expected", _pragmas) def test_property_with_pragma(pragma, expected): - @schema.load + @load class data: class A: x: defs.string | pragma @@ -288,7 +289,7 @@ def test_property_with_pragmas(): for pragma, _ in _pragmas: spec |= pragma - @schema.load + @load class data: class A: x: spec @@ -302,7 +303,7 @@ def test_property_with_pragmas(): @pytest.mark.parametrize("pragma,expected", _pragmas) def test_class_with_pragma(pragma, expected): - @schema.load + @load class data: @pragma class A: @@ -318,7 +319,7 @@ def test_class_with_pragmas(): for p, _ in _pragmas: p(cls) - @schema.load + @load class data: class A: pass @@ -331,7 +332,7 @@ def test_class_with_pragmas(): def test_ipa_from_class(): - @schema.load + @load class data: class A: pass @@ -347,7 +348,7 @@ def test_ipa_from_class(): def test_ipa_from_class_ref(): - @schema.load + @load class data: @defs.synth.from_class("B") class A: @@ -364,7 +365,7 @@ def test_ipa_from_class_ref(): def test_ipa_from_class_dangling(): with pytest.raises(schema.Error): - @schema.load + @load class data: @defs.synth.from_class("X") class A: @@ -372,7 +373,7 @@ def test_ipa_from_class_dangling(): def test_ipa_class_on(): - @schema.load + @load class data: class A: pass @@ -391,7 +392,7 @@ def test_ipa_class_on_ref(): class A: pass - @schema.load + @load class data: @defs.synth.on_arguments(b="B", i=defs.int) class A: @@ -408,7 +409,7 @@ def test_ipa_class_on_ref(): def test_ipa_class_on_dangling(): with pytest.raises(schema.Error): - @schema.load + @load class data: @defs.synth.on_arguments(s=defs.string, a="A", i=defs.int) class B: @@ -416,7 +417,7 @@ def test_ipa_class_on_dangling(): def test_ipa_class_hierarchy(): - @schema.load + @load class data: class Root: pass @@ -449,7 +450,7 @@ def test_ipa_class_hierarchy(): def test_class_docstring(): - @schema.load + @load class data: class A: """Very important class.""" @@ -460,7 +461,7 @@ def test_class_docstring(): def test_property_docstring(): - @schema.load + @load class data: class A: x: int | defs.desc("very important property.") @@ -471,7 +472,7 @@ def test_property_docstring(): def test_class_docstring_newline(): - @schema.load + @load class data: class A: """Very important @@ -483,7 +484,7 @@ def test_class_docstring_newline(): def test_property_docstring_newline(): - @schema.load + @load class data: class A: x: int | defs.desc("""very important @@ -496,7 +497,7 @@ def test_property_docstring_newline(): def test_class_docstring_stripped(): - @schema.load + @load class data: class A: """ @@ -511,7 +512,7 @@ def test_class_docstring_stripped(): def test_property_docstring_stripped(): - @schema.load + @load class data: class A: x: int | defs.desc(""" @@ -526,7 +527,7 @@ def test_property_docstring_stripped(): def test_class_docstring_split(): - @schema.load + @load class data: class A: """Very important class. @@ -539,7 +540,7 @@ def test_class_docstring_split(): def test_property_docstring_split(): - @schema.load + @load class data: class A: x: int | defs.desc("""very important property. @@ -553,7 +554,7 @@ def test_property_docstring_split(): def test_class_docstring_indent(): - @schema.load + @load class data: class A: """ @@ -567,7 +568,7 @@ def test_class_docstring_indent(): def test_property_docstring_indent(): - @schema.load + @load class data: class A: x: int | defs.desc(""" @@ -582,7 +583,7 @@ def test_property_docstring_indent(): def test_property_doc_override(): - @schema.load + @load class data: class A: x: int | defs.doc("y") @@ -595,7 +596,7 @@ def test_property_doc_override(): def test_property_doc_override_no_newlines(): with pytest.raises(schema.Error): - @schema.load + @load class data: class A: x: int | defs.doc("no multiple\nlines") @@ -603,14 +604,14 @@ def test_property_doc_override_no_newlines(): def test_property_doc_override_no_trailing_dot(): with pytest.raises(schema.Error): - @schema.load + @load class data: class A: x: int | defs.doc("no dots please.") def test_class_default_doc_name(): - @schema.load + @load class data: @defs.ql.default_doc_name("b") class A: @@ -622,7 +623,7 @@ def test_class_default_doc_name(): def test_null_class(): - @schema.load + @load class data: class Root: pass @@ -641,7 +642,7 @@ def test_null_class(): def test_null_class_cannot_be_derived(): with pytest.raises(schema.Error): - @schema.load + @load class data: class Root: pass @@ -656,7 +657,7 @@ def test_null_class_cannot_be_derived(): def test_null_class_cannot_be_defined_multiple_times(): with pytest.raises(schema.Error): - @schema.load + @load class data: class Root: pass @@ -672,7 +673,7 @@ def test_null_class_cannot_be_defined_multiple_times(): def test_uppercase_acronyms_are_rejected(): with pytest.raises(schema.Error): - @schema.load + @load class data: class Root: pass diff --git a/swift/codegen/test/test_trapgen.py b/misc/codegen/test/test_trapgen.py similarity index 97% rename from swift/codegen/test/test_trapgen.py rename to misc/codegen/test/test_trapgen.py index c8121ce48ba..a81f40e0dd8 100644 --- a/swift/codegen/test/test_trapgen.py +++ b/misc/codegen/test/test_trapgen.py @@ -1,8 +1,8 @@ import sys -from swift.codegen.generators import trapgen -from swift.codegen.lib import cpp, dbscheme -from swift.codegen.test.utils import * +from misc.codegen.generators import trapgen +from misc.codegen.lib import cpp, dbscheme +from misc.codegen.test.utils import * output_dir = pathlib.Path("path", "to", "output") diff --git a/swift/codegen/test/utils.py b/misc/codegen/test/utils.py similarity index 82% rename from swift/codegen/test/utils.py rename to misc/codegen/test/utils.py index 3911206bfa5..e33500711f2 100644 --- a/swift/codegen/test/utils.py +++ b/misc/codegen/test/utils.py @@ -3,7 +3,7 @@ from unittest import mock import pytest -from swift.codegen.lib import render, schema, paths +from misc.codegen.lib import render, schema, paths schema_dir = pathlib.Path("a", "dir") schema_file = schema_dir / "schema.py" @@ -33,21 +33,21 @@ def render_manager(renderer): @pytest.fixture def opts(): ret = mock.MagicMock() - ret.swift_dir = paths.swift_dir + ret.root_dir = paths.root_dir return ret @pytest.fixture(autouse=True) def override_paths(tmp_path): - with mock.patch("swift.codegen.lib.paths.swift_dir", tmp_path), \ - mock.patch("swift.codegen.lib.paths.exe_file", tmp_path / "exe"): + with mock.patch("misc.codegen.lib.paths.root_dir", tmp_path), \ + mock.patch("misc.codegen.lib.paths.exe_file", tmp_path / "exe"): yield @pytest.fixture def input(opts, tmp_path): opts.schema = tmp_path / schema_file - with mock.patch("swift.codegen.lib.schema.load_file") as load_mock: + with mock.patch("misc.codegen.loaders.schemaloader.load_file") as load_mock: load_mock.return_value = schema.Schema([]) yield load_mock.return_value assert load_mock.mock_calls == [ @@ -58,7 +58,7 @@ def input(opts, tmp_path): @pytest.fixture def dbscheme_input(opts, tmp_path): opts.dbscheme = tmp_path / dbscheme_file - with mock.patch("swift.codegen.lib.dbscheme.iterload") as load_mock: + with mock.patch("misc.codegen.loaders.dbschemeloader.iterload") as load_mock: load_mock.entities = [] load_mock.side_effect = lambda _: load_mock.entities yield load_mock diff --git a/misc/scripts/shared-code-metrics.py b/misc/scripts/shared-code-metrics.py new file mode 100644 index 00000000000..bfc613e5c87 --- /dev/null +++ b/misc/scripts/shared-code-metrics.py @@ -0,0 +1,330 @@ +#!/bin/env python3 +# Generates a report on the amount of code sharing in this repo +# +# The purpose of this is +# a) To be able to understand the structure and dependencies +# b) To provide a metric that measures the amount of shared vs non-shared code + +import datetime +from pathlib import Path +import json +import yaml + +# To add more languages, add them to this list: +languages = ['cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ql', 'ruby', 'swift'] + +repo_location = Path(__file__).parent.parent.parent + +# Gets the total number of lines in a file +def linecount(file): + with open(file, 'r') as fp: return len(fp.readlines()) + +# Gets the language name from the path +def get_language(path): + return path.parts[len(repo_location.parts)] + +# Is this path a CodeQL query file +def is_query(path): + return path.suffix == '.ql' + +# Is this path a CodeQL library file +def is_library(path): + return path.suffix == '.qll' + +# Is this path a relevant CodeQL file +def is_ql(path): + return is_query(path) or is_library(path) + +# Is this file a CodeQL package file +def is_package(path): + return path.name == 'qlpack.yml' + +# A CodeQL source file +class QlFile: + def __init__(self, path): + self.path = path + self.lines = linecount(path) + shared = False + + def language(self): + return get_language(self.path) + + def query(self): + return is_query(self.path) + + def library(self): + return is_library(self.path) + + # Returns if this qlfile is not shared, and is in a pack that is only in one language + def isOnlyInLanguage(self, language): + return not self.shared and (self.package is None or self.package.languages == {language}) and self.language() == language + +# Represents a language folder +class Language: + def __init__(self, name): + self.name = name + self.packs = [] + self.nonshared_files = 0 + self.nonshared_lines = 0 + self.imported_files = 0 + self.imported_lines = 0 + + def addQlFile(self, qlfile): + if not qlfile.shared: + self.nonshared_files += 1 + self.nonshared_lines += qlfile.lines + + def addSharedAsset(self, package): + self.imported_files += package.files + self.imported_lines += package.lines + +# A shared package or file +class SharedAsset: + def __init__(self, name): + self.name = name + +# A file shared using identical-files.json +class IdenticalFileSet(SharedAsset): + def __init__(self, name, ql_files): + self.name = name + self.languages = set() + self.files = 0 + self.lines = 0 + for file in ql_files: + file.package = self + file.shared = True + self.files = 1 + self.lines = file.lines + self.languages.add(file.language()) + + # Gets a pretty-printed markdown link + def link(self): + return self.name + +# Represents all files shared in `identical-files.json` +# Reads the file and builds a list of assets +class IdenticalFiles: + def __init__(self, repo_location, ql_file_index): + identical_files = repo_location/'config'/'identical-files.json' + with open(identical_files, "r") as fp: + identical_files_json = json.load(fp) + # Create a list of assets + self.assets = [] + for group in identical_files_json: + paths = [] + for file in identical_files_json[group]: + path = repo_location / file + if is_ql(path): + ql_file_index[path].shared = True + paths.append(ql_file_index[path]) + self.assets.append(IdenticalFileSet(group, paths)) + +# A package created from a `qlpack.yml`` file +class Package(SharedAsset): + def __init__(self, path, ql_file_index): + self.path = path + self.language = get_language(path) + self.lines = 0 + self.files = 0 + self.languages = set() + self.languages.add(self.language) + self.identical_files_dependencies = set() + with open(path, 'r') as fp: + y = yaml.safe_load(fp) + if 'name' in y: + self.name = y['name'] + else: + self.name = path.parent.name + if 'dependencies' in y: + self.deps = y['dependencies'] + if self.deps is None: + self.deps = {} + else: + self.deps = {} + # Mark all relevant files with their package + for file in ql_file_index: + if self.containsDirectory(file): + file = ql_file_index[file] + if not file.shared: + file.package = self + self.lines += file.lines + self.files += 1 + else: + self.identical_files_dependencies.add(file.package) + self.url = "https://github.com/github/codeql/blob/main/" + str(path.relative_to(repo_location)) + + # Gets a pretty-printed markdown link + def link(self): + return '[' + self.name + '](' + self.url + ')' + + def containsDirectory(self, dir): + return self.path.parent.parts == dir.parts[:len(self.path.parent.parts)] + # dir.startsWith(self.path.parent) + + # Constructs a list of transitive depedencies of this package. + def calculateDependencies(self, packageNameMap): + self.transitive_dependencies = set(self.deps) + queue = list(self.deps) + while len(queue): + item = queue.pop() + for dep2 in packageNameMap[item].deps: + if dep2 not in self.transitive_dependencies: + self.transitive_dependencies.add(dep2) + queue.append(dep2) + # Calculate the amount of imported code + self.total_imported_files = 0 + self.total_imported_lines = 0 + self.all_dependencies = set(self.identical_files_dependencies) + for dep in self.transitive_dependencies: + self.all_dependencies.add(packageNameMap[dep]) + for dep in self.all_dependencies: + self.total_imported_files += dep.files + self.total_imported_lines += dep.lines + dep.languages.add(self.language) + +# Create a big index of all files and their line counts. + +# Map from path to line count +ql_file_index = {} +package_files = [] + +# Queue of directories to read +directories_to_scan = [repo_location] + +while len(directories_to_scan)!=0: + dir = directories_to_scan.pop() + for p in dir.iterdir(): + if p.is_dir(): + directories_to_scan.append(p) + elif is_ql(p): + ql_file_index[p] = QlFile(p) + elif is_package(p): + package_files.append(p) + +# Create identical_files_json +identical_files = IdenticalFiles(repo_location, ql_file_index) + +# Create packages +# Do this after identical_files so that we can figure out the package sizes +# Do this after getting the ql_file_index fully built +packages = [] +for file in package_files: + packages.append(Package(file, ql_file_index)) + +# List all shared assets +shared_assets = packages + identical_files.assets + +# Construct statistics for each language +language_info = {} +for l in languages: + language_info[l] = Language(l) + +for qlfile in ql_file_index.values(): + lang = qlfile.language() + if lang in language_info: + info = language_info[lang] + if qlfile.isOnlyInLanguage(lang): + info.addQlFile(qlfile) + +# Determine all package dependencies + +packageNameMap = {} + +for package in packages: + packageNameMap[package.name] = package + +for package in packages: + package.calculateDependencies(packageNameMap) + +for asset in shared_assets: + if len(asset.languages)>1: + for lang in asset.languages: + if lang in language_info: + language_info[lang].addSharedAsset(asset) + + +# Functions to output the results + +def list_assets(shared_assets, language_info): + print('| Asset | Files | Lines |', end='') + for lang in language_info: + print('', lang, '|', end='') + print() + print('| ----- | ----- | ----- |', end='') + for lang in language_info: + print(' ---- |', end='') + print() + for asset in shared_assets: + print('|', asset.link(), '|', asset.files ,'|', asset.lines, '|', end=' ') + for lang in language_info: + if lang in asset.languages: + print('yes |', end=' ') + else: + print(' |', end=' '); + print() + print() + +def list_package_dependencies(package): + print("Package", package.path, package.name, package.files, package.lines, package.total_imported_files, package.total_imported_lines) + for dep in package.all_dependencies: + print(" ", dep.name, dep.files, dep.lines) + +def print_package_dependencies(packages): + print('| Package name | Non-shared files | Non-shared lines of code | Imported files | Imported lines of code | Shared code % |') + print('| ------------ | ---------------- | ------------------------ | -------------- | ---------------------- | ------------- |') + for package in packages: + nlines = package.lines + package.total_imported_lines + shared_percentage = 100 * package.total_imported_lines / nlines if nlines>0 else 0 + print('|', package.link(), '|', package.files, '|', package.lines, '|', package.total_imported_files, '|', package.total_imported_lines, '|', + # ','.join([p.name for p in package.all_dependencies]), + "%.2f" % shared_percentage, '|') + print() + +def print_language_dependencies(packages): + print_package_dependencies([p for p in packages if p.name.endswith('-all') and p.name.count('-')==1]) + +def list_shared_code_by_language(language_info): + # For each language directory, list the files that are (1) inside the directory and not shared, + # (2) packages from outside the directory, plus identical files + print('| Language | Non-shared files | Non-shared lines of code | Imported files | Imported lines of code | Shared code % |') + print('| -------- | ---------------- | ------------------------ | -------------- | ---------------------- | ------------- |') + for lang in language_info: + info = language_info[lang] + total = info.imported_lines + info.nonshared_lines + shared_percentage = 100 * info.imported_lines / total if total>0 else 0 + print('|', lang, '|', info.nonshared_files, '|', info.nonshared_lines, '|', info.imported_files, '|', info.imported_lines, '|', "%.2f" % shared_percentage, '|') + print() + + +# Output reports + +print('# Report on CodeQL code sharing\n') +print('Generated on', datetime.datetime.now()) +print() + +print('## Shared code by language\n') + +list_shared_code_by_language(language_info) + +print(''' +* *Non-shared files*: The number of CodeQL files (`.ql`/`.qll`) that are only used within this language folder. Excludes `identical-files.json` that are shared between multiple languages. +* *Non-shared lines of code*: The number of lines of code in the non-shared files. +* *Imported files*: All CodeQL files (`.ql`/`.qll`) files that are transitively used in this language folder, either via packages or `identical-files.json` +* *Imported lines of code*: The number of lines of code in the imported files +* *Shared code %*: The proportion of imported lines / total lines (nonshared + imported). + +## Shared packages use by language + +A package is *used* if it is a direct or indirect dependency, or a file shared via `identical-files.json`. + +''') + +list_assets(shared_assets, language_info) + +print('## Shared code by language pack\n') + +print_language_dependencies(packages) + +print('## Shared code by package\n') + +print_package_dependencies(packages) diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md index 108c522a649..e6532a3f5d8 100644 --- a/misc/suite-helpers/CHANGELOG.md +++ b/misc/suite-helpers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.3 + +No user-facing changes. + ## 0.4.2 No user-facing changes. diff --git a/misc/suite-helpers/change-notes/released/0.4.3.md b/misc/suite-helpers/change-notes/released/0.4.3.md new file mode 100644 index 00000000000..126fb622583 --- /dev/null +++ b/misc/suite-helpers/change-notes/released/0.4.3.md @@ -0,0 +1,3 @@ +## 0.4.3 + +No user-facing changes. diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml index 94c5b17423c..1ec9c4ea5d9 100644 --- a/misc/suite-helpers/codeql-pack.release.yml +++ b/misc/suite-helpers/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.2 +lastReleaseVersion: 0.4.3 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 6154a791ba2..8f380beb26b 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,3 +1,3 @@ name: codeql/suite-helpers -version: 0.4.3-dev +version: 0.4.4-dev groups: shared diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index 473d1ebc67e..c7ade22bbcb 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,16 @@ +## 0.8.0 + +### Breaking Changes + +- Python 2 is no longer supported for extracting databases using the CodeQL CLI. As a consequence, + the previously deprecated support for `pyxl` and `spitfire` templates has also been removed. When + extracting Python 2 code, having Python 2 installed is still recommended, as this ensures the + correct version of the Python standard library is extracted. + +### Minor Analysis Improvements + +* Fixed module resolution so we properly recognize that in `from import *`, where `` is a package, the actual imports are made from the `/__init__.py` file. + ## 0.7.2 No user-facing changes. diff --git a/python/ql/lib/change-notes/2023-01-16-new-call-graph.md b/python/ql/lib/change-notes/2023-01-16-new-call-graph.md new file mode 100644 index 00000000000..3a9e6c3abc0 --- /dev/null +++ b/python/ql/lib/change-notes/2023-01-16-new-call-graph.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* We use a new analysis for the call-graph (determining which function is called). This can lead to changed results. In most cases this is much more accurate than the old call-graph that was based on points-to, but we do lose a few valid edges in the call-graph, especially around methods that are not defined inside its' class. diff --git a/python/ql/lib/change-notes/2023-02-13-hmac-modeling.md b/python/ql/lib/change-notes/2023-02-13-hmac-modeling.md new file mode 100644 index 00000000000..2753c24a818 --- /dev/null +++ b/python/ql/lib/change-notes/2023-02-13-hmac-modeling.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added modeling of cryptographic operations in the `hmac` library. diff --git a/python/ql/lib/change-notes/2023-02-16-import-if-then-else.md b/python/ql/lib/change-notes/2023-02-16-import-if-then-else.md new file mode 100644 index 00000000000..c377014a32e --- /dev/null +++ b/python/ql/lib/change-notes/2023-02-16-import-if-then-else.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Fixed module resolution so we properly recognize definitions made within if-then-else statements. diff --git a/python/ql/lib/change-notes/released/0.8.0.md b/python/ql/lib/change-notes/released/0.8.0.md new file mode 100644 index 00000000000..16533f766b6 --- /dev/null +++ b/python/ql/lib/change-notes/released/0.8.0.md @@ -0,0 +1,12 @@ +## 0.8.0 + +### Breaking Changes + +- Python 2 is no longer supported for extracting databases using the CodeQL CLI. As a consequence, + the previously deprecated support for `pyxl` and `spitfire` templates has also been removed. When + extracting Python 2 code, having Python 2 installed is still recommended, as this ensures the + correct version of the Python standard library is extracted. + +### Minor Analysis Improvements + +* Fixed module resolution so we properly recognize that in `from import *`, where `` is a package, the actual imports are made from the `/__init__.py` file. diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index fee171e9685..37eab3197dc 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.7.2 +lastReleaseVersion: 0.8.0 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index cc59833287a..03b59d4771c 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.7.3-dev +version: 0.8.1-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/lib/semmle/python/Constants.qll b/python/ql/lib/semmle/python/Constants.qll index 19e3e757989..03254a4bfd0 100644 --- a/python/ql/lib/semmle/python/Constants.qll +++ b/python/ql/lib/semmle/python/Constants.qll @@ -3,32 +3,34 @@ import python /** the Python major version number */ -int major_version() { - explicit_major_version(result) - or - not explicit_major_version(_) and - /* If there is more than one version, prefer 2 for backwards compatibility */ - (if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3) -} +int major_version() { full_python_analysis_version(result, _, _) } /** the Python minor version number */ -int minor_version() { - exists(string v | py_flags_versioned("version.minor", v, major_version().toString()) | - result = v.toInt() - ) -} +int minor_version() { full_python_analysis_version(_, result, _) } /** the Python micro version number */ -int micro_version() { - exists(string v | py_flags_versioned("version.micro", v, major_version().toString()) | - result = v.toInt() - ) +int micro_version() { full_python_analysis_version(_, _, result) } + +/** Gets the latest supported minor version for the given major version. */ +private int latest_supported_minor_version(int major) { + major = 2 and result = 7 + or + major = 3 and result = 11 } -private predicate explicit_major_version(int v) { - exists(string version | py_flags_versioned("language.version", version, _) | - version.charAt(0) = "2" and v = 2 - or - version.charAt(0) = "3" and v = 3 +private predicate full_python_analysis_version(int major, int minor, int micro) { + exists(string version_string | py_flags_versioned("language.version", version_string, _) | + major = version_string.regexpFind("\\d+", 0, _).toInt() and + ( + minor = version_string.regexpFind("\\d+", 1, _).toInt() + or + not exists(version_string.regexpFind("\\d+", 1, _)) and + minor = latest_supported_minor_version(major) + ) and + ( + micro = version_string.regexpFind("\\d+", 2, _).toInt() + or + not exists(version_string.regexpFind("\\d+", 2, _)) and micro = 0 + ) ) } diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 81a01025558..8dfdc4a6341 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -125,7 +125,7 @@ class ControlFlowNode extends @py_flow_node { /** Gets a textual representation of this element. */ cached string toString() { - Stages::DataFlow::ref() and + Stages::AST::ref() and exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString()) or exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString()) @@ -411,6 +411,12 @@ class CallNode extends ControlFlowNode { result.getNode() = this.getNode().getStarArg() and result.getBasicBlock().dominates(this.getBasicBlock()) } + + /** Gets a dictionary (**) argument of this call, if any. */ + ControlFlowNode getKwargs() { + result.getNode() = this.getNode().getKwargs() and + result.getBasicBlock().dominates(this.getBasicBlock()) + } } /** A control flow corresponding to an attribute expression, such as `value.attr` */ diff --git a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll index 22a2d1c1eb2..79dd19dd972 100644 --- a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll +++ b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll @@ -26,6 +26,26 @@ private newtype TCryptographicAlgorithm = isWeakPasswordHashingAlgorithm(name) and isWeak = true } +/** + * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. + * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. + * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. + */ +bindingset[name] +private CryptographicAlgorithm getBestAlgorithmForName(string name) { + result = + max(CryptographicAlgorithm algorithm | + algorithm.getName() = + [ + name.toUpperCase(), // the full name + name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces + name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores + ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces + | + algorithm order by algorithm.getName().length() + ) +} + /** * A cryptographic algorithm. */ @@ -39,15 +59,11 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { abstract string getName(); /** - * Holds if the name of this algorithm matches `name` modulo case, - * white space, dashes, underscores, and anything after a dash in the name - * (to ignore modes of operation, such as CBC or ECB). + * Holds if the name of this algorithm is the most specific match for `name`. + * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. */ bindingset[name] - predicate matchesName(string name) { - [name.toUpperCase(), name.toUpperCase().regexpCapture("^(\\w+)(?:-.*)?$", 1)] - .regexpReplaceAll("[-_ ]", "") = getName() - } + predicate matchesName(string name) { this = getBestAlgorithmForName(name) } /** * Holds if this algorithm is weak. diff --git a/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll b/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll index a234ba2cc1f..8bb63d97876 100644 --- a/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll +++ b/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll @@ -14,8 +14,20 @@ predicate isStrongHashingAlgorithm(string name) { name = [ + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 + // and https://www.blake2.net/ + "BLAKE2", "BLAKE2B", "BLAKE2S", + // see https://github.com/BLAKE3-team/BLAKE3 + "BLAKE3", + // "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512" + "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 + "SHAKE128", "SHAKE256", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 + "SM3", + // see https://security.stackexchange.com/a/216297 + "WHIRLPOOL", ] } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll new file mode 100644 index 00000000000..0d391d7f98d --- /dev/null +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll @@ -0,0 +1,1615 @@ +/** + * INTERNAL: Do not use. + * + * TypeTracker based call-graph. + * + * The overall scheme for resolving calls, is to notice that Python has different kinds + * of callables, and resolve those with different strategies. Currently we handle these + * completely separately: + * 1. plain functions (and lambdas) + * 2. methods on classes + * 3. class instantiation + * + * So we have type-trackers for each of the 3 categories above, with some considerable + * effort to handle different kinds of methods on classes (staticmethod, classmethod, + * normal), and resolving methods correctly in regards to MRO. + * + * + * A goal of this library is to support modeling calls that happens by third-party + * libraries. For example `call_later(func, arg0, arg1, foo=val)`, and the fact that the + * library might inject it's own arguments, for example a context that will always be + * passed as the actual first argument to the function. Currently the aim is to provide + * enough predicates for such `call_later` function to be modeled by providing + * additional data-flow steps for the arguments/parameters. This means we cannot have + * any special logic that requires an AST call to be made before we care to figure out + * what callable this call might end up targeting. + * + * Specifically this means that we cannot use type-backtrackers from the function of a + * `CallNode`, since there is no `CallNode` to backtrack from for `func` in the example + * above. + * + * Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to + * ask what targets any data-flow node has. But it's still the plan to do this! + */ + +private import python +private import DataFlowPublic +private import DataFlowPrivate +private import FlowSummaryImpl as FlowSummaryImpl +private import FlowSummaryImplSpecific as FlowSummaryImplSpecific +private import semmle.python.internal.CachedStages + +newtype TParameterPosition = + /** Used for `self` in methods, and `cls` in classmethods. */ + TSelfParameterPosition() or + TPositionalParameterPosition(int index) { + index = any(Parameter p).getPosition() + or + // since synthetic parameters are made for a synthetic summary callable, based on + // what Argument positions they have flow for, we need to make sure we have such + // parameter positions available. + FlowSummaryImplSpecific::ParsePositions::isParsedPositionalArgumentPosition(_, index) + } or + TKeywordParameterPosition(string name) { + name = any(Parameter p).getName() + or + // see comment for TPositionalParameterPosition + FlowSummaryImplSpecific::ParsePositions::isParsedKeywordArgumentPosition(_, name) + } or + TStarArgsParameterPosition(int index) { + // since `.getPosition` does not work for `*args`, we need *args parameter positions + // at index 1 larger than the largest positional parameter position (and 0 must be + // included as well). This is a bit of an over-approximation. + index = 0 or + index = any(Parameter p).getPosition() + 1 + } or + TSynthStarArgsElementParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or + TDictSplatParameterPosition() + +/** A parameter position. */ +class ParameterPosition extends TParameterPosition { + /** Holds if this position represents a `self`/`cls` parameter. */ + predicate isSelf() { this = TSelfParameterPosition() } + + /** Holds if this position represents a positional parameter at (0-based) `index`. */ + predicate isPositional(int index) { this = TPositionalParameterPosition(index) } + + /** Holds if this position represents a keyword parameter named `name`. */ + predicate isKeyword(string name) { this = TKeywordParameterPosition(name) } + + /** Holds if this position represents a `*args` parameter at (0-based) `index`. */ + predicate isStarArgs(int index) { this = TStarArgsParameterPosition(index) } + + /** + * Holds if this position represents a synthetic parameter at or after (0-based) + * position `index`, from which there will be made a store step to the real + * `*args` parameter. + */ + predicate isSynthStarArgsElement(int index) { + this = TSynthStarArgsElementParameterPosition(index) + } + + /** Holds if this position represents a `**kwargs` parameter. */ + predicate isDictSplat() { this = TDictSplatParameterPosition() } + + /** Gets a textual representation of this element. */ + string toString() { + this.isSelf() and result = "self" + or + exists(int index | this.isPositional(index) and result = "position " + index) + or + exists(string name | this.isKeyword(name) and result = "keyword " + name) + or + exists(int index | this.isStarArgs(index) and result = "*args at " + index) + or + exists(int index | + this.isSynthStarArgsElement(index) and + result = "synthetic *args element at (or after) " + index + ) + or + this.isDictSplat() and result = "**" + } +} + +newtype TArgumentPosition = + /** Used for `self` in methods, and `cls` in classmethods. */ + TSelfArgumentPosition() or + TPositionalArgumentPosition(int index) { + exists(any(CallNode c).getArg(index)) + or + // since synthetic calls within a summarized callable could use a unique argument + // position, we need to ensure we make these available (these are specified as + // parameters in the flow-summary spec) + FlowSummaryImplSpecific::ParsePositions::isParsedPositionalParameterPosition(_, index) + } or + TKeywordArgumentPosition(string name) { + exists(any(CallNode c).getArgByName(name)) + or + // see comment for TPositionalArgumentPosition + FlowSummaryImplSpecific::ParsePositions::isParsedKeywordParameterPosition(_, name) + } or + TStarArgsArgumentPosition(int index) { + exists(Call c | c.getPositionalArg(index) instanceof Starred) + } or + TDictSplatArgumentPosition() + +/** An argument position. */ +class ArgumentPosition extends TArgumentPosition { + /** Holds if this position represents a `self`/`cls` argument. */ + predicate isSelf() { this = TSelfArgumentPosition() } + + /** Holds if this position represents a positional argument at (0-based) `index`. */ + predicate isPositional(int index) { this = TPositionalArgumentPosition(index) } + + /** Holds if this position represents a keyword argument named `name`. */ + predicate isKeyword(string name) { this = TKeywordArgumentPosition(name) } + + /** Holds if this position represents a `*args` argument at (0-based) `index`. */ + predicate isStarArgs(int index) { this = TStarArgsArgumentPosition(index) } + + /** Holds if this position represents a `**kwargs` argument. */ + predicate isDictSplat() { this = TDictSplatArgumentPosition() } + + /** Gets a textual representation of this element. */ + string toString() { + this.isSelf() and result = "self" + or + exists(int pos | this.isPositional(pos) and result = "position " + pos) + or + exists(string name | this.isKeyword(name) and result = "keyword " + name) + or + exists(int index | this.isStarArgs(index) and result = "*args at " + index) + or + this.isDictSplat() and result = "**" + } +} + +/** Holds if arguments at position `apos` match parameters at position `ppos`. */ +predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { + ppos.isSelf() and apos.isSelf() + or + exists(int index | ppos.isPositional(index) and apos.isPositional(index)) + or + exists(string name | ppos.isKeyword(name) and apos.isKeyword(name)) + or + exists(int index | ppos.isStarArgs(index) and apos.isStarArgs(index)) + or + exists(int paramIndex, int argIndex | argIndex >= paramIndex | + ppos.isSynthStarArgsElement(paramIndex) and apos.isPositional(argIndex) + ) + or + ppos.isDictSplat() and apos.isDictSplat() +} + +// ============================================================================= +// Helper predicates +// ============================================================================= +/** + * Holds if the function `func` is a staticmethod -- either by having a + * `@staticmethod` decorator or by convention + * (like a `__new__` method on a class is a classmethod even without the decorator). + */ +predicate isStaticmethod(Function func) { + exists(NameNode id | id.getId() = "staticmethod" and id.isGlobal() | + func.getADecorator() = id.getNode() + ) +} + +/** + * Holds if the function `func` is a classmethod -- either by having a + * `@classmethod` decorator or by convention + * (like a `__new__` method on a class is a classmethod even without the decorator). + */ +predicate isClassmethod(Function func) { + exists(NameNode id | id.getId() = "classmethod" and id.isGlobal() | + func.getADecorator() = id.getNode() + ) + or + exists(Class cls | + cls.getAMethod() = func and + func.getName() in [ + "__new__", // https://docs.python.org/3.10/reference/datamodel.html#object.__new__ + "__init_subclass__", // https://docs.python.org/3.10/reference/datamodel.html#object.__init_subclass__ + "__class_getitem__", // https://docs.python.org/3.10/reference/datamodel.html#object.__class_getitem__ + ] + ) +} + +/** Holds if the function `func` has a `property` decorator. */ +predicate hasPropertyDecorator(Function func) { + exists(NameNode id | id.getId() = "property" and id.isGlobal() | + func.getADecorator() = id.getNode() + ) +} + +// ============================================================================= +// Callables +// ============================================================================= +/** A callable defined in library code, identified by a unique string. */ +abstract class LibraryCallable extends string { + bindingset[this] + LibraryCallable() { any() } + + /** Gets a call to this library callable. */ + abstract CallCfgNode getACall(); + + /** Gets a data-flow node, where this library callable is used as a call-back. */ + abstract ArgumentNode getACallback(); +} + +newtype TDataFlowCallable = + /** + * Is used as the target for all calls: plain functions, lambdas, methods on classes, + * class instantiations, and (in the future) special methods. + */ + TFunction(Function func) { + // For generators/list-comprehensions we create a synthetic function. In the + // points-to call-graph these were not considered callable, and instead we added + // data-flow steps (read/write) for these. As an easy solution for now, we do the + // same to keep things easy to reason about (and therefore exclude things that do + // not have a definition) + exists(func.getDefinition()) + } or + /** see QLDoc for `DataFlowModuleScope` for why we need this. */ + TModule(Module m) or + TLibraryCallable(LibraryCallable callable) + +/** A callable. */ +abstract class DataFlowCallable extends TDataFlowCallable { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets qualified name for this callable, if any. */ + abstract string getQualifiedName(); + + /** Gets the scope of this callable */ + abstract Scope getScope(); + + /** Gets the parameter at position `ppos`, if any. */ + abstract ParameterNode getParameter(ParameterPosition ppos); + + /** Gets the underlying library callable, if any. */ + LibraryCallable asLibraryCallable() { this = TLibraryCallable(result) } + + /** Gets the location of this dataflow callable. */ + abstract Location getLocation(); +} + +/** A callable function. */ +abstract class DataFlowFunction extends DataFlowCallable, TFunction { + Function func; + + DataFlowFunction() { + this = TFunction(func) and + // TODO: Handle @property decorators + not hasPropertyDecorator(func) + } + + override string toString() { result = func.toString() } + + override string getQualifiedName() { result = func.getQualifiedName() } + + override Function getScope() { result = func } + + override Location getLocation() { result = func.getLocation() } + + /** Gets the positional parameter offset, to take into account self/cls parameters. */ + int positionalOffset() { result = 0 } + + override ParameterNode getParameter(ParameterPosition ppos) { + exists(int index | ppos.isPositional(index) | + result.getParameter() = func.getArg(index + this.positionalOffset()) + ) + or + exists(string name | ppos.isKeyword(name) | result.getParameter() = func.getArgByName(name)) + or + // `*args` + exists(int index | + ( + ppos.isStarArgs(index) and + result.getParameter() = func.getVararg() + or + ppos.isSynthStarArgsElement(index) and + result = TSynthStarArgsElementParameterNode(this) + ) + | + // a `*args` parameter comes after the last positional parameter. We need to take + // self parameter into account, so for + // `def func(foo, bar, *args)` it should be index 2 (pos-param-count == 2) + // `class A: def func(self, foo, bar, *args)` it should be index 2 (pos-param-count - 1 == 3 - 1) + index = func.getPositionalParameterCount() - this.positionalOffset() + or + // no positional argument + not exists(func.getArg(_)) and index = 0 + ) + or + // `**kwargs` + // since the dataflow library has the restriction that we can only have ONE result per + // parameter position, if there is both a synthetic **kwargs and a real **kwargs + // parameter, we only give the result for the synthetic, and add local flow from the + // synthetic to the real. It might seem more natural to do it in the other + // direction, but since we have a clearStep on the real **kwargs parameter, we would have that + // content-clearing would also affect the synthetic parameter, which we don't want. + ppos.isDictSplat() and + if exists(func.getArgByName(_)) + then result = TSynthDictSplatParameterNode(this) + else result.getParameter() = func.getKwarg() + } +} + +/** A plain (non-method) function. */ +class DataFlowPlainFunction extends DataFlowFunction { + DataFlowPlainFunction() { not this instanceof DataFlowMethod } +} + +/** A method. */ +class DataFlowMethod extends DataFlowFunction { + Class cls; + + DataFlowMethod() { cls.getAMethod() = func } + + /** Gets the class this function is a method of. */ + Class getClass() { result = cls } + + override int positionalOffset() { result = 1 } + + override ParameterNode getParameter(ParameterPosition ppos) { + ppos.isSelf() and result.getParameter() = func.getArg(0) + or + result = super.getParameter(ppos) + } +} + +/** A classmethod. */ +class DataFlowClassmethod extends DataFlowMethod { + DataFlowClassmethod() { isClassmethod(func) } +} + +/** A staticmethod. */ +class DataFlowStaticmethod extends DataFlowMethod, DataFlowFunction { + DataFlowStaticmethod() { isStaticmethod(func) } + + override int positionalOffset() { result = 0 } + + override ParameterNode getParameter(ParameterPosition ppos) { + result = DataFlowFunction.super.getParameter(ppos) + } +} + +/** + * A module. This is not actually a callable, but we need this so a + * `ModuleVariableNode` have an enclosing callable. + */ +class DataFlowModuleScope extends DataFlowCallable, TModule { + Module mod; + + DataFlowModuleScope() { this = TModule(mod) } + + override string toString() { result = mod.toString() } + + override string getQualifiedName() { result = mod.getName() } + + override Module getScope() { result = mod } + + override Location getLocation() { result = mod.getLocation() } + + override ParameterNode getParameter(ParameterPosition ppos) { none() } +} + +class LibraryCallableValue extends DataFlowCallable, TLibraryCallable { + LibraryCallable callable; + + LibraryCallableValue() { this = TLibraryCallable(callable) } + + override string toString() { result = "LibraryCallableValue: " + callable.toString() } + + override string getQualifiedName() { result = callable.toString() } + + /** Gets a data-flow node, where this library callable is used as a call-back. */ + ArgumentNode getACallback() { result = callable.getACallback() } + + override Scope getScope() { none() } + + override ParameterNode getParameter(ParameterPosition ppos) { none() } + + override LibraryCallable asLibraryCallable() { result = callable } + + override Location getLocation() { none() } +} + +// ============================================================================= +// Type trackers used to resolve calls. +// ============================================================================= +/** Gets a call to `type`. */ +private CallCfgNode getTypeCall() { + exists(NameNode id | id.getId() = "type" and id.isGlobal() | + result.getFunction().asCfgNode() = id + ) +} + +/** Gets a call to `super`. */ +private CallCfgNode getSuperCall() { + // While it is possible to reference super and call it later, it's almost never done in + // practice. From looking at top 1000 projects, there were a few uses around mocking (see + // link below), but otherwise only 2 edgecases. Overall it seems ok to ignore this complexity. + // + // https://github.com/python/cpython/blob/18b1782192f85bd26db89f5bc850f8bee4247c1a/Lib/unittest/mock.py#L48-L50 + exists(NameNode id | id.getId() = "super" and id.isGlobal() | + result.getFunction().asCfgNode() = id + ) +} + +/** + * Holds if the file `f` should be ignored when computing the call-graph. + * + * We currently see a performance problem when analyzing the `sympy` PyPI package, + * which can be part of the database when dependencies are installed and extracted. + * From what we can understand, SymPy is using Python in a exotic way, so the fact that + * our analysis currently does not handle this project has nothing to say about our + * ability to handle normal Python code. Furthermore, SymPy does not look to be relevant + * in a security context, so we should not lose out on any security results by doing + * this. + */ +private predicate ignoreForCallGraph(File f) { + f.getAbsolutePath().matches("%/site-packages/sympy/%") +} + +/** + * Gets a reference to the function `func`. + */ +private TypeTrackingNode functionTracker(TypeTracker t, Function func) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + ( + result.asExpr() = func.getDefinition() + or + // when a function is decorated, it's the result of the (last) decorator call that + // is used + result.asExpr() = func.getDefinition().(FunctionExpr).getADecoratorCall() + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = functionTracker(t2, func).track(t2, t)) +} + +/** + * Gets a reference to the function `func`. + */ +Node functionTracker(Function func) { functionTracker(TypeTracker::end(), func).flowsTo(result) } + +/** + * Gets a reference to the class `cls`. + */ +private TypeTrackingNode classTracker(TypeTracker t, Class cls) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + ( + result.asExpr() = cls.getParent() + or + // when a class is decorated, it's the result of the (last) decorator call that + // is used + result.asExpr() = cls.getParent().getADecoratorCall() + or + // `type(obj)`, where obj is an instance of this class + result = getTypeCall() and + result.(CallCfgNode).getArg(0) = classInstanceTracker(cls) + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = classTracker(t2, cls).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to the class `cls`. + */ +Node classTracker(Class cls) { classTracker(TypeTracker::end(), cls).flowsTo(result) } + +/** + * Gets a reference to an instance of the class `cls`. + */ +private TypeTrackingNode classInstanceTracker(TypeTracker t, Class cls) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + resolveClassCall(result.(CallCfgNode).asCfgNode(), cls) + or + // result of `super().__new__` as used in a `__new__` method implementation + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + exists(Class classUsedInSuper | + fromSuperNewCall(result.(CallCfgNode).asCfgNode(), classUsedInSuper, _, _) and + classUsedInSuper = getADirectSuperclass*(cls) + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = classInstanceTracker(t2, cls).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to an instance of the class `cls`. + */ +Node classInstanceTracker(Class cls) { + classInstanceTracker(TypeTracker::end(), cls).flowsTo(result) +} + +/** + * Gets a reference to the `self` argument of a method on class `classWithMethod`. + * The method cannot be a `staticmethod` or `classmethod`. + */ +private TypeTrackingNode selfTracker(TypeTracker t, Class classWithMethod) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + exists(Function func | + func = classWithMethod.getAMethod() and + not isStaticmethod(func) and + not isClassmethod(func) + | + result.asExpr() = func.getArg(0) + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = selfTracker(t2, classWithMethod).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to the `self` argument of a method on class `classWithMethod`. + * The method cannot be a `staticmethod` or `classmethod`. + */ +Node selfTracker(Class classWithMethod) { + selfTracker(TypeTracker::end(), classWithMethod).flowsTo(result) +} + +/** + * Gets a reference to the enclosing class `classWithMethod` from within one of its + * methods, either through the `cls` argument from a `classmethod` or from `type(self)` + * from a normal method. + */ +private TypeTrackingNode clsArgumentTracker(TypeTracker t, Class classWithMethod) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + ( + exists(Function func | + func = classWithMethod.getAMethod() and + isClassmethod(func) + | + result.asExpr() = func.getArg(0) + ) + or + // type(self) + result = getTypeCall() and + result.(CallCfgNode).getArg(0) = selfTracker(classWithMethod) + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = clsArgumentTracker(t2, classWithMethod).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to the enclosing class `classWithMethod` from within one of its + * methods, either through the `cls` argument from a `classmethod` or from `type(self)` + * from a normal method. + */ +Node clsArgumentTracker(Class classWithMethod) { + clsArgumentTracker(TypeTracker::end(), classWithMethod).flowsTo(result) +} + +/** + * Gets a reference to the result of calling `super` without any argument, where the + * call happened in the method `func` (either a method or a classmethod). + */ +private TypeTrackingNode superCallNoArgumentTracker(TypeTracker t, Function func) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + not isStaticmethod(func) and + exists(CallCfgNode call | result = call | + call = getSuperCall() and + not exists(call.getArg(_)) and + call.getScope() = func + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = superCallNoArgumentTracker(t2, func).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to the result of calling `super` without any argument, where the + * call happened in the method `func` (either a method or a classmethod). + */ +Node superCallNoArgumentTracker(Function func) { + superCallNoArgumentTracker(TypeTracker::end(), func).flowsTo(result) +} + +/** + * Gets a reference to the result of calling `super` with 2 arguments, where the + * first is a reference to the class `cls`, and the second argument is `obj`. + */ +private TypeTrackingNode superCallTwoArgumentTracker(TypeTracker t, Class cls, Node obj) { + not ignoreForCallGraph(result.getLocation().getFile()) and + t.start() and + exists(CallCfgNode call | result = call | + call = getSuperCall() and + call.getArg(0) = classTracker(cls) and + call.getArg(1) = obj + ) + or + not ignoreForCallGraph(result.getLocation().getFile()) and + exists(TypeTracker t2 | result = superCallTwoArgumentTracker(t2, cls, obj).track(t2, t)) and + not result.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pp | pp.isSelf())) +} + +/** + * Gets a reference to the result of calling `super` with 2 arguments, where the + * first is a reference to the class `cls`, and the second argument is `obj`. + */ +Node superCallTwoArgumentTracker(Class cls, Node obj) { + superCallTwoArgumentTracker(TypeTracker::end(), cls, obj).flowsTo(result) +} + +// ============================================================================= +// MRO +// ============================================================================= +/** + * Gets a direct superclass of the argument `cls`, if any. + * + * For `A` with the class definition `class A(B, C)` it will have results `B` and `C`. + */ +Class getADirectSuperclass(Class cls) { cls.getABase() = classTracker(result).asExpr() } + +/** + * Gets a direct subclass of the argument `cls`, if any. + * + *For `B` with the class definition `class A(B)` it will have result `A`. + */ +Class getADirectSubclass(Class cls) { cls = getADirectSuperclass(result) } + +/** + * Gets a class that, from an approximated MRO calculation, might be the next class used + * for member-lookup when `super().attr` is used inside the class `cls`. + * + * In the example below, with `cls=B`, this predicate will have `A` and `C` as results. + * ```py + * class A: pass + * class B(A): pass + * class C(A): pass + * class D(B, C): pass + * ``` + * + * NOTE: This approximation does not handle all cases correctly, and in the example + * below, with `cls=A` will not have any results, although it should include `Y`. + * + * ```py + * class A: pass + * class B(A): pass + * class X: pass + * class Y(X): pass + * class Ex(B, Y): pass + * ``` + * + * NOTE for debugging the results of this predicate: Since a class can be part of + * multiple MROs, results from this predicate might only be valid in some, but not all, + * inheritance chains: This is the case with the result `C` for `cls=B` in the first + * example -- if `B` and `C` are defined in the same file, but `D` in a different file, + * this might make the results from this predicate difficult to comprehend at first. + * + * For more info on the C3 MRO used in Python see: + * - https://docs.python.org/3/glossary.html#term-method-resolution-order + * - https://www.python.org/download/releases/2.3/mro/ + * - https://opendylan.org/_static/c3-linearization.pdf + */ +private Class getNextClassInMro(Class cls) { + // class A(B, ...): + // `B` must be the next class after `A` in the MRO for A. + cls.getBase(0) = classTracker(result).asExpr() + or + // class A(B, C, D): + // - `C` could be the next class after `B` in MRO. + // - `D` could be the next class after `C` in MRO. + exists(Class sub, int i | + sub.getBase(i) = classTracker(cls).asExpr() and + sub.getBase(i + 1) = classTracker(result).asExpr() and + not result = cls + ) + // There are three important properties for MRO computed with C3 in Python: + // + // 1) monotonicity: if C1 precedes C2 in the MRO of C, then C1 precedes C2 in the MRO + // of any subclass of C. + // 2) local precedence ordering: if C1 precedes C2 in the list of superclasses for C, + // they will keep the same order in the MRO for C (and due to monotonicity, any + // subclass). + // 3) consistency with the extended precedence graph: if A and B (that are part of the + // class hierarchy of C) do not have a subclass/superclass relationship on their + // own, the ordering of A and B in the MRO of C will be determined by the local + // precedence ordering in the classes that use both A and B, either directly or + // through a subclass. (see paper for more details) + // + // Note that not all class hierarchies are allowed with C3, see the Python 2.3 article + // for examples. +} + +/** + * Gets a potential definition of the function `name` according to our approximation of + * MRO for the class `cls` (see `getNextClassInMro` for more information). + */ +Function findFunctionAccordingToMro(Class cls, string name) { + result = cls.getAMethod() and + result.getName() = name + or + not cls.getAMethod().getName() = name and + result = findFunctionAccordingToMro(getNextClassInMro(cls), name) +} + +/** + * Gets a class that, from an approximated MRO calculation, might be the next class + * after `cls` in the MRO for `startingClass`. + * + * Note: this is almost the same as `getNextClassInMro`, except we know the + * `startingClass`, which can give slightly more precise results. + * + * See QLDoc for `getNextClassInMro`. + */ +Class getNextClassInMroKnownStartingClass(Class cls, Class startingClass) { + cls.getBase(0) = classTracker(result).asExpr() and + cls = getADirectSuperclass*(startingClass) + or + exists(Class sub, int i | sub = getADirectSuperclass*(startingClass) | + sub.getBase(i) = classTracker(cls).asExpr() and + sub.getBase(i + 1) = classTracker(result).asExpr() and + not result = cls + ) +} + +private Function findFunctionAccordingToMroKnownStartingClass( + Class cls, Class startingClass, string name +) { + result = cls.getAMethod() and + result.getName() = name and + cls = getADirectSuperclass*(startingClass) + or + not cls.getAMethod().getName() = name and + result = + findFunctionAccordingToMroKnownStartingClass(getNextClassInMroKnownStartingClass(cls, + startingClass), startingClass, name) +} + +/** + * Gets a potential definition of the function `name` according to our approximation of + * MRO for the class `cls` (see `getNextClassInMroKnownStartingClass` for more information). + * + * Note: this is almost the same as `findFunctionAccordingToMro`, except we know the + * `startingClass`, which can give slightly more precise results. + */ +pragma[inline] +Function findFunctionAccordingToMroKnownStartingClass(Class startingClass, string name) { + result = findFunctionAccordingToMroKnownStartingClass(startingClass, startingClass, name) +} + +// ============================================================================= +// attribute trackers +// ============================================================================= +/** Gets a reference to the attribute read `attr` */ +private TypeTrackingNode attrReadTracker(TypeTracker t, AttrRead attr) { + t.start() and + result = attr and + attr.getObject() in [ + classTracker(_), classInstanceTracker(_), selfTracker(_), clsArgumentTracker(_), + superCallNoArgumentTracker(_), superCallTwoArgumentTracker(_, _) + ] + or + exists(TypeTracker t2 | result = attrReadTracker(t2, attr).track(t2, t)) +} + +/** Gets a reference to the attribute read `attr` */ +Node attrReadTracker(AttrRead attr) { attrReadTracker(TypeTracker::end(), attr).flowsTo(result) } + +// ============================================================================= +// call and argument resolution +// ============================================================================= +newtype TCallType = + /** A call to a function that is not part of a class. */ + CallTypePlainFunction() or + /** + * A call to an "normal" method on a class instance. + * Does not include staticmethods or classmethods. + */ + CallTypeNormalMethod() or + /** A call to a staticmethod. */ + CallTypeStaticMethod() or + /** A call to a classmethod. */ + CallTypeClassMethod() or + /** + * A call to method on a class, not going through an instance method, such as + * + * ```py + * class Foo: + * def method(self, arg): + * pass + * + * foo = Foo() + * Foo.method(foo, 42) + * ``` + */ + CallTypeMethodAsPlainFunction() or + /** A call to a class. */ + CallTypeClass() or + /** A call on a class instance, that goes to the `__call__` method of the class */ + CallTypeClassInstanceCall() + +/** A type of call. */ +class CallType extends TCallType { + string toString() { + this instanceof CallTypePlainFunction and + result = "CallTypePlainFunction" + or + this instanceof CallTypeNormalMethod and + result = "CallTypeNormalMethod" + or + this instanceof CallTypeStaticMethod and + result = "CallTypeStaticMethod" + or + this instanceof CallTypeClassMethod and + result = "CallTypeClassMethod" + or + this instanceof CallTypeMethodAsPlainFunction and + result = "CallTypeMethodAsPlainFunction" + or + this instanceof CallTypeClass and + result = "CallTypeClass" + or + this instanceof CallTypeClassInstanceCall and + result = "CallTypeClassInstanceCall" + } +} + +// ------------------------------------- +// method call resolution +// ------------------------------------- +private module MethodCalls { + /** + * Holds if `call` is a call to a method `target` on an instance or class, where the + * instance or class is not derived from an implicit `self`/`cls` argument to a method + * -- for that, see `callWithinMethodImplicitSelfOrCls`. + * + * It is found by making an attribute read `attr` with the name `functionName` on a + * reference to the class `cls`, or to an instance of the class `cls`. The reference the + * attribute-read is made on is `self`. + */ + pragma[nomagic] + private predicate directCall( + CallNode call, Function target, string functionName, Class cls, AttrRead attr, Node self + ) { + target = findFunctionAccordingToMroKnownStartingClass(cls, functionName) and + directCall_join(call, functionName, cls, attr, self) + } + + /** Extracted to give good join order */ + pragma[nomagic] + private predicate directCall_join( + CallNode call, string functionName, Class cls, AttrRead attr, Node self + ) { + call.getFunction() = attrReadTracker(attr).asCfgNode() and + attr.accesses(self, functionName) and + self in [classTracker(cls), classInstanceTracker(cls)] + } + + /** + * Holds if `call` is a call to a method `target` derived from an implicit `self`/`cls` + * argument to a method within the class `classWithMethod`. + * + * It is found by making an attribute read `attr` with the name `functionName` on a + * reference to an implicit `self`/`cls` argument. The reference the attribute-read is + * made on is `self`. + */ + pragma[nomagic] + private predicate callWithinMethodImplicitSelfOrCls( + CallNode call, Function target, string functionName, Class classWithMethod, AttrRead attr, + Node self + ) { + target = findFunctionAccordingToMro(getADirectSubclass*(classWithMethod), functionName) and + callWithinMethodImplicitSelfOrCls_join(call, functionName, classWithMethod, attr, self) + } + + /** Extracted to give good join order */ + pragma[nomagic] + private predicate callWithinMethodImplicitSelfOrCls_join( + CallNode call, string functionName, Class classWithMethod, AttrRead attr, Node self + ) { + call.getFunction() = attrReadTracker(attr).asCfgNode() and + attr.accesses(self, functionName) and + self in [clsArgumentTracker(classWithMethod), selfTracker(classWithMethod)] + } + + /** + * Like `fromSuper`, but only for `__new__`, and without requirement for being able to + * resolve the call to a known target (since the only super class might be the + * builtin `object`, so we never have the implementation of `__new__` in the DB). + */ + predicate fromSuperNewCall(CallNode call, Class classUsedInSuper, AttrRead attr, Node self) { + fromSuper_join(call, "__new__", classUsedInSuper, attr, self) and + self in [classTracker(_), clsArgumentTracker(_)] + } + + /** + * Holds if `call` is a call to a method `target`, derived from a use of `super`, either + * as: + * + * (1) `super(SomeClass, obj)`, where the first argument is a reference to the class + * `classUsedInSuper`, and the second argument is `self`. + * + * (2) `super()`. This implicit version can only happen within a method in a class. + * The implicit first argument is the class the call happens within `classUsedInSuper`. + * The implicit second argument is the `self`/`cls` parameter of the method this happens + * within. + * + * The method call is found by making an attribute read `attr` with the name + * `functionName` on the return value from the `super` call. + */ + pragma[nomagic] + predicate fromSuper( + CallNode call, Function target, string functionName, Class classUsedInSuper, AttrRead attr, + Node self + ) { + target = findFunctionAccordingToMro(getNextClassInMro(classUsedInSuper), functionName) and + fromSuper_join(call, functionName, classUsedInSuper, attr, self) + } + + /** Extracted to give good join order */ + pragma[nomagic] + private predicate fromSuper_join( + CallNode call, string functionName, Class classUsedInSuper, AttrRead attr, Node self + ) { + call.getFunction() = attrReadTracker(attr).asCfgNode() and + ( + exists(Function func | + attr.accesses(superCallNoArgumentTracker(func), functionName) and + // Requiring enclosing scope of function to be a class is a little too + // restrictive, since it is possible to use `super()` in a function defined inside + // the method, where the first argument to the nested-function will be used as + // implicit self argument. In practice I don't expect this to be a problem, and we + // did not support this with points-to either. + func.getEnclosingScope() = classUsedInSuper and + self.(ParameterNode).getParameter() = func.getArg(0) + ) + or + attr.accesses(superCallTwoArgumentTracker(classUsedInSuper, self), functionName) + ) + } + + predicate resolveMethodCall(CallNode call, Function target, CallType type, Node self) { + ( + directCall(call, target, _, _, _, self) + or + callWithinMethodImplicitSelfOrCls(call, target, _, _, _, self) + or + fromSuper(call, target, _, _, _, self) + ) and + ( + // normal method call + type instanceof CallTypeNormalMethod and + ( + self = classInstanceTracker(_) + or + self = selfTracker(_) + ) and + not isStaticmethod(target) and + not isClassmethod(target) + or + // method as plain function call + type instanceof CallTypeMethodAsPlainFunction and + self = classTracker(_) and + not isStaticmethod(target) and + not isClassmethod(target) + or + // staticmethod call + type instanceof CallTypeStaticMethod and + isStaticmethod(target) + or + // classmethod call + type instanceof CallTypeClassMethod and + isClassmethod(target) + ) + } +} + +import MethodCalls + +// ------------------------------------- +// class call resolution +// ------------------------------------- +/** + * Holds when `call` is a call to the class `cls`. + * + * NOTE: We have this predicate mostly to be able to compare with old point-to + * call-graph resolution. So it could be removed in the future. + */ +predicate resolveClassCall(CallNode call, Class cls) { + call.getFunction() = classTracker(cls).asCfgNode() + or + // `cls()` inside a classmethod (which also contains `type(self)()` inside a method) + exists(Class classWithMethod | + call.getFunction() = clsArgumentTracker(classWithMethod).asCfgNode() and + getADirectSuperclass*(cls) = classWithMethod + ) +} + +/** + * Gets a function, either `__init__` or `__new__` as specified by `funcName`, that will + * be invoked when `cls` is constructed -- where the function lookup is based on our MRO + * calculation. + */ +Function invokedFunctionFromClassConstruction(Class cls, string funcName) { + // as described in https://docs.python.org/3/reference/datamodel.html#object.__new__ + // __init__ will only be called when __new__ returns an instance of the class (which + // is not a requirement). However, for simplicity, we assume that __init__ will always + // be called. + funcName in ["__init__", "__new__"] and + result = findFunctionAccordingToMroKnownStartingClass(cls, funcName) +} + +/** + * Holds when `call` is a call on a class instance, that goes to the `__call__` method + * of the class. + * + * See https://docs.python.org/3/reference/datamodel.html#object.__call__ + */ +predicate resolveClassInstanceCall(CallNode call, Function target, Node self) { + exists(Class cls | + call.getFunction() = classInstanceTracker(cls).asCfgNode() and + target = findFunctionAccordingToMroKnownStartingClass(cls, "__call__") + or + call.getFunction() = selfTracker(cls).asCfgNode() and + target = findFunctionAccordingToMro(getADirectSubclass*(cls), "__call__") + | + self.asCfgNode() = call.getFunction() + ) +} + +// ------------------------------------- +// overall call resolution +// ------------------------------------- +/** + * Holds if `call` is a call to the `target`, with call-type `type`. + */ +cached +predicate resolveCall(CallNode call, Function target, CallType type) { + Stages::DataFlow::ref() and + ( + type instanceof CallTypePlainFunction and + call.getFunction() = functionTracker(target).asCfgNode() and + not exists(Class cls | cls.getAMethod() = target) + or + resolveMethodCall(call, target, type, _) + or + type instanceof CallTypeClass and + exists(Class cls | + resolveClassCall(call, cls) and + target = invokedFunctionFromClassConstruction(cls, _) + ) + or + type instanceof CallTypeClassInstanceCall and + resolveClassInstanceCall(call, target, _) + ) +} + +// ============================================================================= +// Argument resolution +// ============================================================================= +/** + * Holds if the argument of `call` at position `apos` is `arg`. This is just a helper + * predicate that maps ArgumentPositions to the arguments of the underlying `CallNode`. + */ +cached +predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) { + exists(int index | + apos.isPositional(index) and + arg.asCfgNode() = call.getArg(index) + ) + or + exists(string name | + apos.isKeyword(name) and + arg.asCfgNode() = call.getArgByName(name) + ) + or + // the first `*args` + exists(int index | + apos.isStarArgs(index) and + arg.asCfgNode() = call.getStarArg() and + // since `CallNode.getArg` doesn't include `*args`, we need to drop to the AST level + // to get the index. Notice that we only use the AST for getting the index, so we + // don't need to check for dominance in regards to splitting. + call.getStarArg().getNode() = call.getNode().getPositionalArg(index).(Starred).getValue() + ) + or + apos.isDictSplat() and + ( + arg.asCfgNode() = call.getKwargs() + or + arg = TSynthDictSplatArgumentNode(call) + ) +} + +/** + * Gets the argument `arg` of `call` at position `apos`, if any. Requires that we can + * resolve `call` to `target` with CallType `type`. + * + * It might seem like it's enough to know the CallType to resolve arguments. The reason + * we also need the `target`, is to avoid cross-talk. In the example below, assuming + * that `Foo` and `Bar` define their own `meth` methods, we might end up passing _both_ + * `foo` and `bar` to both `Foo.meth` and `Bar.meth`, which is wrong. Since the + * attribute access uses the same name, we need to also distinguish on the resolved + * target, to know which of the two objects to pass as the self argument. + * + * + * ```py + * foo = Foo() + * bar = Bar() + * if cond: + * func = foo.meth + * else: + * func = bar.meth + * func(42) + * ``` + * + * Note: If `Bar.meth` and `Foo.meth` resolves to the same function, we will end up + * sending both `self` arguments to that function, which is by definition the right thing to do. + * + * ### Bound methods + * + * For bound methods, such as `bm = x.m; bm()`, it's a little unclear whether we should + * still use the object in the attribute lookup (`x.m`) as the self argument in the + * call (`bm()`). We currently do this, but there might also be cases where we don't + * want to do this. + * + * In the example below, we want to clear taint from the list before it reaches the + * sink, but because we don't have a use of `l` in the `clear()` call, we currently + * don't have any way to achieve our goal. (Note that this is a contrived example) + * + * ```py + * l = list() + * clear = l.clear + * l.append(tainted) + * clear() + * sink(l) + * ``` + * + * To make the above even worse, bound-methods have a `__self__` property that refers to + * the object of the bound-method, so we can re-write the code as: + * + * ```py + * l = list() + * clear = l.clear + * clear.__self__.append(tainted) + * clear() + * sink(l) + * ``` + * + * One idea to solve this is to track the object in a synthetic data-flow node every + * time the bound method is used, such that the `clear()` call would essentially be + * translated into `l.clear()`, and we can still have use-use flow. + */ +cached +predicate getCallArg(CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos) { + Stages::DataFlow::ref() and + resolveCall(call, target, type) and + ( + type instanceof CallTypePlainFunction and + normalCallArg(call, arg, apos) + or + // self argument for normal method calls -- see note above about bound methods + type instanceof CallTypeNormalMethod and + apos.isSelf() and + resolveMethodCall(call, target, type, arg) and + // the dataflow library has a requirement that arguments and calls are in same enclosing + // callable. This requirement would be broken if we used `my_obj` as the self + // argument in the `f()` call in the example below: + // ```py + // def call_func(f): + // f() + // + // call_func(my_obj.some_method) + // ``` + exists(CfgNode cfgNode | cfgNode.getNode() = call | + cfgNode.getEnclosingCallable() = arg.getEnclosingCallable() + ) + or + // cls argument for classmethod calls -- see note above about bound methods + type instanceof CallTypeClassMethod and + apos.isSelf() and + resolveMethodCall(call, target, type, arg) and + (arg = classTracker(_) or arg = clsArgumentTracker(_)) and + // dataflow lib has requirement that arguments and calls are in same enclosing callable. + exists(CfgNode cfgNode | cfgNode.getNode() = call | + cfgNode.getEnclosingCallable() = arg.getEnclosingCallable() + ) + or + // normal arguments for method calls + ( + type instanceof CallTypeNormalMethod or + type instanceof CallTypeStaticMethod or + type instanceof CallTypeClassMethod + ) and + normalCallArg(call, arg, apos) + or + // method as plain function call. + // + // argument index 0 of call has position self (and MUST be given as positional + // argument in call). This also means that call-arguments are shifted by 1, such + // that argument index 1 of call has argument position 0 + type instanceof CallTypeMethodAsPlainFunction and + ( + apos.isSelf() and arg.asCfgNode() = call.getArg(0) + or + not apos.isPositional(_) and normalCallArg(call, arg, apos) + or + exists(ArgumentPosition normalPos, int index | + apos.isPositional(index - 1) and + normalPos.isPositional(index) and + normalCallArg(call, arg, normalPos) + ) + ) + or + // class call + type instanceof CallTypeClass and + ( + // only pass synthetic node for created object to __init__, and not __new__ since + // __new__ is a classmethod. + target = invokedFunctionFromClassConstruction(_, "__init__") and + apos.isSelf() and + arg = TSyntheticPreUpdateNode(call) + or + normalCallArg(call, arg, apos) + ) + or + // call on class instance, which goes to `__call__` method + type instanceof CallTypeClassInstanceCall and + ( + apos.isSelf() and + resolveClassInstanceCall(call, target, arg) + or + normalCallArg(call, arg, apos) + ) + ) +} + +// ============================================================================= +// DataFlowCall +// ============================================================================= +newtype TDataFlowCall = + TNormalCall(CallNode call, Function target, CallType type) { resolveCall(call, target, type) } or + TPotentialLibraryCall(CallNode call) or + /** A synthesized call inside a summarized callable */ + TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) { + FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) + } + +/** A call that is taken into account by the global data flow computation. */ +abstract class DataFlowCall extends TDataFlowCall { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Get the callable to which this call goes. */ + abstract DataFlowCallable getCallable(); + + /** Gets the argument at position `apos`, if any. */ + abstract ArgumentNode getArgument(ArgumentPosition apos); + + /** Get the control flow node representing this call, if any. */ + abstract ControlFlowNode getNode(); + + /** Gets the enclosing callable of this call. */ + abstract DataFlowCallable getEnclosingCallable(); + + /** Gets the location of this dataflow call. */ + abstract Location getLocation(); + + /** + * 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) + } +} + +/** A call found in the program source (as opposed to a synthesised call). */ +abstract class ExtractedDataFlowCall extends DataFlowCall { + override Location getLocation() { result = this.getNode().getLocation() } +} + +/** + * A resolved call in source code with an underlying `CallNode`. + * + * This is considered normal, compared with special calls such as `obj[0]` calling the + * `__getitem__` method on the object. However, this also includes calls that go to the + * `__call__` special method. + */ +class NormalCall extends ExtractedDataFlowCall, TNormalCall { + CallNode call; + Function target; + CallType type; + + NormalCall() { this = TNormalCall(call, target, type) } + + override string toString() { + // note: if we used toString directly on the CallNode we would get + // `ControlFlowNode for func()` + // but the `ControlFlowNode` part is just clutter, so we go directly to the AST node + // instead. + result = call.getNode().toString() + } + + override ControlFlowNode getNode() { result = call } + + override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() } + + override DataFlowCallable getCallable() { result.(DataFlowFunction).getScope() = target } + + override ArgumentNode getArgument(ArgumentPosition apos) { + getCallArg(call, target, type, result, apos) + } + + /** Gets the `CallType` of this call. */ + CallType getCallType() { result = type } +} + +/** + * A potential call to a summarized callable, a `LibraryCallable`. + * + * We currently exclude all resolved calls. This means that a call to, say, `map`, which + * is a `ClassCall`, cannot currently be given a summary. + * We hope to lift this restriction in the future and include all potential calls to summaries + * in this class. + */ +class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall { + CallNode call; + + PotentialLibraryCall() { this = TPotentialLibraryCall(call) } + + override string toString() { + // note: if we used toString directly on the CallNode we would get + // `ControlFlowNode for func()` + // but the `ControlFlowNode` part is just clutter, so we go directly to the AST node + // instead. + result = call.getNode().toString() + } + + // We cannot refer to a `PotentialLibraryCall` here, + // as that could in turn refer to type tracking. + // This call will be tied to a `PotentialLibraryCall` via + // `viableCallable` when the global data flow is assembled. + override DataFlowCallable getCallable() { none() } + + override ArgumentNode getArgument(ArgumentPosition apos) { + normalCallArg(call, result, apos) + or + // potential self argument, from `foo.bar()` -- note that this could also just be a + // module reference, but we really don't have a good way of knowing :| + apos.isSelf() and + result.asCfgNode() = call.getFunction().(AttrNode).getObject() + } + + override ControlFlowNode getNode() { result = call } + + override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() } +} + +/** + * A synthesized call inside a callable with a flow summary. + * + * For example, in + * ```python + * map(lambda x: x + 1, [1, 2, 3]) + * ``` + * + * there is a synthesized call to the lambda argument inside `map`. + */ +class SummaryCall extends DataFlowCall, TSummaryCall { + private FlowSummaryImpl::Public::SummarizedCallable c; + private Node receiver; + + SummaryCall() { this = TSummaryCall(c, receiver) } + + /** Gets the data flow node that this call targets. */ + Node getReceiver() { result = receiver } + + override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } + + override DataFlowCallable getCallable() { none() } + + override ArgumentNode getArgument(ArgumentPosition apos) { none() } + + override ControlFlowNode getNode() { none() } + + override string toString() { result = "[summary] call to " + receiver + " in " + c } + + override Location getLocation() { none() } +} + +/** + * The value of a parameter at function entry, viewed as a node in a data + * flow graph. + */ +abstract class ParameterNodeImpl extends Node { + /** Gets the `Parameter` this `ParameterNode` represents. */ + abstract Parameter getParameter(); + + /** + * Holds if this node is the parameter of callable `c` at the + * position `ppos`. + */ + predicate isParameterOf(DataFlowCallable c, ParameterPosition ppos) { + this = c.getParameter(ppos) + } +} + +/** A parameter for a library callable with a flow summary. */ +class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode { + private FlowSummaryImpl::Public::SummarizedCallable sc; + private ParameterPosition pos; + + SummaryParameterNode() { this = TSummaryParameterNode(sc, pos) } + + override Parameter getParameter() { none() } + + override predicate isParameterOf(DataFlowCallable c, ParameterPosition ppos) { + sc = c.asLibraryCallable() and + ppos = pos and + // avoid overlap with `SynthDictSplatParameterNode` + not ( + pos.isDictSplat() and + exists(ParameterPosition keywordPos | + FlowSummaryImpl::Private::summaryParameterNodeRange(sc, keywordPos) and + keywordPos.isKeyword(_) + ) + ) + } + + override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc } + + override string toString() { result = "parameter " + pos + " of " + sc } + + // Hack to return "empty location" + override predicate hasLocationInfo( + string file, int startline, int startcolumn, int endline, int endcolumn + ) { + file = "" and + startline = 0 and + startcolumn = 0 and + endline = 0 and + endcolumn = 0 + } +} + +/** A data-flow node used to model flow summaries. */ +class SummaryNode extends Node, TSummaryNode { + private FlowSummaryImpl::Public::SummarizedCallable c; + private FlowSummaryImpl::Private::SummaryNodeState state; + + SummaryNode() { this = TSummaryNode(c, state) } + + override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } + + override string toString() { result = "[summary] " + state + " in " + c } + + // Hack to return "empty location" + override predicate hasLocationInfo( + string file, int startline, int startcolumn, int endline, int endcolumn + ) { + file = "" and + startline = 0 and + startcolumn = 0 and + endline = 0 and + endcolumn = 0 + } +} + +private class SummaryReturnNode extends SummaryNode, ReturnNode { + private ReturnKind rk; + + SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) } + + override ReturnKind getKind() { result = rk } +} + +private class SummaryArgumentNode extends SummaryNode, ArgumentNode { + SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) } + + override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { + FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos) + } +} + +private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNodeImpl { + private Node pre; + + SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) } + + override Node getPreUpdateNode() { result = pre } +} + +/** Gets a viable run-time target for the call `call`. */ +DataFlowCallable viableCallable(ExtractedDataFlowCall call) { + result = call.getCallable() + or + // A call to a library callable with a flow summary + // In this situation we can not resolve the callable from the call, + // as that would make data flow depend on type tracking. + // Instead we resolve the call from the summary. + exists(LibraryCallable callable | + result = TLibraryCallable(callable) and + call.getNode() = callable.getACall().getNode() and + call instanceof PotentialLibraryCall + ) +} + +// ============================================================================= +// Remaining required data-flow things +// ============================================================================= +private newtype TReturnKind = TNormalReturnKind() + +/** + * A return kind. A return kind describes how a value can be returned + * from a callable. For Python, this is simply a method return. + */ +class ReturnKind extends TReturnKind { + /** Gets a textual representation of this element. */ + string toString() { result = "return" } +} + +/** A data flow node that represents a value returned by a callable. */ +abstract class ReturnNode extends Node { + /** Gets the kind of this return node. */ + ReturnKind getKind() { any() } +} + +/** A data flow node that represents a value returned by a callable. */ +class ExtractedReturnNode extends ReturnNode, CfgNode { + // See `TaintTrackingImplementation::returnFlowStep` + ExtractedReturnNode() { node = any(Return ret).getValue().getAFlowNode() } + + override ReturnKind getKind() { any() } +} + +/** A data-flow node that represents the output of a call. */ +abstract class OutNode extends Node { + /** Gets the underlying call, where this node is a corresponding output of kind `kind`. */ + abstract DataFlowCall getCall(ReturnKind kind); +} + +private module OutNodes { + /** + * A data-flow node that reads a value returned directly by a callable. + */ + class ExprOutNode extends OutNode, ExprNode { + private DataFlowCall call; + + ExprOutNode() { call.(ExtractedDataFlowCall).getNode() = this.getNode() } + + override DataFlowCall getCall(ReturnKind kind) { + result = call and + kind = kind + } + } + + private class SummaryOutNode extends SummaryNode, OutNode { + SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) } + + override DataFlowCall getCall(ReturnKind kind) { + FlowSummaryImpl::Private::summaryOutNode(result, this, kind) + } + } +} + +/** + * Gets a node that can read the value returned from `call` with return kind + * `kind`. + */ +OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { call = result.getCall(kind) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatchPointsTo.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatchPointsTo.qll deleted file mode 100644 index 0efae6ae45c..00000000000 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatchPointsTo.qll +++ /dev/null @@ -1,838 +0,0 @@ -/** - * INTERNAL: Do not use. - * - * Points-to based call-graph. - */ - -private import python -private import DataFlowPublic -private import semmle.python.SpecialMethods -private import FlowSummaryImpl as FlowSummaryImpl - -/** A parameter position represented by an integer. */ -class ParameterPosition extends int { - ParameterPosition() { exists(any(DataFlowCallable c).getParameter(this)) } - - /** Holds if this position represents a positional parameter at position `pos`. */ - predicate isPositional(int pos) { this = pos } // with the current representation, all parameters are positional -} - -/** An argument position represented by an integer. */ -class ArgumentPosition extends int { - ArgumentPosition() { this in [-2, -1] or exists(any(Call c).getArg(this)) } - - /** Holds if this position represents a positional argument at position `pos`. */ - predicate isPositional(int pos) { this = pos } // with the current representation, all arguments are positional -} - -/** Holds if arguments at position `apos` match parameters at position `ppos`. */ -pragma[inline] -predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos } - -/** - * Computes routing of arguments to parameters - * - * When a call contains more positional arguments than there are positional parameters, - * the extra positional arguments are passed as a tuple to a starred parameter. This is - * achieved by synthesizing a node `TPosOverflowNode(call, callable)` - * that represents the tuple of extra positional arguments. There is a store step from each - * extra positional argument to this node. - * - * CURRENTLY NOT SUPPORTED: - * When a call contains an iterable unpacking argument, such as `func(*args)`, it is expanded into positional arguments. - * - * CURRENTLY NOT SUPPORTED: - * If a call contains an iterable unpacking argument, such as `func(*args)`, and the callee contains a starred argument, any extra - * positional arguments are passed to the starred argument. - * - * When a call contains keyword arguments that do not correspond to keyword parameters, these - * extra keyword arguments are passed as a dictionary to a doubly starred parameter. This is - * achieved by synthesizing a node `TKwOverflowNode(call, callable)` - * that represents the dictionary of extra keyword arguments. There is a store step from each - * extra keyword argument to this node. - * - * When a call contains a dictionary unpacking argument, such as `func(**kwargs)`, with entries corresponding to a keyword parameter, - * the value at such a key is unpacked and passed to the parameter. This is achieved - * by synthesizing an argument node `TKwUnpacked(call, callable, name)` representing the unpacked - * value. This node is used as the argument passed to the matching keyword parameter. There is a read - * step from the dictionary argument to the synthesized argument node. - * - * When a call contains a dictionary unpacking argument, such as `func(**kwargs)`, and the callee contains a doubly starred parameter, - * entries which are not unpacked are passed to the doubly starred parameter. This is achieved by - * adding a dataflow step from the dictionary argument to `TKwOverflowNode(call, callable)` and a - * step to clear content of that node at any unpacked keys. - * - * ## Examples: - * Assume that we have the callable - * ```python - * def f(x, y, *t, **d): - * pass - * ``` - * Then the call - * ```python - * f(0, 1, 2, a=3) - * ``` - * will be modeled as - * ```python - * f(0, 1, [*t], [**d]) - * ``` - * where `[` and `]` denotes synthesized nodes, so `[*t]` is the synthesized tuple argument - * `TPosOverflowNode` and `[**d]` is the synthesized dictionary argument `TKwOverflowNode`. - * There will be a store step from `2` to `[*t]` at pos `0` and one from `3` to `[**d]` at key - * `a`. - * - * For the call - * ```python - * f(0, **{"y": 1, "a": 3}) - * ``` - * no tuple argument is synthesized. It is modeled as - * ```python - * f(0, [y=1], [**d]) - * ``` - * where `[y=1]` is the synthesized unpacked argument `TKwUnpacked` (with `name` = `y`). There is - * a read step from `**{"y": 1, "a": 3}` to `[y=1]` at key `y` to get the value passed to the parameter - * `y`. There is a dataflow step from `**{"y": 1, "a": 3}` to `[**d]` to transfer the content and - * a clearing of content at key `y` for node `[**d]`, since that value has been unpacked. - */ -module ArgumentPassing { - /** - * Holds if `call` represents a `DataFlowCall` to a `DataFlowCallable` represented by `callable`. - * - * It _may not_ be the case that `call = callable.getACall()`, i.e. if `call` represents a `ClassCall`. - * - * Used to limit the size of predicates. - */ - predicate connects(CallNode call, CallableValue callable) { - exists(NormalCall c | - call = c.getNode() and - callable = c.getCallable().getCallableValue() - ) - } - - /** - * Gets the `n`th parameter of `callable`. - * If the callable has a starred parameter, say `*tuple`, that is matched with `n=-1`. - * If the callable has a doubly starred parameter, say `**dict`, that is matched with `n=-2`. - * Note that, unlike other languages, we do _not_ use -1 for the position of `self` in Python, - * as it is an explicit parameter at position 0. - */ - NameNode getParameter(CallableValue callable, int n) { - // positional parameter - result = callable.getParameter(n) - or - // starred parameter, `*tuple` - exists(Function f | - f = callable.getScope() and - n = -1 and - result = f.getVararg().getAFlowNode() - ) - or - // doubly starred parameter, `**dict` - exists(Function f | - f = callable.getScope() and - n = -2 and - result = f.getKwarg().getAFlowNode() - ) - } - - /** - * A type representing a mapping from argument indices to parameter indices. - * We currently use two mappings: NoShift, the identity, used for ordinary - * function calls, and ShiftOneUp which is used for calls where an extra argument - * is inserted. These include method calls, constructor calls and class calls. - * In these calls, the argument at index `n` is mapped to the parameter at position `n+1`. - */ - newtype TArgParamMapping = - TNoShift() or - TShiftOneUp() - - /** A mapping used for parameter passing. */ - abstract class ArgParamMapping extends TArgParamMapping { - /** Gets the index of the parameter that corresponds to the argument at index `argN`. */ - bindingset[argN] - abstract int getParamN(int argN); - - /** Gets a textual representation of this element. */ - abstract string toString(); - } - - /** A mapping that passes argument `n` to parameter `n`. */ - class NoShift extends ArgParamMapping, TNoShift { - NoShift() { this = TNoShift() } - - override string toString() { result = "NoShift [n -> n]" } - - bindingset[argN] - override int getParamN(int argN) { result = argN } - } - - /** A mapping that passes argument `n` to parameter `n+1`. */ - class ShiftOneUp extends ArgParamMapping, TShiftOneUp { - ShiftOneUp() { this = TShiftOneUp() } - - override string toString() { result = "ShiftOneUp [n -> n+1]" } - - bindingset[argN] - override int getParamN(int argN) { result = argN + 1 } - } - - /** - * Gets the node representing the argument to `call` that is passed to the parameter at - * (zero-based) index `paramN` in `callable`. If this is a positional argument, it must appear - * at an index, `argN`, in `call` which satisfies `paramN = mapping.getParamN(argN)`. - * - * `mapping` will be the identity for function calls, but not for method- or constructor calls, - * where the first parameter is `self` and the first positional argument is passed to the second positional parameter. - * Similarly for classmethod calls, where the first parameter is `cls`. - * - * NOT SUPPORTED: Keyword-only parameters. - */ - Node getArg(CallNode call, ArgParamMapping mapping, CallableValue callable, int paramN) { - connects(call, callable) and - ( - // positional argument - exists(int argN | - paramN = mapping.getParamN(argN) and - result = TCfgNode(call.getArg(argN)) - ) - or - // keyword argument - // TODO: Since `getArgName` have no results for keyword-only parameters, - // these are currently not supported. - exists(Function f, string argName | - f = callable.getScope() and - f.getArgName(paramN) = argName and - result = TCfgNode(call.getArgByName(unbind_string(argName))) - ) - or - // a synthesized argument passed to the starred parameter (at position -1) - callable.getScope().hasVarArg() and - paramN = -1 and - result = TPosOverflowNode(call, callable) - or - // a synthesized argument passed to the doubly starred parameter (at position -2) - callable.getScope().hasKwArg() and - paramN = -2 and - result = TKwOverflowNode(call, callable) - or - // argument unpacked from dict - exists(string name | - call_unpacks(call, mapping, callable, name, paramN) and - result = TKwUnpackedNode(call, callable, name) - ) - ) - } - - /** Currently required in `getArg` in order to prevent a bad join. */ - bindingset[result, s] - private string unbind_string(string s) { result <= s and s <= result } - - /** Gets the control flow node that is passed as the `n`th overflow positional argument. */ - ControlFlowNode getPositionalOverflowArg(CallNode call, CallableValue callable, int n) { - connects(call, callable) and - exists(Function f, int posCount, int argNr | - f = callable.getScope() and - f.hasVarArg() and - posCount = f.getPositionalParameterCount() and - result = call.getArg(argNr) and - argNr >= posCount and - argNr = posCount + n - ) - } - - /** Gets the control flow node that is passed as the overflow keyword argument with key `key`. */ - ControlFlowNode getKeywordOverflowArg(CallNode call, CallableValue callable, string key) { - connects(call, callable) and - exists(Function f | - f = callable.getScope() and - f.hasKwArg() and - not exists(f.getArgByName(key)) and - result = call.getArgByName(key) - ) - } - - /** - * Holds if `call` unpacks a dictionary argument in order to pass it via `name`. - * It will then be passed to the parameter of `callable` at index `paramN`. - */ - predicate call_unpacks( - CallNode call, ArgParamMapping mapping, CallableValue callable, string name, int paramN - ) { - connects(call, callable) and - exists(Function f | - f = callable.getScope() and - not exists(int argN | paramN = mapping.getParamN(argN) | exists(call.getArg(argN))) and // no positional argument available - name = f.getArgName(paramN) and - // not exists(call.getArgByName(name)) and // only matches keyword arguments not preceded by ** - // TODO: make the below logic respect control flow splitting (by not going to the AST). - not call.getNode().getANamedArg().(Keyword).getArg() = name and // no keyword argument available - paramN >= 0 and - paramN < f.getPositionalParameterCount() + f.getKeywordOnlyParameterCount() and - exists(call.getNode().getKwargs()) // dict argument available - ) - } -} - -import ArgumentPassing - -/** A callable defined in library code, identified by a unique string. */ -abstract class LibraryCallable extends string { - bindingset[this] - LibraryCallable() { any() } - - /** Gets a call to this library callable. */ - abstract CallCfgNode getACall(); - - /** Gets a data-flow node, where this library callable is used as a call-back. */ - abstract ArgumentNode getACallback(); -} - -/** - * IPA type for DataFlowCallable. - * - * A callable is either a function value, a class value, or a module (for enclosing `ModuleVariableNode`s). - * A module has no calls. - */ -newtype TDataFlowCallable = - TCallableValue(CallableValue callable) { - callable instanceof FunctionValue and - not callable.(FunctionValue).isLambda() - or - callable instanceof ClassValue - } or - TLambda(Function lambda) { lambda.isLambda() } or - TModule(Module m) or - TLibraryCallable(LibraryCallable callable) - -/** A callable. */ -class DataFlowCallable extends TDataFlowCallable { - /** Gets a textual representation of this element. */ - string toString() { result = "DataFlowCallable" } - - /** Gets a call to this callable. */ - CallNode getACall() { none() } - - /** Gets the scope of this callable */ - Scope getScope() { none() } - - /** Gets the specified parameter of this callable */ - NameNode getParameter(int n) { none() } - - /** Gets the name of this callable. */ - string getName() { none() } - - /** Gets a callable value for this callable, if any. */ - CallableValue getCallableValue() { none() } - - /** Gets the underlying library callable, if any. */ - LibraryCallable asLibraryCallable() { this = TLibraryCallable(result) } - - Location getLocation() { none() } -} - -/** A class representing a callable value. */ -class DataFlowCallableValue extends DataFlowCallable, TCallableValue { - CallableValue callable; - - DataFlowCallableValue() { this = TCallableValue(callable) } - - override string toString() { result = callable.toString() } - - override CallNode getACall() { result = callable.getACall() } - - override Scope getScope() { result = callable.getScope() } - - override NameNode getParameter(int n) { result = getParameter(callable, n) } - - override string getName() { result = callable.getName() } - - override CallableValue getCallableValue() { result = callable } -} - -/** A class representing a callable lambda. */ -class DataFlowLambda extends DataFlowCallable, TLambda { - Function lambda; - - DataFlowLambda() { this = TLambda(lambda) } - - override string toString() { result = lambda.toString() } - - override CallNode getACall() { result = this.getCallableValue().getACall() } - - override Scope getScope() { result = lambda.getEvaluatingScope() } - - override NameNode getParameter(int n) { result = getParameter(this.getCallableValue(), n) } - - override string getName() { result = "Lambda callable" } - - override FunctionValue getCallableValue() { - result.getOrigin().getNode() = lambda.getDefinition() - } - - Expr getDefinition() { result = lambda.getDefinition() } -} - -/** A class representing the scope in which a `ModuleVariableNode` appears. */ -class DataFlowModuleScope extends DataFlowCallable, TModule { - Module mod; - - DataFlowModuleScope() { this = TModule(mod) } - - override string toString() { result = mod.toString() } - - override CallNode getACall() { none() } - - override Scope getScope() { result = mod } - - override NameNode getParameter(int n) { none() } - - override string getName() { result = mod.getName() } - - override CallableValue getCallableValue() { none() } -} - -class LibraryCallableValue extends DataFlowCallable, TLibraryCallable { - LibraryCallable callable; - - LibraryCallableValue() { this = TLibraryCallable(callable) } - - override string toString() { result = callable.toString() } - - override CallNode getACall() { result = callable.getACall().getNode() } - - /** Gets a data-flow node, where this library callable is used as a call-back. */ - ArgumentNode getACallback() { result = callable.getACallback() } - - override Scope getScope() { none() } - - override NameNode getParameter(int n) { none() } - - override string getName() { result = callable } - - override LibraryCallable asLibraryCallable() { result = callable } -} - -/** - * IPA type for DataFlowCall. - * - * Calls corresponding to `CallNode`s are either to callable values or to classes. - * The latter is directed to the callable corresponding to the `__init__` method of the class. - * - * An `__init__` method can also be called directly, so that the callable can be targeted by - * different types of calls. In that case, the parameter mappings will be different, - * as the class call will synthesize an argument node to be mapped to the `self` parameter. - * - * A call corresponding to a special method call is handled by the corresponding `SpecialMethodCallNode`. - * - * TODO: Add `TClassMethodCall` mapping `cls` appropriately. - */ -newtype TDataFlowCall = - /** - * Includes function calls, method calls, class calls and library calls. - * All these will be associated with a `CallNode`. - */ - TNormalCall(CallNode call) or - /** - * Includes calls to special methods. - * These will be associated with a `SpecialMethodCallNode`. - */ - TSpecialCall(SpecialMethodCallNode special) or - /** A synthesized call inside a summarized callable */ - TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) { - FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) - } - -/** A call found in the program source (as opposed to a synthesised summary call). */ -class TExtractedDataFlowCall = TSpecialCall or TNormalCall; - -/** A call that is taken into account by the global data flow computation. */ -abstract class DataFlowCall extends TDataFlowCall { - /** Gets a textual representation of this element. */ - abstract string toString(); - - /** Get the callable to which this call goes, if such exists. */ - abstract DataFlowCallable getCallable(); - - /** - * Gets the argument to this call that will be sent - * to the `n`th parameter of the callable, if any. - */ - abstract Node getArg(int n); - - /** Get the control flow node representing this call, if any. */ - abstract ControlFlowNode getNode(); - - /** Gets the enclosing callable of this call. */ - abstract DataFlowCallable getEnclosingCallable(); - - /** Gets the location of this dataflow call. */ - abstract Location getLocation(); - - /** - * 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) - } -} - -/** A call found in the program source (as opposed to a synthesised call). */ -abstract class ExtractedDataFlowCall extends DataFlowCall, TExtractedDataFlowCall { - final override Location getLocation() { result = this.getNode().getLocation() } - - abstract override DataFlowCallable getCallable(); - - abstract override Node getArg(int n); - - abstract override ControlFlowNode getNode(); -} - -/** A call associated with a `CallNode`. */ -class NormalCall extends ExtractedDataFlowCall, TNormalCall { - CallNode call; - - NormalCall() { this = TNormalCall(call) } - - override string toString() { result = call.toString() } - - abstract override Node getArg(int n); - - override CallNode getNode() { result = call } - - abstract override DataFlowCallable getCallable(); - - override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getNode().getScope() } -} - -/** - * A call to a function. - * This excludes calls to bound methods, classes, and special methods. - * Bound method calls and class calls insert an argument for the explicit - * `self` parameter, and special method calls have special argument passing. - */ -class FunctionCall extends NormalCall { - DataFlowCallableValue callable; - - FunctionCall() { - call = any(FunctionValue f).getAFunctionCall() and - call = callable.getACall() - } - - override Node getArg(int n) { result = getArg(call, TNoShift(), callable.getCallableValue(), n) } - - override DataFlowCallable getCallable() { result = callable } -} - -/** A call to a lambda. */ -class LambdaCall extends NormalCall { - DataFlowLambda callable; - - LambdaCall() { - call = callable.getACall() and - callable = TLambda(any(Function f)) - } - - override Node getArg(int n) { result = getArg(call, TNoShift(), callable.getCallableValue(), n) } - - override DataFlowCallable getCallable() { result = callable } -} - -/** - * Represents a call to a bound method call. - * The node representing the instance is inserted as argument to the `self` parameter. - */ -class MethodCall extends NormalCall { - FunctionValue bm; - - MethodCall() { call = bm.getAMethodCall() } - - private CallableValue getCallableValue() { result = bm } - - override Node getArg(int n) { - n > 0 and result = getArg(call, TShiftOneUp(), this.getCallableValue(), n) - or - n = 0 and result = TCfgNode(call.getFunction().(AttrNode).getObject()) - } - - override DataFlowCallable getCallable() { result = TCallableValue(this.getCallableValue()) } -} - -/** - * Represents a call to a class. - * The pre-update node for the call is inserted as argument to the `self` parameter. - * That makes the call node be the post-update node holding the value of the object - * after the constructor has run. - */ -class ClassCall extends NormalCall { - ClassValue c; - - ClassCall() { - not c.isAbsent() and - call = c.getACall() - } - - private CallableValue getCallableValue() { c.getScope().getInitMethod() = result.getScope() } - - override Node getArg(int n) { - n > 0 and result = getArg(call, TShiftOneUp(), this.getCallableValue(), n) - or - n = 0 and result = TSyntheticPreUpdateNode(TCfgNode(call)) - } - - override DataFlowCallable getCallable() { result = TCallableValue(this.getCallableValue()) } -} - -/** A call to a special method. */ -class SpecialCall extends ExtractedDataFlowCall, TSpecialCall { - SpecialMethodCallNode special; - - SpecialCall() { this = TSpecialCall(special) } - - override string toString() { result = special.toString() } - - override Node getArg(int n) { result = TCfgNode(special.(SpecialMethod::Potential).getArg(n)) } - - override ControlFlowNode getNode() { result = special } - - override DataFlowCallable getCallable() { - result = TCallableValue(special.getResolvedSpecialMethod()) - } - - override DataFlowCallable getEnclosingCallable() { - result.getScope() = special.getNode().getScope() - } -} - -/** - * A call to a summarized callable, a `LibraryCallable`. - * - * We currently exclude all resolved calls. This means that a call to, say, `map`, which - * is a `ClassCall`, cannot currently be given a summary. - * We hope to lift this restriction in the future and include all potential calls to summaries - * in this class. - */ -class LibraryCall extends NormalCall { - LibraryCall() { - // TODO: share this with `resolvedCall` - not ( - call = any(DataFlowCallableValue cv).getACall() - or - call = any(DataFlowLambda l).getACall() - or - // TODO: this should be covered by `DataFlowCallableValue`, but a `ClassValue` is not a `CallableValue`. - call = any(ClassValue c).getACall() - ) - } - - // TODO: Implement Python calling convention? - override Node getArg(int n) { result = TCfgNode(call.getArg(n)) } - - // We cannot refer to a `LibraryCallable` here, - // as that could in turn refer to type tracking. - // This call will be tied to a `LibraryCallable` via - // `getViableCallabe` when the global data flow is assembled. - override DataFlowCallable getCallable() { none() } -} - -/** - * A synthesized call inside a callable with a flow summary. - * - * For example, in - * ```python - * map(lambda x: x + 1, [1, 2, 3]) - * ``` - * - * there is a synthesized call to the lambda argument inside `map`. - */ -class SummaryCall extends DataFlowCall, TSummaryCall { - private FlowSummaryImpl::Public::SummarizedCallable c; - private Node receiver; - - SummaryCall() { this = TSummaryCall(c, receiver) } - - /** Gets the data flow node that this call targets. */ - Node getReceiver() { result = receiver } - - override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } - - override DataFlowCallable getCallable() { none() } - - override Node getArg(int n) { none() } - - override ControlFlowNode getNode() { none() } - - override string toString() { result = "[summary] call to " + receiver + " in " + c } - - override Location getLocation() { none() } -} - -/** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. - */ -abstract class ParameterNodeImpl extends Node { - abstract Parameter getParameter(); - - /** - * Holds if this node is the parameter of callable `c` at the - * (zero-based) index `i`. - */ - abstract predicate isParameterOf(DataFlowCallable c, int i); -} - -/** A parameter for a library callable with a flow summary. */ -class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode { - private FlowSummaryImpl::Public::SummarizedCallable sc; - private int pos; - - SummaryParameterNode() { this = TSummaryParameterNode(sc, pos) } - - override Parameter getParameter() { none() } - - override predicate isParameterOf(DataFlowCallable c, int i) { - sc = c.asLibraryCallable() and i = pos - } - - override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc } - - override string toString() { result = "parameter " + pos + " of " + sc } - - // Hack to return "empty location" - override predicate hasLocationInfo( - string file, int startline, int startcolumn, int endline, int endcolumn - ) { - file = "" and - startline = 0 and - startcolumn = 0 and - endline = 0 and - endcolumn = 0 - } -} - -/** A data-flow node used to model flow summaries. */ -class SummaryNode extends Node, TSummaryNode { - private FlowSummaryImpl::Public::SummarizedCallable c; - private FlowSummaryImpl::Private::SummaryNodeState state; - - SummaryNode() { this = TSummaryNode(c, state) } - - override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } - - override string toString() { result = "[summary] " + state + " in " + c } - - // Hack to return "empty location" - override predicate hasLocationInfo( - string file, int startline, int startcolumn, int endline, int endcolumn - ) { - file = "" and - startline = 0 and - startcolumn = 0 and - endline = 0 and - endcolumn = 0 - } -} - -private class SummaryReturnNode extends SummaryNode, ReturnNode { - private ReturnKind rk; - - SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) } - - override ReturnKind getKind() { result = rk } -} - -private class SummaryArgumentNode extends SummaryNode, ArgumentNode { - SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) } - - override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos) - } -} - -private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode { - private Node pre; - - SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) } - - override Node getPreUpdateNode() { result = pre } -} - -/** Gets a viable run-time target for the call `call`. */ -DataFlowCallable viableCallable(ExtractedDataFlowCall call) { - result = call.getCallable() - or - // A call to a library callable with a flow summary - // In this situation we can not resolve the callable from the call, - // as that would make data flow depend on type tracking. - // Instead we resolve the call from the summary. - exists(LibraryCallable callable | - result = TLibraryCallable(callable) and - call.getNode() = callable.getACall().getNode() - ) -} - -private newtype TReturnKind = TNormalReturnKind() - -/** - * A return kind. A return kind describes how a value can be returned - * from a callable. For Python, this is simply a method return. - */ -class ReturnKind extends TReturnKind { - /** Gets a textual representation of this element. */ - string toString() { result = "return" } -} - -/** A data flow node that represents a value returned by a callable. */ -abstract class ReturnNode extends Node { - /** Gets the kind of this return node. */ - ReturnKind getKind() { any() } -} - -/** A data flow node that represents a value returned by a callable. */ -class ExtractedReturnNode extends ReturnNode, CfgNode { - // See `TaintTrackingImplementation::returnFlowStep` - ExtractedReturnNode() { node = any(Return ret).getValue().getAFlowNode() } - - override ReturnKind getKind() { any() } -} - -/** A data-flow node that represents the output of a call. */ -abstract class OutNode extends Node { - /** Gets the underlying call, where this node is a corresponding output of kind `kind`. */ - abstract DataFlowCall getCall(ReturnKind kind); -} - -private module OutNodes { - /** - * A data-flow node that reads a value returned directly by a callable. - */ - class ExprOutNode extends OutNode, ExprNode { - private DataFlowCall call; - - ExprOutNode() { call.(ExtractedDataFlowCall).getNode() = this.getNode() } - - override DataFlowCall getCall(ReturnKind kind) { - result = call and - kind = kind - } - } - - private class SummaryOutNode extends SummaryNode, OutNode { - SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) } - - override DataFlowCall getCall(ReturnKind kind) { - FlowSummaryImpl::Private::summaryOutNode(result, this, kind) - } - } -} - -/** - * Gets a node that can read the value returned from `call` with return kind - * `kind`. - */ -OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { call = result.getCall(kind) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 016f748a79a..c46cd74e3d4 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -16,7 +16,7 @@ private import semmle.python.Frameworks // make it more digestible. import MatchUnpacking import IterableUnpacking -import DataFlowDispatchPointsTo +import DataFlowDispatch /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() } @@ -39,162 +39,267 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) //-------- predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr } -/** DEPRECATED: Alias for `SyntheticPreUpdateNode` */ -deprecated module syntheticPreUpdateNode = SyntheticPreUpdateNode; +// ============================================================================= +// SyntheticPreUpdateNode +// ============================================================================= +class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { + CallNode node; -/** A module collecting the different reasons for synthesising a pre-update node. */ -module SyntheticPreUpdateNode { - class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { - NeedsSyntheticPreUpdateNode post; + SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(node) } - SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(post) } + /** Gets the node for which this is a synthetic pre-update node. */ + CfgNode getPostUpdateNode() { result.getNode() = node } - /** Gets the node for which this is a synthetic pre-update node. */ - Node getPostUpdateNode() { result = post } + override string toString() { result = "[pre] " + node.toString() } - override string toString() { result = "[pre " + post.label() + "] " + post.toString() } + override Scope getScope() { result = node.getScope() } - override Scope getScope() { result = post.getScope() } - - override Location getLocation() { result = post.getLocation() } - } - - /** A data flow node for which we should synthesise an associated pre-update node. */ - class NeedsSyntheticPreUpdateNode extends PostUpdateNode { - NeedsSyntheticPreUpdateNode() { this = objectCreationNode() } - - override Node getPreUpdateNode() { result.(SyntheticPreUpdateNode).getPostUpdateNode() = this } - - /** - * Gets the label for this kind of node. This will figure in the textual representation of the synthesized pre-update node. - * - * There is currently only one reason for needing a pre-update node, so we always use that as the label. - */ - string label() { result = "objCreate" } - } - - /** - * Calls to constructors are treated as post-update nodes for the synthesized argument - * that is mapped to the `self` parameter. That way, constructor calls represent the value of the - * object after the constructor (currently only `__init__`) has run. - */ - CfgNode objectCreationNode() { result.getNode() = any(ClassCall c).getNode() } + override Location getLocation() { result = node.getLocation() } } -import SyntheticPreUpdateNode +// ============================================================================= +// *args (StarArgs) related +// ============================================================================= +/** + * A (synthetic) data-flow parameter node to capture all positional arguments that + * should be passed to the `*args` parameter. + * + * To handle + * ```py + * def func(*args): + * for arg in args: + * sink(arg) + * + * func(source1, source2, ...) + * ``` + * + * we add a synthetic parameter to `func` that accepts any positional argument at (or + * after) the index for the `*args` parameter. We add a store step (at any list index) to the real + * `*args` parameter. This means we can handle the code above, but if the code had done `sink(args[0])` + * we would (wrongly) add flow for `source2` as well. + * + * To solve this more precisely, we could add a synthetic argument with position `*args` + * that had store steps with the correct index (like we do for mapping keyword arguments to a + * `**kwargs` parameter). However, if a single call could go to 2 different + * targets with `*args` parameters at different positions, as in the example below, it's unclear what + * index to store `2` at. For the `foo` callable it should be 1, for the `bar` callable it should be 0. + * So this information would need to be encoded in the arguments of a `ArgumentPosition` branch, and + * one of the arguments would be which callable is the target. However, we cannot build `ArgumentPosition` + * branches based on the call-graph, so this strategy doesn't work. + * + * Another approach to solving it precisely is to add multiple synthetic parameters that have store steps + * to the real `*args` parameter. So for the example below, `foo` would need to have synthetic parameter + * nodes for indexes 1 and 2 (which would have store step for index 0 and 1 of the `*args` parameter), + * and `bar` would need it for indexes 1, 2, and 3. The question becomes how many synthetic parameters to + * create, which _must_ be `max(Call call, int i | exists(call.getArg(i)))`, since (again) we can't base + * this on the call-graph. And each function with a `*args` parameter would need this many extra synthetic + * nodes. My gut feeling at that this simple approach will be good enough, but if we need to get it more + * precise, it should be possible to do it like this. + * + * In PR review, @yoff suggested an alternative approach for more precise handling: + * + * - At the call site, all positional arguments are stored into a synthetic starArgs argument, always tarting at index 0 + * - This is sent to a synthetic star parameter + * - At the receiving end, we know the offset of a potential real star parameter, so we can define read steps accordingly: In foo, we read from the synthetic star parameter at index 1 and store to the real star parameter at index 0. + * + * ```py + * def foo(one, *args): ... + * def bar(*args): ... + * + * func = foo if else bar + * func(1, 2, 3) + */ +class SynthStarArgsElementParameterNode extends ParameterNodeImpl, + TSynthStarArgsElementParameterNode { + DataFlowCallable callable; -/** DEPRECATED: Alias for `SyntheticPostUpdateNode` */ -deprecated module syntheticPostUpdateNode = SyntheticPostUpdateNode; + SynthStarArgsElementParameterNode() { this = TSynthStarArgsElementParameterNode(callable) } -/** A module collecting the different reasons for synthesising a post-update node. */ -module SyntheticPostUpdateNode { - private import semmle.python.SpecialMethods + override string toString() { result = "SynthStarArgsElementParameterNode" } - /** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */ - class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode { - NeedsSyntheticPostUpdateNode pre; + override Scope getScope() { result = callable.getScope() } - SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(pre) } + override Location getLocation() { result = callable.getLocation() } - override Node getPreUpdateNode() { result = pre } - - override string toString() { result = "[post " + pre.label() + "] " + pre.toString() } - - override Scope getScope() { result = pre.getScope() } - - override Location getLocation() { result = pre.getLocation() } - } - - /** A data flow node for which we should synthesise an associated post-update node. */ - class NeedsSyntheticPostUpdateNode extends Node { - NeedsSyntheticPostUpdateNode() { - this = argumentPreUpdateNode() - or - this = storePreUpdateNode() - or - this = readPreUpdateNode() - } - - /** - * Gets the label for this kind of node. This will figure in the textual representation of the synthesized post-update node. - * We favour being an arguments as the reason for the post-update node in case multiple reasons apply. - */ - string label() { - if this = argumentPreUpdateNode() - then result = "arg" - else - if this = storePreUpdateNode() - then result = "store" - else result = "read" - } - } - - /** - * Gets the pre-update node for this node. - * - * An argument might have its value changed as a result of a call. - * Certain arguments, such as implicit self arguments are already post-update nodes - * and should not have an extra node synthesised. - */ - Node argumentPreUpdateNode() { - result = any(FunctionCall c).getArg(_) - or - result = any(LambdaCall c).getArg(_) - or - // Avoid argument 0 of method calls as those have read post-update nodes. - exists(MethodCall c, int n | n > 0 | result = c.getArg(n)) - or - result = any(SpecialCall c).getArg(_) - or - // Avoid argument 0 of class calls as those have non-synthetic post-update nodes. - exists(ClassCall c, int n | n > 0 | result = c.getArg(n)) - or - // any argument of any call that we have not been able to resolve - exists(CallNode call | not resolvedCall(call) | - result.(CfgNode).getNode() in [call.getArg(_), call.getArgByName(_)] - ) - } - - /** Holds if `call` can be resolved as a normal call */ - private predicate resolvedCall(CallNode call) { - call = any(DataFlowCallableValue cv).getACall() - or - call = any(DataFlowLambda l).getACall() - } - - /** Gets the pre-update node associated with a store. This is used for when an object might have its value changed after a store. */ - CfgNode storePreUpdateNode() { - exists(Attribute a | - result.getNode() = a.getObject().getAFlowNode() and - a.getCtx() instanceof Store - ) - } - - /** - * Gets a node marking the state change of an object after a read. - * - * A reverse read happens when the result of a read is modified, e.g. in - * ```python - * l = [ mutable ] - * l[0].mutate() - * ``` - * we may now have changed the content of `l`. To track this, there must be - * a postupdate node for `l`. - */ - CfgNode readPreUpdateNode() { - exists(Attribute a | - result.getNode() = a.getObject().getAFlowNode() and - a.getCtx() instanceof Load - ) - or - result.getNode() = any(SubscriptNode s).getObject() - or - // The dictionary argument is read from if the callable has parameters matching the keys. - result.getNode().getNode() = any(Call call).getKwargs() - } + override Parameter getParameter() { none() } } -import SyntheticPostUpdateNode +predicate synthStarArgsElementParameterNodeStoreStep( + SynthStarArgsElementParameterNode nodeFrom, ListElementContent c, ParameterNode nodeTo +) { + c = c and // suppress warning about unused parameter + exists(DataFlowCallable callable, ParameterPosition ppos | + nodeFrom = TSynthStarArgsElementParameterNode(callable) and + nodeTo = callable.getParameter(ppos) and + ppos.isStarArgs(_) + ) +} + +// ============================================================================= +// **kwargs (DictSplat) related +// ============================================================================= +/** + * A (synthetic) data-flow node that represents all keyword arguments, as if they had + * been passed in a `**kwargs` argument. + */ +class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode { + CallNode node; + + SynthDictSplatArgumentNode() { this = TSynthDictSplatArgumentNode(node) } + + override string toString() { result = "SynthDictSplatArgumentNode" } + + override Scope getScope() { result = node.getScope() } + + override Location getLocation() { result = node.getLocation() } +} + +private predicate synthDictSplatArgumentNodeStoreStep( + ArgumentNode nodeFrom, DictionaryElementContent c, SynthDictSplatArgumentNode nodeTo +) { + exists(string name, CallNode call, ArgumentPosition keywordPos | + nodeTo = TSynthDictSplatArgumentNode(call) and + getCallArg(call, _, _, nodeFrom, keywordPos) and + keywordPos.isKeyword(name) and + c.getKey() = name + ) +} + +/** + * Ensures that the a `**kwargs` parameter will not contain elements with names of + * keyword parameters. + * + * For example, for the function below, it's not possible that the `kwargs` dictionary + * can contain an element with the name `a`, since that parameter can be given as a + * keyword argument. + * + * ```py + * def func(a, **kwargs): + * ... + * ``` + */ +private predicate dictSplatParameterNodeClearStep(ParameterNode n, DictionaryElementContent c) { + exists(DataFlowCallable callable, ParameterPosition dictSplatPos, ParameterPosition keywordPos | + dictSplatPos.isDictSplat() and + ( + n.getParameter() = callable.(DataFlowFunction).getScope().getKwarg() + or + n = TSummaryParameterNode(callable.asLibraryCallable(), dictSplatPos) + ) and + exists(callable.getParameter(keywordPos)) and + keywordPos.isKeyword(c.getKey()) + ) +} + +/** + * A synthetic data-flow node to allow flow to keyword parameters from a `**kwargs` argument. + * + * Take the code snippet below as an example. Since the call only has a `**kwargs` argument, + * with a `**` argument position, we add this synthetic parameter node with `**` parameter position, + * and a read step to the `p1` parameter. + * + * ```py + * def foo(p1, p2): ... + * + * kwargs = {"p1": 42, "p2": 43} + * foo(**kwargs) + * ``` + * + * + * Note that this will introduce a bit of redundancy in cases like + * + * ```py + * foo(p1=taint(1), p2=taint(2)) + * ``` + * + * where direct keyword matching is possible, since we construct a synthesized dict + * splat argument (`SynthDictSplatArgumentNode`) at the call site, which means that + * `taint(1)` will flow into `p1` both via normal keyword matching and via the synthesized + * nodes (and similarly for `p2`). However, this redundancy is OK since + * (a) it means that type-tracking through keyword arguments also works in most cases, + * (b) read/store steps can be avoided when direct keyword matching is possible, and + * hence access path limits are not a concern, and + * (c) since the synthesized nodes are hidden, the reported data-flow paths will be + * collapsed anyway. + */ +class SynthDictSplatParameterNode extends ParameterNodeImpl, TSynthDictSplatParameterNode { + DataFlowCallable callable; + + SynthDictSplatParameterNode() { this = TSynthDictSplatParameterNode(callable) } + + override string toString() { result = "SynthDictSplatParameterNode" } + + override Scope getScope() { result = callable.getScope() } + + override Location getLocation() { result = callable.getLocation() } + + override Parameter getParameter() { none() } +} + +/** + * Flow step from the synthetic `**kwargs` parameter to the real `**kwargs` parameter. + * Due to restriction in dataflow library, we can only give one of them as result for + * `DataFlowCallable.getParameter`, so this is a workaround to ensure there is flow to + * _both_ of them. + */ +private predicate dictSplatParameterNodeFlowStep( + ParameterNodeImpl nodeFrom, ParameterNodeImpl nodeTo +) { + exists(DataFlowCallable callable | + nodeFrom = TSynthDictSplatParameterNode(callable) and + ( + nodeTo.getParameter() = callable.(DataFlowFunction).getScope().getKwarg() + or + exists(ParameterPosition pos | + nodeTo = TSummaryParameterNode(callable.asLibraryCallable(), pos) and + pos.isDictSplat() + ) + ) + ) +} + +/** + * Reads from the synthetic **kwargs parameter to each keyword parameter. + */ +predicate synthDictSplatParameterNodeReadStep( + SynthDictSplatParameterNode nodeFrom, DictionaryElementContent c, ParameterNode nodeTo +) { + exists(DataFlowCallable callable, ParameterPosition ppos | + nodeFrom = TSynthDictSplatParameterNode(callable) and + nodeTo = callable.getParameter(ppos) and + ppos.isKeyword(c.getKey()) + ) +} + +// ============================================================================= +// PostUpdateNode +// ============================================================================= +abstract class PostUpdateNodeImpl extends Node { + /** Gets the node before the state update. */ + abstract Node getPreUpdateNode(); +} + +class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode { + ControlFlowNode node; + + SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(node) } + + override Node getPreUpdateNode() { result.(CfgNode).getNode() = node } + + override string toString() { result = "[post] " + node.toString() } + + override Scope getScope() { result = node.getScope() } + + override Location getLocation() { result = node.getLocation() } +} + +class NonSyntheticPostUpdateNode extends PostUpdateNodeImpl, CfgNode { + SyntheticPreUpdateNode pre; + + NonSyntheticPostUpdateNode() { this = pre.getPostUpdateNode() } + + override Node getPreUpdateNode() { result = pre } +} class DataFlowExpr = Expr; @@ -274,13 +379,6 @@ module EssaFlow { iterableUnpackingFlowStep(nodeFrom, nodeTo) or matchFlowStep(nodeFrom, nodeTo) - or - // Overflow keyword argument - exists(CallNode call, CallableValue callable | - call = callable.getACall() and - nodeTo = TKwOverflowNode(call, callable) and - nodeFrom.asCfgNode() = call.getNode().getKwargs().getAFlowNode() - ) } predicate useToNextUse(NameNode nodeFrom, NameNode nodeTo) { @@ -305,6 +403,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStepForTypetracking(nodeFrom, nodeTo) or summaryFlowSteps(nodeFrom, nodeTo) + or + dictSplatParameterNodeFlowStep(nodeFrom, nodeTo) } /** @@ -521,15 +621,15 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) { or attributeStoreStep(nodeFrom, c, nodeTo) or - posOverflowStoreStep(nodeFrom, c, nodeTo) - or - kwOverflowStoreStep(nodeFrom, c, nodeTo) - or matchStoreStep(nodeFrom, c, nodeTo) or any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo) or FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom, c, nodeTo) + or + synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo) + or + synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo) } /** @@ -669,30 +769,6 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode n ) } -/** - * Holds if `nodeFrom` flows into the synthesized positional overflow argument (`nodeTo`) - * at the position indicated by `c`. - */ -predicate posOverflowStoreStep(CfgNode nodeFrom, TupleElementContent c, Node nodeTo) { - exists(CallNode call, CallableValue callable, int n | - nodeFrom.asCfgNode() = getPositionalOverflowArg(call, callable, n) and - nodeTo = TPosOverflowNode(call, callable) and - c.getIndex() = n - ) -} - -/** - * Holds if `nodeFrom` flows into the synthesized keyword overflow argument (`nodeTo`) - * at the key indicated by `c`. - */ -predicate kwOverflowStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) { - exists(CallNode call, CallableValue callable, string key | - nodeFrom.asCfgNode() = getKeywordOverflowArg(call, callable, key) and - nodeTo = TKwOverflowNode(call, callable) and - c.getKey() = key - ) -} - predicate defaultValueFlowStep(CfgNode nodeFrom, CfgNode nodeTo) { exists(Function f, Parameter p, ParameterDefinition def | // `getArgByName` supports, unlike `getAnArg`, keyword-only parameters @@ -722,9 +798,9 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) { or attributeReadStep(nodeFrom, c, nodeTo) or - kwUnpackReadStep(nodeFrom, c, nodeTo) - or FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom, c, nodeTo) + or + synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo) } /** Data flows from a sequence to a subscript of the sequence. */ @@ -814,43 +890,19 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo) nodeTo.accesses(nodeFrom, c.getAttribute()) } -/** - * Holds if `nodeFrom` is a dictionary argument being unpacked and `nodeTo` is the - * synthesized unpacked argument with the name indicated by `c`. - */ -predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) { - exists(CallNode call, string name | - nodeFrom.asCfgNode() = call.getNode().getKwargs().getAFlowNode() and - nodeTo = TKwUnpackedNode(call, _, name) and - name = c.getKey() - ) -} - -/** - * Clear content at key `name` of the synthesized dictionary `TKwOverflowNode(call, callable)`, - * whenever `call` unpacks `name`. - */ -predicate kwOverflowClearStep(Node n, Content c) { - exists(CallNode call, CallableValue callable, string name | - call_unpacks(call, _, callable, name, _) and - n = TKwOverflowNode(call, callable) and - c.(DictionaryElementContent).getKey() = name - ) -} - /** * Holds if values stored inside content `c` are cleared at node `n`. For example, * any value stored inside `f` is cleared at the pre-update node associated with `x` * in `x.f = newValue`. */ predicate clearsContent(Node n, Content c) { - kwOverflowClearStep(n, c) - or matchClearStep(n, c) or attributeClearStep(n, c) or FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c) + or + dictSplatParameterNodeClearStep(n, c) } /** @@ -906,23 +958,24 @@ predicate nodeIsHidden(Node n) { n instanceof SummaryNode or n instanceof SummaryParameterNode + or + n instanceof SynthStarArgsElementParameterNode + or + n instanceof SynthDictSplatArgumentNode + or + n instanceof SynthDictSplatParameterNode } 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) { - // lambda + // lambda and plain functions kind = kind and - creation.asExpr() = c.(DataFlowLambda).getDefinition() - or - // normal function - exists(FunctionDef def | - def.defines(creation.asVar().getSourceVariable()) and - def.getDefinedFunction() = c.(DataFlowCallableValue).getCallableValue().getScope() - ) + creation.asExpr() = c.(DataFlowPlainFunction).getScope().getDefinition() or // summarized function + exists(kind) and // avoid warning on unused 'kind' exists(Call call | creation.asExpr() = call.getAnArg() and creation = c.(LibraryCallableValue).getACallback() diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 4a00d0aafc3..440ce3b70d4 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -31,10 +31,44 @@ newtype TNode = or node.getNode() instanceof Pattern } or - /** A synthetic node representing the value of an object before a state change */ - TSyntheticPreUpdateNode(NeedsSyntheticPreUpdateNode post) or - /** A synthetic node representing the value of an object after a state change. */ - TSyntheticPostUpdateNode(NeedsSyntheticPostUpdateNode pre) or + /** + * A synthetic node representing the value of an object before a state change. + * + * For class calls we pass a synthetic self argument, so attribute writes in + * `__init__` is reflected on the resulting object (we need special logic for this + * since there is no `return` in `__init__`) + */ + // NOTE: since we can't rely on the call graph, but we want to have synthetic + // pre-update nodes for class calls, we end up getting synthetic pre-update nodes for + // ALL calls :| + TSyntheticPreUpdateNode(CallNode call) or + /** + * A synthetic node representing the value of an object after a state change. + * See QLDoc for `PostUpdateNode`. + */ + TSyntheticPostUpdateNode(ControlFlowNode node) { + exists(CallNode call | + node = call.getArg(_) + or + node = call.getArgByName(_) + or + // `self` argument when handling class instance calls (`__call__` special method)) + node = call.getFunction() + ) + or + node = any(AttrNode a).getObject() + or + node = any(SubscriptNode s).getObject() + or + // self parameter when used implicitly in `super()` + exists(Class cls, Function func, ParameterDefinition def | + func = cls.getAMethod() and + not isStaticmethod(func) and + // this matches what we do in ExtractedParameterNode + def.getDefiningNode() = node and + def.getParameter() = func.getArg(0) + ) + } or /** A node representing a global (module-level) variable in a specific module. */ TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m and @@ -45,37 +79,6 @@ newtype TNode = ImportStar::globalNameDefinedInModule(v.getId(), m) ) } or - /** - * A node representing the overflow positional arguments to a call. - * That is, `call` contains more positional arguments than there are - * positional parameters in `callable`. The extra ones are passed as - * a tuple to a starred parameter; this synthetic node represents that tuple. - */ - TPosOverflowNode(CallNode call, CallableValue callable) { - exists(getPositionalOverflowArg(call, callable, _)) - } or - /** - * A node representing the overflow keyword arguments to a call. - * That is, `call` contains keyword arguments for keys that do not have - * keyword parameters in `callable`. These extra ones are passed as - * a dictionary to a doubly starred parameter; this synthetic node - * represents that dictionary. - */ - TKwOverflowNode(CallNode call, CallableValue callable) { - exists(getKeywordOverflowArg(call, callable, _)) - or - ArgumentPassing::connects(call, callable) and - exists(call.getNode().getKwargs()) and - callable.getScope().hasKwArg() - } or - /** - * A node representing an unpacked element of a dictionary argument. - * That is, `call` contains argument `**{"foo": bar}` which is passed - * to parameter `foo` of `callable`. - */ - TKwUnpackedNode(CallNode call, CallableValue callable, string name) { - call_unpacks(call, _, callable, name, _) - } or /** * A synthetic node representing that an iterable sequence flows to consumer. */ @@ -109,10 +112,18 @@ newtype TNode = } or TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition pos) { FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos) + } or + /** A synthetic node to capture positional arguments that are passed to a `*args` parameter. */ + TSynthStarArgsElementParameterNode(DataFlowCallable callable) { + exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos))) + } or + /** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */ + TSynthDictSplatArgumentNode(CallNode call) { exists(call.getArgByName(_)) } or + /** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */ + TSynthDictSplatParameterNode(DataFlowCallable callable) { + exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos))) } -class TParameterNode = TCfgNode or TSummaryParameterNode; - /** Helper for `Node::getEnclosingCallable`. */ private DataFlowCallable getCallableScope(Scope s) { result.getScope() = s @@ -288,7 +299,7 @@ ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e } * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParameterNode extends Node, TParameterNode instanceof ParameterNodeImpl { +class ParameterNode extends Node instanceof ParameterNodeImpl { /** Gets the parameter corresponding to this node, if any. */ final Parameter getParameter() { result = super.getParameter() } } @@ -298,18 +309,8 @@ class ExtractedParameterNode extends ParameterNodeImpl, CfgNode { //, LocalSourceNode { ParameterDefinition def; - ExtractedParameterNode() { - node = def.getDefiningNode() and - // Disregard parameters that we cannot resolve - // TODO: Make this unnecessary - exists(DataFlowCallable c | node = c.getParameter(_)) - } + ExtractedParameterNode() { node = def.getDefiningNode() } - override predicate isParameterOf(DataFlowCallable c, int i) { node = c.getParameter(i) } - - override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) } - - /** Gets the `Parameter` this `ParameterNode` represents. */ override Parameter getParameter() { result = def.getParameter() } } @@ -327,16 +328,24 @@ abstract class ArgumentNode extends Node { final ExtractedDataFlowCall getCall() { this.argumentOf(result, _) } } -/** A data flow node that represents a call argument found in the source code. */ +/** + * A data flow node that represents a call argument found in the source code. + */ class ExtractedArgumentNode extends ArgumentNode { - ExtractedArgumentNode() { this = any(ExtractedDataFlowCall c).getArg(_) } - - final override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - this.extractedArgumentOf(call, pos) + ExtractedArgumentNode() { + // for resolved calls, we need to allow all argument nodes + getCallArg(_, _, _, this, _) + or + // for potential summaries we allow all normal call arguments + normalCallArg(_, this, _) + or + // and self arguments + this.asCfgNode() = any(CallNode c).getFunction().(AttrNode).getObject() } - predicate extractedArgumentOf(ExtractedDataFlowCall call, ArgumentPosition pos) { - this = call.getArg(pos) + final override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { + this = call.getArgument(pos) and + call instanceof ExtractedDataFlowCall } } @@ -345,16 +354,17 @@ class ExtractedArgumentNode extends ArgumentNode { * 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. + * (which might have mutated the argument), the qualifier of a field after + * an update to the field, or a container such as a list/dictionary after an element + * update. * * Nodes corresponding to AST elements, for example `ExprNode`s, usually refer - * to the value before the update with the exception of `ObjectCreationNode`s, + * to the value before the update with the exception of class calls, * which represents the value _after_ the constructor has run. */ -abstract class PostUpdateNode extends Node { +class PostUpdateNode extends Node instanceof PostUpdateNodeImpl { /** Gets the node before the state update. */ - abstract Node getPreUpdateNode(); + Node getPreUpdateNode() { result = super.getPreUpdateNode() } } /** @@ -448,70 +458,6 @@ private predicate resolved_import_star_module(Module m, string name, Node n) { ) } -/** - * The node holding the extra positional arguments to a call. This node is passed as a tuple - * to the starred parameter of the callable. - */ -class PosOverflowNode extends Node, TPosOverflowNode { - CallNode call; - - PosOverflowNode() { this = TPosOverflowNode(call, _) } - - override string toString() { result = "PosOverflowNode for " + call.getNode().toString() } - - override DataFlowCallable getEnclosingCallable() { - exists(Node node | - node = TCfgNode(call) and - result = node.getEnclosingCallable() - ) - } - - override Location getLocation() { result = call.getLocation() } -} - -/** - * The node holding the extra keyword arguments to a call. This node is passed as a dictionary - * to the doubly starred parameter of the callable. - */ -class KwOverflowNode extends Node, TKwOverflowNode { - CallNode call; - - KwOverflowNode() { this = TKwOverflowNode(call, _) } - - override string toString() { result = "KwOverflowNode for " + call.getNode().toString() } - - override DataFlowCallable getEnclosingCallable() { - exists(Node node | - node = TCfgNode(call) and - result = node.getEnclosingCallable() - ) - } - - override Location getLocation() { result = call.getLocation() } -} - -/** - * The node representing the synthetic argument of a call that is unpacked from a dictionary - * argument. - */ -class KwUnpackedNode extends Node, TKwUnpackedNode { - CallNode call; - string name; - - KwUnpackedNode() { this = TKwUnpackedNode(call, _, name) } - - override string toString() { result = "KwUnpacked " + name } - - override DataFlowCallable getEnclosingCallable() { - exists(Node node | - node = TCfgNode(call) and - result = node.getEnclosingCallable() - ) - } - - override Location getLocation() { result = call.getLocation() } -} - /** * A synthetic node representing an iterable sequence. Used for changing content type * for instance from a `ListElement` to a `TupleElement`, especially if the content is diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll index 2d731d72e99..dcf4d987e92 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll @@ -61,11 +61,11 @@ bindingset[c, rk] DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() } /** - * Gets the type of the `i`th parameter in a synthesized call that targets a - * callback of type `t`. + * Gets the type of the parameter matching arguments at position `pos` in a + * synthesized call that targets a callback of type `t`. */ -bindingset[t, i] -DataFlowType getCallbackParameterType(DataFlowType t, int i) { any() } +bindingset[t, pos] +DataFlowType getCallbackParameterType(DataFlowType t, ArgumentPosition pos) { any() } /** * Gets the return type of kind `rk` in a synthesized call that targets a @@ -114,10 +114,34 @@ string getComponentSpecific(SummaryComponent sc) { } /** Gets the textual representation of a parameter position in the format used for flow summaries. */ -string getParameterPosition(ParameterPosition pos) { result = pos.toString() } +string getParameterPosition(ParameterPosition pos) { + pos.isSelf() and result = "self" + or + exists(int i | + pos.isPositional(i) and + result = i.toString() + ) + or + exists(string name | + pos.isKeyword(name) and + result = name + ":" + ) +} /** Gets the textual representation of an argument position in the format used for flow summaries. */ -string getArgumentPosition(ArgumentPosition pos) { result = pos.toString() } +string getArgumentPosition(ArgumentPosition pos) { + pos.isSelf() and result = "self" + or + exists(int i | + pos.isPositional(i) and + result = i.toString() + ) + or + exists(string name | + pos.isKeyword(name) and + result = name + ":" + ) +} /** Holds if input specification component `c` needs a reference. */ predicate inputNeedsReferenceSpecific(string c) { none() } @@ -197,29 +221,55 @@ module ParsePositions { ) } - predicate isParsedParameterPosition(string c, int i) { + predicate isParsedPositionalParameterPosition(string c, int i) { isParamBody(c) and i = AccessPath::parseInt(c) } - predicate isParsedArgumentPosition(string c, int i) { + predicate isParsedKeywordParameterPosition(string c, string paramName) { + isParamBody(c) and + c = paramName + ":" + } + + predicate isParsedPositionalArgumentPosition(string c, int i) { isArgBody(c) and i = AccessPath::parseInt(c) } + + predicate isParsedKeywordArgumentPosition(string c, string argName) { + isArgBody(c) and + c = argName + ":" + } } /** Gets the argument position obtained by parsing `X` in `Parameter[X]`. */ ArgumentPosition parseParamBody(string s) { exists(int i | - ParsePositions::isParsedParameterPosition(s, i) and + ParsePositions::isParsedPositionalParameterPosition(s, i) and result.isPositional(i) ) + or + exists(string name | + ParsePositions::isParsedKeywordParameterPosition(s, name) and + result.isKeyword(name) + ) + or + s = "self" and + result.isSelf() } /** Gets the parameter position obtained by parsing `X` in `Argument[X]`. */ ParameterPosition parseArgBody(string s) { exists(int i | - ParsePositions::isParsedArgumentPosition(s, i) and + ParsePositions::isParsedPositionalArgumentPosition(s, i) and result.isPositional(i) ) + or + exists(string name | + ParsePositions::isParsedKeywordArgumentPosition(s, name) and + result.isKeyword(name) + ) + or + s = "self" and + result.isSelf() } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll index e4af21caacc..7af9ca524aa 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll @@ -71,13 +71,19 @@ module ImportResolution { */ pragma[nomagic] predicate module_export(Module m, string name, DataFlow::CfgNode defn) { - exists(EssaVariable v | + exists(EssaVariable v, EssaDefinition essaDef | v.getName() = name and - v.getAUse() = ImportStar::getStarImported*(m).getANormalExit() + v.getAUse() = ImportStar::getStarImported*(m).getANormalExit() and + ( + essaDef = v.getDefinition() + or + // to handle definitions guarded by if-then-else + essaDef = v.getDefinition().(PhiFunction).getAnInput() + ) | - defn.getNode() = v.getDefinition().(AssignmentDefinition).getValue() + defn.getNode() = essaDef.(AssignmentDefinition).getValue() or - defn.getNode() = v.getDefinition().(ArgumentRefinement).getArgument() + defn.getNode() = essaDef.(ArgumentRefinement).getArgument() ) or exists(Alias a | @@ -167,8 +173,22 @@ module ImportResolution { ) } + /** + * Gets the (most likely) module for the name `name`, if any. + * + * Handles the fact that for the name `` representing a package the actual module + * is `.__init__`. + * + * See `isPreferredModuleForName` for more details on what "most likely" module means. + */ + pragma[inline] + private Module getModuleFromName(string name) { + isPreferredModuleForName(result.getFile(), name + ["", ".__init__"]) + } + + /** Gets the module from which attributes are imported by `i`. */ Module getModuleImportedByImportStar(ImportStar i) { - isPreferredModuleForName(result.getFile(), i.getImportedModuleName()) + result = getModuleFromName(i.getImportedModuleName()) } /** @@ -223,7 +243,7 @@ module ImportResolution { exists(string module_name | result = getReferenceToModuleName(module_name) | // Depending on whether the referenced module is a package or not, we may need to add a // trailing `.__init__` to the module name. - isPreferredModuleForName(m.getFile(), module_name + ["", ".__init__"]) + m = getModuleFromName(module_name) or // Module defined via `sys.modules` m = sys_modules_module_with_name(module_name) @@ -234,7 +254,7 @@ module ImportResolution { ar.accesses(getModuleReference(p), attr_name) and result = ar | - isPreferredModuleForName(m.getFile(), p.getPackageName() + "." + attr_name + ["", ".__init__"]) + m = getModuleFromName(p.getPackageName() + "." + attr_name) ) or // This is also true for attributes that come from reexports. @@ -248,8 +268,7 @@ module ImportResolution { exists(string submodule, Module package | SsaSource::init_module_submodule_defn(result.asVar().getSourceVariable(), package.getEntryNode()) and - isPreferredModuleForName(m.getFile(), - package.getPackageName() + "." + submodule + ["", ".__init__"]) + m = getModuleFromName(package.getPackageName() + "." + submodule) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll index 690216089e9..67e3db984e8 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll @@ -60,22 +60,6 @@ string getPossibleContentName() { result = any(DataFlowPublic::AttrRef a).getAttributeName() } -/** - * Gets a callable for the call where `nodeFrom` is used as the `i`'th argument. - * - * Helper predicate to avoid bad join order experienced in `callStep`. - * This happened when `isParameterOf` was joined _before_ `getCallable`. - */ -pragma[nomagic] -private DataFlowPrivate::DataFlowCallable getCallableForArgument( - DataFlowPublic::ExtractedArgumentNode nodeFrom, int i -) { - exists(DataFlowPrivate::ExtractedDataFlowCall call | - nodeFrom.extractedArgumentOf(call, i) and - result = call.getCallable() - ) -} - /** * Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call. * @@ -83,11 +67,15 @@ private DataFlowPrivate::DataFlowCallable getCallableForArgument( * recursion (or, at best, terrible performance), since identifying calls to library * methods is done using API graphs (which uses type tracking). */ -predicate callStep(DataFlowPublic::ArgumentNode nodeFrom, DataFlowPrivate::ParameterNodeImpl nodeTo) { - // TODO: Support special methods? - exists(DataFlowPrivate::DataFlowCallable callable, int i | - callable = getCallableForArgument(nodeFrom, i) and - nodeTo.isParameterOf(callable, i) +predicate callStep(DataFlowPublic::ArgumentNode nodeFrom, DataFlowPublic::ParameterNode nodeTo) { + exists( + DataFlowPrivate::DataFlowCall call, DataFlowPrivate::DataFlowCallable callable, + DataFlowPrivate::ArgumentPosition apos, DataFlowPrivate::ParameterPosition ppos + | + nodeFrom = call.getArgument(apos) and + nodeTo = callable.getParameter(ppos) and + DataFlowPrivate::parameterMatch(ppos, apos) and + callable = call.getCallable() ) } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 3fce979c147..4a4b34af422 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1465,7 +1465,19 @@ private module StdlibPrivate { t.start() and result = openCall and ( - openCall instanceof OpenCall + openCall instanceof OpenCall and + // don't include the open call inside of Path.open in pathlib.py since + // the call to `path_obj.open` is covered by `PathLibOpenCall`. + not exists(Module mod, Class cls, Function func | + openCall.(OpenCall).asCfgNode().getScope() = func and + func.getName() = "open" and + func.getScope() = cls and + cls.getName() = "Path" and + cls.getScope() = mod and + mod.getName() = "pathlib" and + // do allow this call if we're analyzing pathlib.py as part of CPython though + not exists(mod.getFile().getRelativePath()) + ) or openCall instanceof PathLibOpenCall ) @@ -2669,6 +2681,7 @@ private module StdlibPrivate { HashlibNewCall() { this = hashlibNewCall(hashName) and + // we only want to consider it as an cryptographic operation if the input is available exists(this.getParameter(1, "data")) } @@ -2751,6 +2764,78 @@ private module StdlibPrivate { } } + // --------------------------------------------------------------------------- + // hmac + // --------------------------------------------------------------------------- + abstract class HmacCryptographicOperation extends Cryptography::CryptographicOperation::Range, + API::CallNode { + abstract API::Node getDigestArg(); + + override Cryptography::CryptographicAlgorithm getAlgorithm() { + exists(string algorithmName | result.matchesName(algorithmName) | + this.getDigestArg().asSink() = hashlibMember(algorithmName).asSource() + or + this.getDigestArg().getAValueReachingSink().asExpr().(StrConst).getText() = algorithmName + ) + } + + override Cryptography::BlockMode getBlockMode() { none() } + } + + API::CallNode getHmacConstructorCall(API::Node digestArg) { + result = API::moduleImport("hmac").getMember(["new", "HMAC"]).getACall() and + digestArg = result.getParameter(2, "digestmod") + } + + /** + * A call to `hmac.new`/`hmac.HMAC`. + * + * See https://docs.python.org/3.11/library/hmac.html#hmac.new + */ + class HmacNewCall extends HmacCryptographicOperation { + API::Node digestArg; + + HmacNewCall() { + this = getHmacConstructorCall(digestArg) and + // we only want to consider it as an cryptographic operation if the input is available + exists(this.getParameter(1, "msg").asSink()) + } + + override API::Node getDigestArg() { result = digestArg } + + override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() } + } + + /** + * A call to `.update` on an HMAC object. + * + * See https://docs.python.org/3.11/library/hmac.html#hmac.HMAC.update + */ + class HmacUpdateCall extends HmacCryptographicOperation { + API::Node digestArg; + + HmacUpdateCall() { + this = getHmacConstructorCall(digestArg).getReturn().getMember("update").getACall() + } + + override API::Node getDigestArg() { result = digestArg } + + override DataFlow::Node getAnInput() { result = this.getParameter(0, "msg").asSink() } + } + + /** + * A call to `hmac.digest`. + * + * See https://docs.python.org/3.11/library/hmac.html#hmac.digest + */ + class HmacDigestCall extends HmacCryptographicOperation { + HmacDigestCall() { this = API::moduleImport("hmac").getMember("digest").getACall() } + + override API::Node getDigestArg() { result = this.getParameter(2, "digest") } + + override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() } + } + // --------------------------------------------------------------------------- // logging // --------------------------------------------------------------------------- diff --git a/python/ql/lib/semmle/python/internal/CachedStages.qll b/python/ql/lib/semmle/python/internal/CachedStages.qll index 290a90f5a73..40dda556caa 100644 --- a/python/ql/lib/semmle/python/internal/CachedStages.qll +++ b/python/ql/lib/semmle/python/internal/CachedStages.qll @@ -93,6 +93,8 @@ module Stages { exists(PyFlow::DefinitionNode b) or exists(any(PyFlow::SequenceNode n).getElement(_)) + or + exists(any(PyFlow::ControlFlowNode c).toString()) } } @@ -125,6 +127,45 @@ module Stages { } } + /** + * The points-to stage. + */ + cached + module PointsTo { + /** + * Always holds. + * Ensures that a predicate is evaluated as part of the points-to stage. + */ + cached + predicate ref() { 1 = 1 } + + private import semmle.python.pointsto.Base as PointsToBase + private import semmle.python.types.Object as TypeObject + private import semmle.python.objects.TObject as TObject + private import semmle.python.objects.ObjectInternal as ObjectInternal + // have to alias since this module is also called PointsTo + private import semmle.python.pointsto.PointsTo as RealPointsTo + + /** + * DONT USE! + * Contains references to each predicate that use the above `ref` predicate. + */ + cached + predicate backref() { + 1 = 1 + or + PointsToBase::BaseFlow::scope_entry_value_transfer_from_earlier(_, _, _, _) + or + exists(TypeObject::Object a) + or + exists(TObject::TObject f) + or + exists(any(ObjectInternal::ObjectInternal o).toString()) + or + RealPointsTo::AttributePointsTo::variableAttributePointsTo(_, _, _, _, _) + } + } + /** * The `dataflow` stage. */ @@ -138,14 +179,9 @@ module Stages { predicate ref() { 1 = 1 } private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic + private import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch private import semmle.python.dataflow.new.internal.LocalSources as LocalSources private import semmle.python.internal.Awaited as Awaited - private import semmle.python.pointsto.Base as PointsToBase - private import semmle.python.types.Object as TypeObject - private import semmle.python.objects.TObject as TObject - private import semmle.python.Flow as Flow - private import semmle.python.objects.ObjectInternal as ObjectInternal - private import semmle.python.pointsto.PointsTo as PointsTo /** * DONT USE! @@ -159,21 +195,13 @@ module Stages { or any(DataFlowPublic::Node node).hasLocationInfo(_, _, _, _, _) or + DataFlowDispatch::resolveCall(_, _, _) + or + DataFlowDispatch::getCallArg(_, _, _, _, _) + or any(LocalSources::LocalSourceNode n).flowsTo(_) or exists(Awaited::awaited(_)) - or - PointsToBase::BaseFlow::scope_entry_value_transfer_from_earlier(_, _, _, _) - or - exists(TypeObject::Object a) - or - exists(TObject::TObject f) - or - exists(any(Flow::ControlFlowNode c).toString()) - or - exists(any(ObjectInternal::ObjectInternal o).toString()) - or - PointsTo::AttributePointsTo::variableAttributePointsTo(_, _, _, _, _) } } } diff --git a/python/ql/lib/semmle/python/internal/ConceptsShared.qll b/python/ql/lib/semmle/python/internal/ConceptsShared.qll index 2f6c8bb8b29..e86b156e204 100644 --- a/python/ql/lib/semmle/python/internal/ConceptsShared.qll +++ b/python/ql/lib/semmle/python/internal/ConceptsShared.qll @@ -45,8 +45,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ BlockMode getBlockMode() { result = super.getBlockMode() } } @@ -69,8 +73,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ abstract BlockMode getBlockMode(); } @@ -81,10 +89,21 @@ module Cryptography { * data of arbitrary length using a block encryption algorithm. */ class BlockMode extends string { - BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] } + BlockMode() { + this = + [ + "ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP", + "XTS", // https://csrc.nist.gov/publications/detail/sp/800-38e/final + "EAX" // https://en.wikipedia.org/wiki/EAX_mode + ] + } /** Holds if this block mode is considered to be insecure. */ predicate isWeak() { this = "ECB" } + + /** Holds if the given string appears to match this block mode. */ + bindingset[s] + predicate matchesString(string s) { s.toUpperCase().matches("%" + this + "%") } } } diff --git a/python/ql/lib/semmle/python/objects/ObjectInternal.qll b/python/ql/lib/semmle/python/objects/ObjectInternal.qll index b6725e87cb6..a58b8b5f0a9 100644 --- a/python/ql/lib/semmle/python/objects/ObjectInternal.qll +++ b/python/ql/lib/semmle/python/objects/ObjectInternal.qll @@ -216,7 +216,7 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { override Builtin getBuiltin() { this = TBuiltinOpaqueObject(result) } override string toString() { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and result = this.getBuiltin().getClass().getName() + " object" } diff --git a/python/ql/lib/semmle/python/pointsto/Base.qll b/python/ql/lib/semmle/python/pointsto/Base.qll index a3407419da2..96437cfed7e 100644 --- a/python/ql/lib/semmle/python/pointsto/Base.qll +++ b/python/ql/lib/semmle/python/pointsto/Base.qll @@ -318,7 +318,7 @@ module BaseFlow { predicate scope_entry_value_transfer_from_earlier( EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope ) { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and exists(SsaSourceVariable var | essa_var_scope(var, pred_scope, pred_var) and scope_entry_def_scope(var, succ_scope, succ_def) diff --git a/python/ql/lib/semmle/python/pointsto/PointsTo.qll b/python/ql/lib/semmle/python/pointsto/PointsTo.qll index 6068d7308c9..1369d6d6ce7 100644 --- a/python/ql/lib/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/lib/semmle/python/pointsto/PointsTo.qll @@ -2566,7 +2566,7 @@ module AttributePointsTo { predicate variableAttributePointsTo( EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin ) { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and definitionAttributePointsTo(var.getDefinition(), context, name, value, origin) or exists(EssaVariable prev | diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll index fcf8885f3f4..ae61bd04314 100644 --- a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll @@ -57,16 +57,43 @@ module CleartextLogging { /** A piece of data printed, considered as a flow sink. */ class PrintedDataAsSink extends Sink { PrintedDataAsSink() { - this = API::builtin("print").getACall().getArg(_) - or - // special handling of writing to `sys.stdout` and `sys.stderr`, which is - // essentially the same as printing - this = - API::moduleImport("sys") - .getMember(["stdout", "stderr"]) - .getMember("write") - .getACall() - .getArg(0) + ( + this = API::builtin("print").getACall().getArg(_) + or + // special handling of writing to `sys.stdout` and `sys.stderr`, which is + // essentially the same as printing + this = + API::moduleImport("sys") + .getMember(["stdout", "stderr"]) + .getMember("write") + .getACall() + .getArg(0) + ) and + // since some of the inner error handling implementation of the logging module is + // ```py + // sys.stderr.write('Message: %r\n' + // 'Arguments: %s\n' % (record.msg, + // record.args)) + // ``` + // any time we would report flow to such a logging sink, we can ALSO report + // the flow to the `record.msg`/`record.args` sinks -- obviously we + // don't want that. + // + // However, simply removing taint edges out of a sink is not a good enough solution, + // since we would only flag one of the `logging.info` calls in the following example + // due to use-use flow + // ```py + // logging.info(user_controlled) + // logging.info(user_controlled) + // ``` + // + // The same approach is used in the command injection query. + not exists(Module loggingInit | + loggingInit.getName() = "logging.__init__" and + this.getScope().getEnclosingModule() = loggingInit and + // do allow this call if we're analyzing logging/__init__.py as part of CPython though + not exists(loggingInit.getFile().getRelativePath()) + ) } } } diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll index 0ff32823d68..001b9395ef4 100644 --- a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll @@ -50,7 +50,34 @@ module CleartextStorage { /** The data written to a file, considered as a flow sink. */ class FileWriteDataAsSink extends Sink { - FileWriteDataAsSink() { this = any(FileSystemWriteAccess write).getADataNode() } + FileWriteDataAsSink() { + this = any(FileSystemWriteAccess write).getADataNode() and + // since implementation of Path.write_bytes in pathlib.py is like + // ```py + // def write_bytes(self, data): + // with self.open(mode='wb') as f: + // return f.write(data) + // ``` + // any time we would report flow to the `Path.write_bytes` sink, we can ALSO report + // the flow from the `data` parameter to the `f.write` sink -- obviously we + // don't want that. + // + // However, simply removing taint edges out of a sink is not a good enough solution, + // since we would only flag one of the `p.write` calls in the following example + // due to use-use flow + // ```py + // p.write(user_controlled) + // p.write(user_controlled) + // ``` + // + // The same approach is used in the command injection query. + not exists(Module pathlib | + pathlib.getName() = "pathlib" and + this.getScope().getEnclosingModule() = pathlib and + // do allow this call if we're analyzing pathlib.py as part of CPython though + not exists(pathlib.getFile().getRelativePath()) + ) + } } /** The data written to a cookie on a HTTP response, considered as a flow sink. */ diff --git a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll index a18bfe73372..d43095a04f8 100644 --- a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll @@ -76,6 +76,9 @@ module CommandInjection { // `subprocess`. See: // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341 + // + // The same approach is used in the path-injection, cleartext-storage, and + // cleartext-logging queries. not this.getScope().getEnclosingModule().getName() in [ "os", "subprocess", "platform", "popen2" ] diff --git a/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll index a96bbb996bc..b50ff70fde2 100644 --- a/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll @@ -58,7 +58,33 @@ module PathInjection { * A file system access, considered as a flow sink. */ class FileSystemAccessAsSink extends Sink { - FileSystemAccessAsSink() { this = any(FileSystemAccess e).getAPathArgument() } + FileSystemAccessAsSink() { + this = any(FileSystemAccess e).getAPathArgument() and + // since implementation of Path.open in pathlib.py is like + // ```py + // def open(self, ...): + // return io.open(self, ...) + // ``` + // any time we would report flow to the `path_obj.open` sink, we can ALSO report + // the flow from the `self` parameter to the `io.open` sink -- obviously we + // don't want that. + // + // However, simply removing taint edges out of a sink is not a good enough solution, + // since we would only flag one of the `p.open` calls in the following example + // due to use-use flow + // ```py + // p.open() + // p.open() + // ``` + // + // The same approach is used in the command injection query. + not exists(Module pathlib | + pathlib.getName() = "pathlib" and + this.getScope().getEnclosingModule() = pathlib and + // do allow this call if we're analyzing pathlib.py as part of CPython though + not exists(pathlib.getFile().getRelativePath()) + ) + } } private import semmle.python.frameworks.data.ModelsAsData diff --git a/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll index 9a31dcc2a10..c454ff8e994 100644 --- a/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll +++ b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll @@ -41,7 +41,32 @@ module StackTraceExposure { /** * A source of exception info, considered as a flow source. */ - class ExceptionInfoAsSource extends Source instanceof ExceptionInfo { } + class ExceptionInfoAsSource extends Source instanceof ExceptionInfo { + ExceptionInfoAsSource() { + // since `traceback.format_exc()` in Python 2 is internally implemented as + // ```py + // def format_exc(limit=None): + // """Like print_exc() but return a string.""" + // try: + // etype, value, tb = sys.exc_info() + // return ''.join(format_exception(etype, value, tb, limit)) + // finally: + // etype = value = tb = None + // ``` + // any time we would report flow to such from a call to format_exc, we can ALSO report + // the flow from the `sys.exc_info()` source -- obviously we don't want that. + // + // + // To avoid this, we use the same approach as for sinks in the command injection + // query (and others). + not exists(Module traceback | + traceback.getName() = "traceback" and + this.getScope().getEnclosingModule() = traceback and + // do allow this call if we're analyzing traceback.py as part of CPython though + not exists(traceback.getFile().getRelativePath()) + ) + } + } /** * The body of a HTTP response that will be returned from a server, considered as a flow sink. diff --git a/python/ql/lib/semmle/python/types/Builtins.qll b/python/ql/lib/semmle/python/types/Builtins.qll index 066b496b80e..e6a21e1b717 100644 --- a/python/ql/lib/semmle/python/types/Builtins.qll +++ b/python/ql/lib/semmle/python/types/Builtins.qll @@ -111,11 +111,7 @@ class Builtin extends @py_cobject { } module Builtin { - Builtin builtinModule() { - py_special_objects(result, "builtin_module_2") and major_version() = 2 - or - py_special_objects(result, "builtin_module_3") and major_version() = 3 - } + Builtin builtinModule() { py_special_objects(result, "builtin_module") } Builtin builtin(string name) { result = builtinModule().getMember(name) } diff --git a/python/ql/lib/semmle/python/types/Object.qll b/python/ql/lib/semmle/python/types/Object.qll index e0d252929f9..b408fc7ba1c 100644 --- a/python/ql/lib/semmle/python/types/Object.qll +++ b/python/ql/lib/semmle/python/types/Object.qll @@ -5,7 +5,7 @@ private import semmle.python.internal.CachedStages cached private predicate is_an_object(@py_object obj) { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and /* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */ obj instanceof ControlFlowNode and not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and @@ -78,7 +78,7 @@ class Object extends @py_object { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and this.hasOrigin() and this.getOrigin() .getLocation() @@ -98,7 +98,7 @@ class Object extends @py_object { /** Gets a textual representation of this element. */ cached string toString() { - Stages::DataFlow::ref() and + Stages::PointsTo::ref() and not this = undefinedVariable() and not this = unknownValue() and exists(ClassObject type | type.asBuiltin() = this.asBuiltin().getClass() | diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index 6199749411d..eace5e34204 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.3 + +No user-facing changes. + ## 0.6.2 No user-facing changes. diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll index 85b0a730cf1..94762ace98c 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll @@ -1,48 +1,36 @@ /** * Definitions for reasoning about untrusted data used in APIs defined outside the - * database. + * user-written code. */ -import python +private import python import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.TaintTracking -import semmle.python.Concepts -import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.ApiGraphs private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate private import semmle.python.dataflow.new.internal.TaintTrackingPrivate as TaintTrackingPrivate -private import semmle.python.types.Builtins -private import semmle.python.objects.ObjectInternal -// IMPLEMENTATION NOTES: -// -// This query uses *both* the new data-flow library, and points-to. Why? To get this -// finished quickly, so it can provide value for our field team and ourselves. -// -// In the long run, it should not need to use points-to for anything. Possibly this can -// even be helpful in figuring out what we need from TypeTrackers and the new data-flow -// library to be fully operational. -// -// At least it will allow us to provide a baseline comparison against a solution that -// doesn't use points-to at all -// -// There is a few dirty things we do here: -// 1. DataFlowPrivate: since `DataFlowCall` and `DataFlowCallable` are not exposed -// publicly, but we really want access to them. -// 2. points-to: we kinda need to do this since this is what powers `DataFlowCall` and -// `DataFlowCallable` -// 3. ObjectInternal: to provide better names for built-in functions and methods. If we -// really wanted to polish our points-to implementation, we could move this -// functionality into `BuiltinFunctionValue` and `BuiltinMethodValue`, but will -// probably require some more work: for this query, it's totally ok to use -// `builtins.open` for the code `open(f)`, but well, it requires a bit of thinking to -// figure out if that is desirable in general. I simply skipped a corner here! -// 4. TaintTrackingPrivate: Nothing else gives us access to `defaultAdditionalTaintStep` :( /** - * A callable that is considered a "safe" external API from a security perspective. + * An external API that is considered "safe" from a security perspective. */ class SafeExternalApi extends Unit { - /** Gets a callable that is considered a "safe" external API from a security perspective. */ - abstract DataFlowPrivate::DataFlowCallable getSafeCallable(); + /** + * Gets a call that is considered "safe" from a security perspective. You can use API + * graphs to find calls to functions you know are safe. + * + * Which works even when the external library isn't extracted. + */ + abstract DataFlow::CallCfgNode getSafeCall(); + + /** + * Gets a callable that is considered a "safe" external API from a security + * perspective. + * + * You probably want to define this as `none()` and use `getSafeCall` instead, since + * that can handle the external library not being extracted. + */ + DataFlowPrivate::DataFlowCallable getSafeCallable() { none() } } /** DEPRECATED: Alias for SafeExternalApi */ @@ -50,42 +38,127 @@ deprecated class SafeExternalAPI = SafeExternalApi; /** The default set of "safe" external APIs. */ private class DefaultSafeExternalApi extends SafeExternalApi { - override DataFlowPrivate::DataFlowCallable getSafeCallable() { - exists(CallableValue cv | cv = result.getCallableValue() | - cv = Value::named(["len", "isinstance", "getattr", "hasattr"]) - or - exists(ClassValue cls, string attr | - cls = Value::named("dict") and attr in ["__getitem__", "__setitem__"] - | - cls.lookup(attr) = cv - ) + override DataFlow::CallCfgNode getSafeCall() { + result = + API::builtin([ + "len", "enumerate", "isinstance", "getattr", "hasattr", "bool", "float", "int", "repr", + "str", "type" + ]).getACall() + } +} + +/** + * Gets a human readable representation of `node`. + * + * Note that this is only defined for API nodes that are allowed as external APIs, + * so `None.json.dumps` will for example not be allowed. + */ +string apiNodeToStringRepr(API::Node node) { + node = API::builtin(result) + or + node = API::moduleImport(result) + or + exists(API::Node base, string basename | + base.getDepth() < node.getDepth() and + basename = apiNodeToStringRepr(base) and + not base = API::builtin(["None", "True", "False"]) + | + exists(string m | node = base.getMember(m) | result = basename + "." + m) + or + node = base.getReturn() and + result = basename + "()" and + not base.getACall() = any(SafeExternalApi safe).getSafeCall() + or + node = base.getAwaited() and + result = basename + ) +} + +predicate resolvedCall(CallNode call) { + DataFlowPrivate::resolveCall(call, _, _) or + DataFlowPrivate::resolveClassCall(call, _) +} + +newtype TInterestingExternalApiCall = + TUnresolvedCall(DataFlow::CallCfgNode call) { + exists(call.getLocation().getFile().getRelativePath()) and + not resolvedCall(call.getNode()) and + not call = any(SafeExternalApi safe).getSafeCall() + } or + TResolvedCall(DataFlowPrivate::DataFlowCall call) { + exists(call.getLocation().getFile().getRelativePath()) and + exists(call.getCallable()) and + not call.getCallable() = any(SafeExternalApi safe).getSafeCallable() and + // ignore calls inside codebase, and ignore calls that are marked as safe. This is + // only needed as long as we extract dependencies. When we stop doing that, all + // targets of resolved calls will be from user-written code. + not exists(call.getCallable().getLocation().getFile().getRelativePath()) and + not exists(DataFlow::CallCfgNode callCfgNode | callCfgNode.getNode() = call.getNode() | + any(SafeExternalApi safe).getSafeCall() = callCfgNode + ) + } + +abstract class InterestingExternalApiCall extends TInterestingExternalApiCall { + /** Gets the argument at position `apos`, if any */ + abstract DataFlow::Node getArgument(DataFlowPrivate::ArgumentPosition apos); + + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** + * Gets a human-readable name for the external API. + */ + abstract string getApiName(); +} + +class UnresolvedCall extends InterestingExternalApiCall, TUnresolvedCall { + DataFlow::CallCfgNode call; + + UnresolvedCall() { this = TUnresolvedCall(call) } + + override DataFlow::Node getArgument(DataFlowPrivate::ArgumentPosition apos) { + exists(int i | apos.isPositional(i) | result = call.getArg(i)) + or + exists(string name | apos.isKeyword(name) | result = call.getArgByName(name)) + } + + override string toString() { + result = "ExternalAPI:UnresolvedCall: " + call.getNode().getNode().toString() + } + + override string getApiName() { + exists(API::Node apiNode | + result = apiNodeToStringRepr(apiNode) and + apiNode.getACall() = call + ) + } +} + +class ResolvedCall extends InterestingExternalApiCall, TResolvedCall { + DataFlowPrivate::DataFlowCall dfCall; + + ResolvedCall() { this = TResolvedCall(dfCall) } + + override DataFlow::Node getArgument(DataFlowPrivate::ArgumentPosition apos) { + result = dfCall.getArgument(apos) + } + + override string toString() { + result = "ExternalAPI:ResolvedCall: " + dfCall.getNode().getNode().toString() + } + + override string getApiName() { + exists(DataFlow::CallCfgNode call, API::Node apiNode | dfCall.getNode() = call.getNode() | + result = apiNodeToStringRepr(apiNode) and + apiNode.getACall() = call ) } } /** A node representing data being passed to an external API through a call. */ class ExternalApiDataNode extends DataFlow::Node { - DataFlowPrivate::DataFlowCallable callable; - int i; - ExternalApiDataNode() { - exists(DataFlowPrivate::DataFlowCall call | - exists(call.getLocation().getFile().getRelativePath()) - | - callable = call.getCallable() and - // TODO: this ignores some complexity of keyword arguments (especially keyword-only args) - this = call.getArg(i) - ) and - not any(SafeExternalApi safe).getSafeCallable() = callable and - exists(Value cv | cv = callable.getCallableValue() | - cv.isAbsent() - or - cv.isBuiltin() - or - cv.(CallableValue).getScope().getLocation().getFile().inStdlib() - or - not exists(cv.(CallableValue).getScope().getLocation().getFile().getRelativePath()) - ) and + exists(InterestingExternalApiCall call | this = call.getArgument(_)) and // Not already modeled as a taint step not TaintTrackingPrivate::defaultAdditionalTaintStep(this, _) and // for `list.append(x)`, we have a additional taint step from x -> [post] list. @@ -95,12 +168,6 @@ class ExternalApiDataNode extends DataFlow::Node { TaintTrackingPrivate::defaultAdditionalTaintStep(_, post) ) } - - /** Gets the index for the parameter that will receive this untrusted data */ - int getIndex() { result = i } - - /** Gets the callable to which this argument is passed. */ - DataFlowPrivate::DataFlowCallable getCallable() { result = callable } } /** DEPRECATED: Alias for ExternalApiDataNode */ @@ -133,19 +200,26 @@ deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode; /** An external API which is used with untrusted data. */ private newtype TExternalApi = - /** An untrusted API method `m` where untrusted data is passed at `index`. */ - TExternalApiParameter(DataFlowPrivate::DataFlowCallable callable, int index) { - exists(UntrustedExternalApiDataNode n | - callable = n.getCallable() and - index = n.getIndex() + MkExternalApi(string repr, DataFlowPrivate::ArgumentPosition apos) { + exists(UntrustedExternalApiDataNode ex, InterestingExternalApiCall call | + ex = call.getArgument(apos) and + repr = call.getApiName() ) } -/** An external API which is used with untrusted data. */ -class ExternalApiUsedWithUntrustedData extends TExternalApi { +/** A argument of an external API which is used with untrusted data. */ +class ExternalApiUsedWithUntrustedData extends MkExternalApi { + string repr; + DataFlowPrivate::ArgumentPosition apos; + + ExternalApiUsedWithUntrustedData() { this = MkExternalApi(repr, apos) } + /** Gets a possibly untrusted use of this external API. */ UntrustedExternalApiDataNode getUntrustedDataNode() { - this = TExternalApiParameter(result.getCallable(), result.getIndex()) + exists(InterestingExternalApiCall call | + result = call.getArgument(apos) and + call.getApiName() = repr + ) } /** Gets the number of untrusted sources used with this external API. */ @@ -154,63 +228,8 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi { } /** Gets a textual representation of this element. */ - string toString() { - exists( - DataFlowPrivate::DataFlowCallable callable, int index, string callableString, - string indexString - | - this = TExternalApiParameter(callable, index) and - indexString = "param " + index and - exists(CallableValue cv | cv = callable.getCallableValue() | - callableString = - cv.getScope().getEnclosingModule().getName() + "." + cv.getScope().getQualifiedName() - or - not exists(cv.getScope()) and - ( - cv instanceof BuiltinFunctionValue and - callableString = pretty_builtin_function_value(cv) - or - cv instanceof BuiltinMethodValue and - callableString = pretty_builtin_method_value(cv) - or - not cv instanceof BuiltinFunctionValue and - not cv instanceof BuiltinMethodValue and - callableString = cv.toString() - ) - ) and - result = callableString + " [" + indexString + "]" - ) - } + string toString() { result = repr + " [" + apos + "]" } } /** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */ deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData; - -/** Gets the fully qualified name for the `BuiltinFunctionValue` bfv. */ -private string pretty_builtin_function_value(BuiltinFunctionValue bfv) { - exists(Builtin b | b = bfv.(BuiltinFunctionObjectInternal).getBuiltin() | - result = prefix_with_module_if_found(b) - ) -} - -/** Gets the fully qualified name for the `BuiltinMethodValue` bmv. */ -private string pretty_builtin_method_value(BuiltinMethodValue bmv) { - exists(Builtin b | b = bmv.(BuiltinMethodObjectInternal).getBuiltin() | - exists(Builtin cls | cls.isClass() and cls.getMember(b.getName()) = b | - result = prefix_with_module_if_found(cls) + "." + b.getName() - ) - or - not exists(Builtin cls | cls.isClass() and cls.getMember(b.getName()) = b) and - result = b.getName() - ) -} - -/** Helper predicate that tries to adds module qualifier to `b`. Will succeed even if module not found. */ -private string prefix_with_module_if_found(Builtin b) { - exists(Builtin mod | mod.isModule() and mod.getMember(b.getName()) = b | - result = mod.getName() + "." + b.getName() - ) - or - not exists(Builtin mod | mod.isModule() and mod.getMember(b.getName()) = b) and - result = b.getName() -} diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp index 0627615ca64..e0692ffeae0 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp @@ -11,11 +11,9 @@ relevant for security analysis of this application.

An external API is defined as a call to a method that is not defined in the source code, and is not modeled as a taint step in the default taint library. External APIs may -be from the Python standard library or dependencies. The query will report the fully qualified name, -along with [param x], where x indicates the position of -the parameter receiving the untrusted data. Note that for methods and -classmethods, parameter 0 represents the class instance or class itself -respectively.

+be from the Python standard library or dependencies. The query will report the fully +qualified name, along with [position index] or [keyword name], +to indicate the argument passing the untrusted data.

Note that an excepted sink might not be included in the results, if it also defines a taint step. This is the case for pickle.loads which is a sink for the @@ -24,8 +22,6 @@ Unsafe Deserialization query, but is also a taint step for other queries.

Note: Compared to the Java version of this query, we currently do not give special care to methods that are overridden in the source code.

-

Note: Currently this query will only report results for external packages that are extracted.

- diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp index fc7f1a18da9..2b8c31d37b7 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp @@ -11,11 +11,9 @@ be modeled as either taint steps, or sinks for specific problems.

An external API is defined as a call to a method that is not defined in the source code, and is not modeled as a taint step in the default taint library. External APIs may -be from the Python standard library or dependencies. The query will report the fully qualified name, -along with [param x], where x indicates the position of -the parameter receiving the untrusted data. Note that for methods and -classmethods, parameter 0 represents the class instance or class itself -respectively.

+be from the Python standard library or dependencies. The query will report the fully +qualified name, along with [position index] or [keyword name], +to indicate the argument passing the untrusted data.

Note that an excepted sink might not be included in the results, if it also defines a taint step. This is the case for pickle.loads which is a sink for the @@ -24,8 +22,6 @@ Unsafe Deserialization query, but is also a taint step for other queries.

Note: Compared to the Java version of this query, we currently do not give special care to methods that are overridden in the source code.

-

Note: Currently this query will only report results for external packages that are extracted.

- diff --git a/python/ql/src/Security/CWE-022/examples/tainted_path.py b/python/ql/src/Security/CWE-022/examples/tainted_path.py index 31dfafc9309..b3d402874d5 100644 --- a/python/ql/src/Security/CWE-022/examples/tainted_path.py +++ b/python/ql/src/Security/CWE-022/examples/tainted_path.py @@ -1,36 +1,30 @@ import os.path +from flask import Flask, request, abort +app = Flask(__name__) -urlpatterns = [ - # Route to user_picture - url(r'^user-pic1$', user_picture1, name='user-picture1'), - url(r'^user-pic2$', user_picture2, name='user-picture2'), - url(r'^user-pic3$', user_picture3, name='user-picture3') -] - - -def user_picture1(request): - """A view that is vulnerable to malicious file access.""" - filename = request.GET.get('p') +@app.route("/user_picture1") +def user_picture1(): + filename = request.args.get('p') # BAD: This could read any file on the file system data = open(filename, 'rb').read() - return HttpResponse(data) + return data -def user_picture2(request): - """A view that is vulnerable to malicious file access.""" +@app.route("/user_picture2") +def user_picture2(): base_path = '/server/static/images' - filename = request.GET.get('p') + filename = request.args.get('p') # BAD: This could still read any file on the file system data = open(os.path.join(base_path, filename), 'rb').read() - return HttpResponse(data) + return data -def user_picture3(request): - """A view that is not vulnerable to malicious file access.""" +@app.route("/user_picture3") +def user_picture3(): base_path = '/server/static/images' - filename = request.GET.get('p') + filename = request.args.get('p') #GOOD -- Verify with normalised version of path fullpath = os.path.normpath(os.path.join(base_path, filename)) if not fullpath.startswith(base_path): - raise SecurityException() + raise Exception("not allowed") data = open(fullpath, 'rb').read() - return HttpResponse(data) + return data diff --git a/python/ql/src/Security/CWE-022/examples/tarslip_bad.py b/python/ql/src/Security/CWE-022/examples/tarslip_bad.py index d0a233e2c4b..d7976e97b5b 100644 --- a/python/ql/src/Security/CWE-022/examples/tarslip_bad.py +++ b/python/ql/src/Security/CWE-022/examples/tarslip_bad.py @@ -1,7 +1,7 @@ - +import sys import tarfile -with tarfile.open('archive.zip') as tar: +with tarfile.open(sys.argv[1]) as tar: #BAD : This could write any file on the filesystem. for entry in tar: tar.extract(entry, "/tmp/unpack/") diff --git a/python/ql/src/Security/CWE-022/examples/tarslip_good.py b/python/ql/src/Security/CWE-022/examples/tarslip_good.py index 59be338d212..0791ab9d3e8 100644 --- a/python/ql/src/Security/CWE-022/examples/tarslip_good.py +++ b/python/ql/src/Security/CWE-022/examples/tarslip_good.py @@ -1,8 +1,8 @@ - +import sys import tarfile import os.path -with tarfile.open('archive.zip') as tar: +with tarfile.open(sys.argv[1]) as tar: for entry in tar: #GOOD: Check that entry is safe if os.path.isabs(entry.name) or ".." in entry.name: diff --git a/python/ql/src/change-notes/released/0.6.3.md b/python/ql/src/change-notes/released/0.6.3.md new file mode 100644 index 00000000000..83374bcef56 --- /dev/null +++ b/python/ql/src/change-notes/released/0.6.3.md @@ -0,0 +1,3 @@ +## 0.6.3 + +No user-facing changes. diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 5501a2a1cc5..b7dafe32c5d 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.6.2 +lastReleaseVersion: 0.6.3 diff --git a/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.qhelp b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.qhelp new file mode 100644 index 00000000000..1219bbe43bc --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.qhelp @@ -0,0 +1,56 @@ + + + + +

Extracting files from a malicious tarball without validating that the destination file path +is within the destination directory using shutil.unpack_archive() can cause files outside the +destination directory to be overwritten, due to the possible presence of directory traversal elements + (..) in archive path names.

+ +

Tarball contain archive entries representing each file in the archive. These entries +include a file path for the entry, but these file paths are not restricted and may contain +unexpected special elements such as the directory traversal element (..). If these +file paths are used to determine an output file to write the contents of the archive item to, then +the file may be written to an unexpected location. This can result in sensitive information being +revealed or deleted, or an attacker being able to influence behavior by modifying unexpected +files.

+ +

For example, if a tarball contains a file entry ../sneaky-file.txt, and the tarball +is extracted to the directory /tmp/tmp123, then naively combining the paths would result +in an output file path of /tmp/tmp123/../sneaky-file.txt, which would cause the file to be +written to /tmp/.

+ +
+ + +

Ensure that output paths constructed from tarball entries are validated +to prevent writing files to unexpected locations.

+ +

Consider using a safer module, such as: zipfile

+ +
+ + +

+In this example an archive is extracted without validating file paths. +

+ + + +

To fix this vulnerability, we need to call the function tarfile.extract() + on each member after verifying that it does not contain either .. or startswith /. +

+ + + +
+ + +
  • + Shutil official documentation + shutil.unpack_archive() warning. +
  • +
    +
    diff --git a/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql new file mode 100644 index 00000000000..a6a0e06559c --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql @@ -0,0 +1,24 @@ +/** + * @name Arbitrary file write during a tarball extraction from a user controlled source + * @description Extracting files from a potentially malicious tarball using `shutil.unpack_archive()` without validating + * that the destination file path is within the destination directory can cause files outside + * the destination directory to be overwritten. More precisely, if the tarball comes from a user controlled + * location either a remote one or cli argument. + * @kind path-problem + * @id py/unsafe-unpacking + * @problem.severity error + * @security-severity 7.5 + * @precision medium + * @tags security + * experimental + * external/cwe/cwe-022 + */ + +import python +import experimental.Security.UnsafeUnpackQuery +import DataFlow::PathGraph + +from UnsafeUnpackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Unsafe extraction from a malicious tarball retrieved from a remote location." diff --git a/python/ql/src/experimental/Security/CWE-022bis/examples/HIT_UnsafeUnpack.py b/python/ql/src/experimental/Security/CWE-022bis/examples/HIT_UnsafeUnpack.py new file mode 100644 index 00000000000..cc0f857f8c0 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-022bis/examples/HIT_UnsafeUnpack.py @@ -0,0 +1,12 @@ +import requests +import shutil + +url = "https://www.someremote.location/tarball.tar.gz" +response = requests.get(url, stream=True) + +tarpath = "/tmp/tmp456/tarball.tar.gz" +with open(tarpath, "wb") as f: + f.write(response.raw.read()) + +untarredpath = "/tmp/tmp123" +shutil.unpack_archive(tarpath, untarredpath) \ No newline at end of file diff --git a/python/ql/src/experimental/Security/CWE-022bis/examples/NoHIT_UnsafeUnpack.py b/python/ql/src/experimental/Security/CWE-022bis/examples/NoHIT_UnsafeUnpack.py new file mode 100644 index 00000000000..426bcd71481 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-022bis/examples/NoHIT_UnsafeUnpack.py @@ -0,0 +1,17 @@ +import requests +import tarfile + +url = "https://www.someremote.location/tarball.tar.gz" +response = requests.get(url, stream=True) + +tarpath = "/tmp/tmp456/tarball.tar.gz" +with open(tarpath, "wb") as f: + f.write(response.raw.read()) + +untarredpath = "/tmp/tmp123" +with tarfile.open(tarpath) as tar: + for member in tar.getmembers(): + if member.name.startswith("/") or ".." in member.name: + raise Exception("Path traversal identified in tarball") + + tar.extract(untarredpath, member) \ No newline at end of file diff --git a/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll new file mode 100644 index 00000000000..ba359ee32f3 --- /dev/null +++ b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll @@ -0,0 +1,213 @@ +/** + * Provides a taint-tracking configuration for detecting "UnsafeUnpacking" vulnerabilities. + */ + +import python +import semmle.python.Concepts +import semmle.python.dataflow.new.internal.DataFlowPublic +import semmle.python.ApiGraphs +import semmle.python.dataflow.new.TaintTracking +import semmle.python.frameworks.Stdlib +import semmle.python.dataflow.new.RemoteFlowSources + +/** + * Handle those three cases of Tarfile opens: + * - `tarfile.open()` + * - `tarfile.TarFile()` + * - `MKtarfile.Tarfile.open()` + */ +API::Node tarfileOpen() { + result in [ + API::moduleImport("tarfile").getMember(["open", "TarFile"]), + API::moduleImport("tarfile").getMember("TarFile").getASubclass().getMember("open") + ] +} + +/** + * A class for handling the previous three cases, plus the use of `closing` in with the previous cases + */ +class AllTarfileOpens extends API::CallNode { + AllTarfileOpens() { + this = tarfileOpen().getACall() + or + exists(API::Node closing, Node arg | + closing = API::moduleImport("contextlib").getMember("closing") and + this = closing.getACall() and + arg = this.getArg(0) and + arg = tarfileOpen().getACall() + ) + } +} + +class UnsafeUnpackingConfig extends TaintTracking::Configuration { + UnsafeUnpackingConfig() { this = "UnsafeUnpackingConfig" } + + override predicate isSource(DataFlow::Node source) { + // A source coming from a remote location + source instanceof RemoteFlowSource + or + // A source coming from a CLI argparse module + // see argparse: https://docs.python.org/3/library/argparse.html + exists(MethodCallNode args | + args = source.(AttrRead).getObject().getALocalSource() and + args = + API::moduleImport("argparse") + .getMember("ArgumentParser") + .getReturn() + .getMember("parse_args") + .getACall() + ) + or + // A source catching an S3 file download + // see boto3: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.download_file + source = + API::moduleImport("boto3") + .getMember("client") + .getReturn() + .getMember(["download_file", "download_fileobj"]) + .getACall() + .getArg(2) + or + // A source catching an S3 file download + // see boto3: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html + source = + API::moduleImport("boto3") + .getMember("Session") + .getReturn() + .getMember("client") + .getReturn() + .getMember(["download_file", "download_fileobj"]) + .getACall() + .getArg(2) + or + // A source download a file using wget + // see wget: https://pypi.org/project/wget/ + exists(API::CallNode mcn | + mcn = API::moduleImport("wget").getMember("download").getACall() and + if exists(mcn.getArg(1)) then source = mcn.getArg(1) else source = mcn.getReturn().asSource() + ) + or + // catch the Django uploaded files as a source + // see HttpRequest.FILES: https://docs.djangoproject.com/en/4.1/ref/request-response/#django.http.HttpRequest.FILES + source.(AttrRead).getAttributeName() = "FILES" + } + + override predicate isSink(DataFlow::Node sink) { + ( + // A sink capturing method calls to `unpack_archive`. + sink = API::moduleImport("shutil").getMember("unpack_archive").getACall().getArg(0) + or + // A sink capturing method calls to `extractall` without `members` argument. + // For a call to `file.extractall` without `members` argument, `file` is considered a sink. + exists(MethodCallNode call, AllTarfileOpens atfo | + call = atfo.getReturn().getMember("extractall").getACall() and + not exists(call.getArgByName("members")) and + sink = call.getObject() + ) + or + // A sink capturing method calls to `extractall` with `members` argument. + // For a call to `file.extractall` with `members` argument, `file` is considered a sink if not + // a the `members` argument contains a NameConstant as None, a List or call to the method `getmembers`. + // Otherwise, the argument of `members` is considered a sink. + exists(MethodCallNode call, Node arg, AllTarfileOpens atfo | + call = atfo.getReturn().getMember("extractall").getACall() and + arg = call.getArgByName("members") and + if + arg.asCfgNode() instanceof NameConstantNode or + arg.asCfgNode() instanceof ListNode + then sink = call.getObject() + else + if arg.(MethodCallNode).getMethodName() = "getmembers" + then sink = arg.(MethodCallNode).getObject() + else sink = call.getArgByName("members") + ) + or + // An argument to `extract` is considered a sink. + exists(AllTarfileOpens atfo | + sink = atfo.getReturn().getMember("extract").getACall().getArg(0) + ) + or + //An argument to `_extract_member` is considered a sink. + exists(MethodCallNode call, AllTarfileOpens atfo | + call = atfo.getReturn().getMember("_extract_member").getACall() and + call.getArg(1).(AttrRead).accesses(sink, "name") + ) + ) and + not sink.getScope().getLocation().getFile().inStdlib() + } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Reading the response + nodeTo.(MethodCallNode).calls(nodeFrom, "read") + or + // Open a file for access + exists(MethodCallNode cn | + cn.calls(nodeTo, "open") and + cn.flowsTo(nodeFrom) + ) + or + // Open a file for access using builtin + exists(API::CallNode cn | + cn = API::builtin("open").getACall() and + nodeTo = cn.getArg(0) and + cn.flowsTo(nodeFrom) + ) + or + // Write access + exists(MethodCallNode cn | + cn.calls(nodeTo, "write") and + nodeFrom = cn.getArg(0) + ) + or + // Retrieve Django uploaded files + // see getlist(): https://docs.djangoproject.com/en/4.1/ref/request-response/#django.http.QueryDict.getlist + // see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks + nodeTo.(MethodCallNode).calls(nodeFrom, ["getlist", "get", "chunks"]) + or + // Considering the use of "fs" + // see fs: https://docs.djangoproject.com/en/4.1/ref/files/storage/#the-filesystemstorage-class + nodeTo = + API::moduleImport("django") + .getMember("core") + .getMember("files") + .getMember("storage") + .getMember("FileSystemStorage") + .getReturn() + .getMember(["save", "path"]) + .getACall() and + nodeFrom = nodeTo.(MethodCallNode).getArg(0) + or + // Accessing the name or raw content + nodeTo.(AttrRead).accesses(nodeFrom, ["name", "raw"]) + or + // Join the base_dir to the filename + nodeTo = API::moduleImport("os").getMember("path").getMember("join").getACall() and + nodeFrom = nodeTo.(API::CallNode).getArg(1) + or + // Go through an Open for a Tarfile + nodeTo = tarfileOpen().getACall() and nodeFrom = nodeTo.(MethodCallNode).getArg(0) + or + // Handle the case where the getmembers is used. + nodeTo.(MethodCallNode).calls(nodeFrom, "getmembers") and + nodeFrom instanceof AllTarfileOpens + or + // To handle the case of `with closing(tarfile.open()) as file:` + // we add a step from the first argument of `closing` to the call to `closing`, + // whenever that first argument is a return of `tarfile.open()`. + nodeTo = API::moduleImport("contextlib").getMember("closing").getACall() and + nodeFrom = nodeTo.(API::CallNode).getArg(0) and + nodeFrom = tarfileOpen().getReturn().getAValueReachableFromSource() + or + // see Path : https://docs.python.org/3/library/pathlib.html#pathlib.Path + nodeTo = API::moduleImport("pathlib").getMember("Path").getACall() and + nodeFrom = nodeTo.(API::CallNode).getArg(0) + or + // Use of absolutepath + // see absolute : https://docs.python.org/3/library/pathlib.html#pathlib.Path.absolute + exists(API::CallNode mcn | + mcn = API::moduleImport("pathlib").getMember("Path").getACall() and + nodeTo = mcn.getAMethodCall("absolute") and + nodeFrom = mcn.getArg(0) + ) + } +} diff --git a/python/ql/src/experimental/semmle/python/security/InsecureRandomnessCustomizations.qll b/python/ql/src/experimental/semmle/python/security/InsecureRandomnessCustomizations.qll index 29230af4634..cc99b286f8a 100644 --- a/python/ql/src/experimental/semmle/python/security/InsecureRandomnessCustomizations.qll +++ b/python/ql/src/experimental/semmle/python/security/InsecureRandomnessCustomizations.qll @@ -59,12 +59,11 @@ module InsecureRandomness { */ class RandomFnSink extends Sink { RandomFnSink() { - exists(DataFlowCallable randomFn | - randomFn - .getName() + exists(Function func | + func.getName() .regexpMatch("(?i).*(gen(erate)?|make|mk|create).*(nonce|salt|pepper|Password).*") | - this.getEnclosingCallable() = randomFn + this.asExpr().getScope() = func ) } } diff --git a/python/ql/src/meta/analysis-quality/CallGraph.ql b/python/ql/src/meta/analysis-quality/CallGraph.ql index 2872912bb51..53114e978b0 100644 --- a/python/ql/src/meta/analysis-quality/CallGraph.ql +++ b/python/ql/src/meta/analysis-quality/CallGraph.ql @@ -1,9 +1,9 @@ /** * @name Call graph - * @description An edge in the points-to call graph. + * @description An edge in the call graph. * @kind problem * @problem.severity recommendation - * @id py/meta/points-to-call-graph + * @id py/meta/call-graph * @tags meta * @precision very-low */ @@ -12,9 +12,9 @@ import python import semmle.python.dataflow.new.internal.DataFlowPrivate import meta.MetaMetrics -from DataFlowCall c, DataFlowCallableValue f +from DataFlowCall call, DataFlowCallable target where - c.getCallable() = f and - not c.getLocation().getFile() instanceof IgnoredFile and - not f.getScope().getLocation().getFile() instanceof IgnoredFile -select c, "Call to $@", f.getScope(), f.toString() + target = viableCallable(call) and + not call.getLocation().getFile() instanceof IgnoredFile and + not target.getScope().getLocation().getFile() instanceof IgnoredFile +select call, "Call to $@", target.getScope(), target.toString() diff --git a/python/ql/src/meta/analysis-quality/CallGraphQuality.qll b/python/ql/src/meta/analysis-quality/CallGraphQuality.qll index 46f384b89ad..b1f29b52cc7 100644 --- a/python/ql/src/meta/analysis-quality/CallGraphQuality.qll +++ b/python/ql/src/meta/analysis-quality/CallGraphQuality.qll @@ -1,16 +1,55 @@ /** * Provides predicates for measuring the quality of the call graph, that is, - * the number of calls that could be resolved to a callee. + * the number of calls that could be resolved to a target. */ import python import meta.MetaMetrics +newtype TTarget = + TFunction(Function func) or + TClass(Class cls) + +class Target extends TTarget { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets the location of this dataflow call. */ + abstract Location getLocation(); + + /** Whether this target is relevant. */ + predicate isRelevant() { exists(this.getLocation().getFile().getRelativePath()) } +} + +class TargetFunction extends Target, TFunction { + Function func; + + TargetFunction() { this = TFunction(func) } + + override string toString() { result = func.toString() } + + override Location getLocation() { result = func.getLocation() } + + Function getFunction() { result = func } +} + +class TargetClass extends Target, TClass { + Class cls; + + TargetClass() { this = TClass(cls) } + + override string toString() { result = cls.toString() } + + override Location getLocation() { result = cls.getLocation() } + + Class getClass() { result = cls } +} + /** * A call that is (possibly) relevant for analysis quality. * See `IgnoredFile` for details on what is excluded. */ -class RelevantCall extends Call { +class RelevantCall extends CallNode { RelevantCall() { not this.getLocation().getFile() instanceof IgnoredFile } } @@ -18,12 +57,16 @@ class RelevantCall extends Call { module PointsToBasedCallGraph { /** A call that can be resolved by points-to. */ class ResolvableCall extends RelevantCall { - Value callee; + Value targetValue; - ResolvableCall() { callee.getACall() = this.getAFlowNode() } + ResolvableCall() { targetValue.getACall() = this } - /** Gets a resolved callee of this call. */ - Value getCallee() { result = callee } + /** Gets a resolved target of this call. */ + Target getTarget() { + result.(TargetFunction).getFunction() = targetValue.(CallableValue).getScope() + or + result.(TargetClass).getClass() = targetValue.(ClassValue).getScope() + } } /** A call that cannot be resolved by points-to. */ @@ -32,34 +75,79 @@ module PointsToBasedCallGraph { } /** - * A call that can be resolved by points-to, where the resolved callee is relevant. - * Relevant callees include: - * - builtins - * - standard library + * A call that can be resolved by points-to, where the resolved target is relevant. + * Relevant targets include: * - source code of the project */ - class ResolvableCallRelevantCallee extends ResolvableCall { - ResolvableCallRelevantCallee() { - callee.isBuiltin() - or - exists(File file | - file = callee.(CallableValue).getScope().getLocation().getFile() - or - file = callee.(ClassValue).getScope().getLocation().getFile() - | - file.inStdlib() - or - // part of the source code of the project - exists(file.getRelativePath()) + class ResolvableCallRelevantTarget extends ResolvableCall { + ResolvableCallRelevantTarget() { + exists(Target target | target = this.getTarget() | + exists(target.getLocation().getFile().getRelativePath()) ) } } /** - * A call that can be resolved by points-to, where the resolved callee is not considered relevant. - * See `ResolvableCallRelevantCallee` for the definition of relevance. + * A call that can be resolved by points-to, where the resolved target is not considered relevant. + * See `ResolvableCallRelevantTarget` for the definition of relevance. */ - class ResolvableCallIrrelevantCallee extends ResolvableCall { - ResolvableCallIrrelevantCallee() { not this instanceof ResolvableCallRelevantCallee } + class ResolvableCallIrrelevantTarget extends ResolvableCall { + ResolvableCallIrrelevantTarget() { not this instanceof ResolvableCallRelevantTarget } + } +} + +/** Provides classes for call-graph resolution by using type-tracking. */ +module TypeTrackingBasedCallGraph { + private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT + + /** A call that can be resolved by type-tracking. */ + class ResolvableCall extends RelevantCall { + ResolvableCall() { + exists(TT::TNormalCall(this, _, _)) + or + TT::resolveClassCall(this, _) + } + + /** Gets a resolved target of this call. */ + Target getTarget() { + exists(TT::DataFlowCall call, TT::CallType ct, Function targetFunc | + call = TT::TNormalCall(this, targetFunc, ct) and + not ct instanceof TT::CallTypeClass and + targetFunc = result.(TargetFunction).getFunction() + ) + or + // a TT::TNormalCall only exists when the call can be resolved to a function. + // Since points-to just says the call goes directly to the class itself, and + // type-tracking based wants to resolve this to the constructor, which might not + // exist. So to do a proper comparison, we don't require the call to be resolve to + // a specific function. + TT::resolveClassCall(this, result.(TargetClass).getClass()) + } + } + + /** A call that cannot be resolved by type-tracking. */ + class UnresolvableCall extends RelevantCall { + UnresolvableCall() { not this instanceof ResolvableCall } + } + + /** + * A call that can be resolved by type-tracking, where the resolved callee is relevant. + * Relevant targets include: + * - source code of the project + */ + class ResolvableCallRelevantTarget extends ResolvableCall { + ResolvableCallRelevantTarget() { + exists(Target target | target = this.getTarget() | + exists(target.getLocation().getFile().getRelativePath()) + ) + } + } + + /** + * A call that can be resolved by type-tracking, where the resolved target is not considered relevant. + * See `ResolvableCallRelevantTarget` for the definition of relevance. + */ + class ResolvableCallIrrelevantTarget extends ResolvableCall { + ResolvableCallIrrelevantTarget() { not this instanceof ResolvableCallRelevantTarget } } } diff --git a/python/ql/src/meta/analysis-quality/PointsToResolvableCallsRelevantTarget.ql b/python/ql/src/meta/analysis-quality/PointsToResolvableCallsRelevantTarget.ql index 0e9c47023c3..580d2d6b8a1 100644 --- a/python/ql/src/meta/analysis-quality/PointsToResolvableCallsRelevantTarget.ql +++ b/python/ql/src/meta/analysis-quality/PointsToResolvableCallsRelevantTarget.ql @@ -11,4 +11,4 @@ import python import CallGraphQuality -select projectRoot(), count(PointsToBasedCallGraph::ResolvableCallRelevantCallee call) +select projectRoot(), count(PointsToBasedCallGraph::ResolvableCallRelevantTarget call) diff --git a/python/ql/src/meta/analysis-quality/TTCallGraph.ql b/python/ql/src/meta/analysis-quality/TTCallGraph.ql new file mode 100644 index 00000000000..d6383a32eb1 --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraph.ql @@ -0,0 +1,17 @@ +/** + * @name New call graph edge from using type-tracking instead of points-to + * @kind problem + * @problem.severity recommendation + * @id py/meta/type-tracking-call-graph + * @tags meta + * @precision very-low + */ + +import python +import CallGraphQuality + +from CallNode call, Target target +where + target.isRelevant() and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target +select call, "$@ to $@", call, "Call", target, target.toString() diff --git a/python/ql/src/meta/analysis-quality/TTCallGraphMissing.ql b/python/ql/src/meta/analysis-quality/TTCallGraphMissing.ql new file mode 100644 index 00000000000..bbf5b3553ef --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraphMissing.ql @@ -0,0 +1,18 @@ +/** + * @name Missing call graph edge from using type-tracking instead of points-to + * @kind problem + * @problem.severity recommendation + * @id py/meta/call-graph-missing + * @tags meta + * @precision very-low + */ + +import python +import CallGraphQuality + +from CallNode call, Target target +where + target.isRelevant() and + call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + not call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target +select call, "MISSING: $@ to $@", call, "Call", target, target.toString() diff --git a/python/ql/src/meta/analysis-quality/TTCallGraphNew.ql b/python/ql/src/meta/analysis-quality/TTCallGraphNew.ql new file mode 100644 index 00000000000..82a830265c6 --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraphNew.ql @@ -0,0 +1,18 @@ +/** + * @name New call graph edge from using type-tracking instead of points-to + * @kind problem + * @problem.severity recommendation + * @id py/meta/call-graph-new + * @tags meta + * @precision very-low + */ + +import python +import CallGraphQuality + +from CallNode call, Target target +where + target.isRelevant() and + not call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target +select call, "NEW: $@ to $@", call, "Call", target, target.toString() diff --git a/python/ql/src/meta/analysis-quality/TTCallGraphNewAmbiguous.ql b/python/ql/src/meta/analysis-quality/TTCallGraphNewAmbiguous.ql new file mode 100644 index 00000000000..dc27dcf262c --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraphNewAmbiguous.ql @@ -0,0 +1,19 @@ +/** + * @name New call graph edge from using type-tracking instead of points-to, that is ambiguous + * @kind problem + * @problem.severity recommendation + * @id py/meta/call-graph-new-ambiguous + * @tags meta + * @precision very-low + */ + +import python +import CallGraphQuality + +from CallNode call, Target target +where + target.isRelevant() and + not call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target and + 1 < count(call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget()) +select call, "NEW: $@ to $@", call, "Call", target, target.toString() diff --git a/python/ql/src/meta/analysis-quality/TTCallGraphOverview.ql b/python/ql/src/meta/analysis-quality/TTCallGraphOverview.ql new file mode 100644 index 00000000000..5a789d1be90 --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraphOverview.ql @@ -0,0 +1,35 @@ +/** + * @name Call graph edge overview from using type-tracking instead of points-to + * @id py/meta/call-graph-overview + * @precision very-low + */ + +import python +import CallGraphQuality + +from string tag, int c +where + tag = "SHARED" and + c = + count(CallNode call, Target target | + target.isRelevant() and + call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target + ) + or + tag = "NEW" and + c = + count(CallNode call, Target target | + target.isRelevant() and + not call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target + ) + or + tag = "MISSING" and + c = + count(CallNode call, Target target | + target.isRelevant() and + call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + not call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target + ) +select tag, c diff --git a/python/ql/src/meta/analysis-quality/TTCallGraphShared.ql b/python/ql/src/meta/analysis-quality/TTCallGraphShared.ql new file mode 100644 index 00000000000..7a3bd794839 --- /dev/null +++ b/python/ql/src/meta/analysis-quality/TTCallGraphShared.ql @@ -0,0 +1,18 @@ +/** + * @name Shared call graph edge from using type-tracking instead of points-to + * @kind problem + * @problem.severity recommendation + * @id py/meta/call-graph-shared + * @tags meta + * @precision very-low + */ + +import python +import CallGraphQuality + +from CallNode call, Target target +where + target.isRelevant() and + call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and + call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target +select call, "SHARED: $@ to $@", call, "Call", target, target.toString() diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 8f91049c479..dc28c02032a 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.6.3-dev +version: 0.6.4-dev groups: - python - queries diff --git a/python/ql/test/2/library-tests/six/pointsto.expected b/python/ql/test/2/library-tests/six/pointsto.expected index 0e0d568caf3..b2ad9ae96f4 100644 --- a/python/ql/test/2/library-tests/six/pointsto.expected +++ b/python/ql/test/2/library-tests/six/pointsto.expected @@ -6,4 +6,4 @@ | six.moves.urllib | Package six.moves.urllib | | six.moves.urllib.parse | Module six.moves.urllib_parse | | six.moves.urllib.parse.urlsplit | Function urlsplit | -| six.moves.zip | builtin-class itertools.izip | +| six.moves.zip | Builtin-function zip | diff --git a/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.expected b/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.expected index 9c06cae162e..32fa7b97bf1 100644 --- a/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.expected +++ b/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.expected @@ -1 +1 @@ -| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf8' codec can't decode byte 0x82 in position 82: invalid start byte | +| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf-8' codec can't decode byte 0x82 in position 82: invalid start byte | diff --git a/python/ql/test/experimental/dataflow/TestUtil/DataFlowConsistency.qll b/python/ql/test/experimental/dataflow/TestUtil/DataFlowConsistency.qll new file mode 100644 index 00000000000..456b18e2a87 --- /dev/null +++ b/python/ql/test/experimental/dataflow/TestUtil/DataFlowConsistency.qll @@ -0,0 +1,47 @@ +import python +import semmle.python.dataflow.new.DataFlow::DataFlow +import semmle.python.dataflow.new.internal.DataFlowPrivate +import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency + +// TODO: this should be promoted to be a REAL consistency query by being placed in +// `python/ql/consistency-queries`. For for now it resides here. +private class MyConsistencyConfiguration extends ConsistencyConfiguration { + override predicate argHasPostUpdateExclude(ArgumentNode n) { + exists(ArgumentPosition apos | n.argumentOf(_, apos) and apos.isStarArgs(_)) + or + exists(ArgumentPosition apos | n.argumentOf(_, apos) and apos.isDictSplat()) + } + + override predicate reverseReadExclude(Node n) { + // since `self`/`cls` parameters can be marked as implicit argument to `super()`, + // they will have PostUpdateNodes. We have a read-step from the synthetic `**kwargs` + // parameter, but dataflow-consistency queries should _not_ complain about there not + // being a post-update node for the synthetic `**kwargs` parameter. + n instanceof SynthDictSplatParameterNode + } + + override predicate uniqueParameterNodeAtPositionExclude( + DataFlowCallable c, ParameterPosition pos, Node p + ) { + // TODO: This can be removed once we solve the overlap of dictionary splat parameters + c.getParameter(pos) = p and + pos.isDictSplat() and + not exists(p.getLocation().getFile().getRelativePath()) + } + + override predicate uniqueParameterNodePositionExclude( + DataFlowCallable c, ParameterPosition pos, Node p + ) { + // For normal parameters that can both be passed as positional arguments or keyword + // arguments, we currently have parameter positions for both cases.. + // + // TODO: Figure out how bad breaking this consistency check is + exists(Function func, Parameter param | + c.getScope() = func and + p = parameterNode(param) and + c.getParameter(pos) = p and + param = func.getArg(_) and + param = func.getArgByName(_) + ) + } +} diff --git a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll index e96922bc25e..36b603baa78 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll @@ -26,29 +26,30 @@ abstract class RoutingTest extends InlineExpectationsTest { element = fromNode.toString() and ( tag = this.flowTag() and - if "\"" + tag + "\"" = this.fromValue(fromNode) - then value = "" - else value = this.fromValue(fromNode) + if "\"" + tag + "\"" = fromValue(fromNode) then value = "" else value = fromValue(fromNode) or + // only have result for `func` tag if the function where `arg` is used, is + // different from the function name of the call where `arg` was specified as + // an argument tag = "func" and - value = this.toFunc(toNode) and - not value = this.fromFunc(fromNode) + value = toFunc(toNode) and + not value = fromFunc(fromNode) ) ) } - - pragma[inline] - private string fromValue(DataFlow::Node fromNode) { - result = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" - } - - pragma[inline] - private string fromFunc(DataFlow::ArgumentNode fromNode) { - result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId() - } - - pragma[inline] - private string toFunc(DataFlow::Node toNode) { - result = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing? - } +} + +pragma[inline] +private string fromValue(DataFlow::Node fromNode) { + result = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" +} + +pragma[inline] +private string fromFunc(DataFlow::ArgumentNode fromNode) { + result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId() +} + +pragma[inline] +private string toFunc(DataFlow::Node toNode) { + result = toNode.getEnclosingCallable().getQualifiedName() } diff --git a/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll b/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll index ea123e9ca45..b84f8e6f165 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll @@ -12,13 +12,10 @@ class UnresolvedCallExpectations extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(location.getFile().getRelativePath()) and exists(CallNode call | - not exists(DataFlowPrivate::DataFlowCall dfc | dfc.getNode() = call | - // For every `CallNode`, there is a `DataFlowCall` in the form of a `NormalCall`. - // It does not really count, as it has some abstract overrides. For instance, it does not - // define `getCallable`, so checking for the existence of this guarantees that we are in a - // properly resolved call. - exists(dfc.getCallable()) + not exists(DataFlowPrivate::DataFlowCall dfc | + exists(dfc.getCallable()) and dfc.getNode() = call ) and + not DataFlowPrivate::resolveClassCall(call, _) and not call = API::builtin(_).getACall().asCfgNode() and location = call.getLocation() and tag = "unresolved_call" and diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected index 01ae02a1ad0..0f87376ef1a 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected @@ -1,3 +1,4 @@ -| file://:0:0:0:0 | parameter 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 0 of builtins.reversed | +| test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:19:1:19 | ControlFlowNode for x | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | diff --git a/python/ql/test/experimental/dataflow/basic/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/basic/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/basic/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/basic/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/basic/global.expected b/python/ql/test/experimental/dataflow/basic/global.expected index 885d61309d4..800312b07be 100644 --- a/python/ql/test/experimental/dataflow/basic/global.expected +++ b/python/ql/test/experimental/dataflow/basic/global.expected @@ -1,4 +1,4 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.expected b/python/ql/test/experimental/dataflow/basic/globalStep.expected index 38611776824..fa5b20486c2 100644 --- a/python/ql/test/experimental/dataflow/basic/globalStep.expected +++ b/python/ql/test/experimental/dataflow/basic/globalStep.expected @@ -1,4 +1,4 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/local.expected b/python/ql/test/experimental/dataflow/basic/local.expected index 33636a8e81d..2354efea8e5 100644 --- a/python/ql/test/experimental/dataflow/basic/local.expected +++ b/python/ql/test/experimental/dataflow/basic/local.expected @@ -1,8 +1,8 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter 0 of builtins.reversed | file://:0:0:0:0 | parameter 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed | | test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b | @@ -10,6 +10,7 @@ | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | +| test.py:1:1:1:21 | SynthDictSplatParameterNode | test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | @@ -52,8 +53,10 @@ | test.py:7:1:7:1 | ControlFlowNode for b | test.py:7:1:7:1 | ControlFlowNode for b | | test.py:7:1:7:1 | GSSA Variable b | test.py:7:1:7:1 | GSSA Variable b | | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | +| test.py:7:5:7:17 | [post] ControlFlowNode for obfuscated_id | test.py:7:5:7:17 | [post] ControlFlowNode for obfuscated_id | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:1:7:1 | GSSA Variable b | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | | test.py:7:5:7:20 | GSSA Variable a | test.py:7:5:7:20 | GSSA Variable a | +| test.py:7:5:7:20 | [pre] ControlFlowNode for obfuscated_id() | test.py:7:5:7:20 | [pre] ControlFlowNode for obfuscated_id() | | test.py:7:19:7:19 | ControlFlowNode for a | test.py:7:19:7:19 | ControlFlowNode for a | -| test.py:7:19:7:19 | [post arg] ControlFlowNode for a | test.py:7:19:7:19 | [post arg] ControlFlowNode for a | +| test.py:7:19:7:19 | [post] ControlFlowNode for a | test.py:7:19:7:19 | [post] ControlFlowNode for a | diff --git a/python/ql/test/experimental/dataflow/basic/localStep.expected b/python/ql/test/experimental/dataflow/basic/localStep.expected index 900e4ac3900..534c31da1a6 100644 --- a/python/ql/test/experimental/dataflow/basic/localStep.expected +++ b/python/ql/test/experimental/dataflow/basic/localStep.expected @@ -1,4 +1,4 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/basic/sinks.expected b/python/ql/test/experimental/dataflow/basic/sinks.expected index 3aa3245c465..aafff76bbe2 100644 --- a/python/ql/test/experimental/dataflow/basic/sinks.expected +++ b/python/ql/test/experimental/dataflow/basic/sinks.expected @@ -1,12 +1,13 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 0 of builtins.reversed | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | | test.py:0:0:0:0 | SSA variable $ | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | +| test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:19:1:19 | ControlFlowNode for x | @@ -24,7 +25,9 @@ | test.py:7:1:7:1 | ControlFlowNode for b | | test.py:7:1:7:1 | GSSA Variable b | | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | +| test.py:7:5:7:17 | [post] ControlFlowNode for obfuscated_id | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | | test.py:7:5:7:20 | GSSA Variable a | +| test.py:7:5:7:20 | [pre] ControlFlowNode for obfuscated_id() | | test.py:7:19:7:19 | ControlFlowNode for a | -| test.py:7:19:7:19 | [post arg] ControlFlowNode for a | +| test.py:7:19:7:19 | [post] ControlFlowNode for a | diff --git a/python/ql/test/experimental/dataflow/basic/sources.expected b/python/ql/test/experimental/dataflow/basic/sources.expected index 3aa3245c465..aafff76bbe2 100644 --- a/python/ql/test/experimental/dataflow/basic/sources.expected +++ b/python/ql/test/experimental/dataflow/basic/sources.expected @@ -1,12 +1,13 @@ -| file://:0:0:0:0 | [summary] read: argument 0.List element in builtins.reversed | +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 0 of builtins.reversed | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | | test.py:0:0:0:0 | SSA variable $ | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | +| test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:19:1:19 | ControlFlowNode for x | @@ -24,7 +25,9 @@ | test.py:7:1:7:1 | ControlFlowNode for b | | test.py:7:1:7:1 | GSSA Variable b | | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | +| test.py:7:5:7:17 | [post] ControlFlowNode for obfuscated_id | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | | test.py:7:5:7:20 | GSSA Variable a | +| test.py:7:5:7:20 | [pre] ControlFlowNode for obfuscated_id() | | test.py:7:19:7:19 | ControlFlowNode for a | -| test.py:7:19:7:19 | [post arg] ControlFlowNode for a | +| test.py:7:19:7:19 | [post] ControlFlowNode for a | diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.expected b/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.expected new file mode 100644 index 00000000000..99c2d987d16 --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.expected @@ -0,0 +1,13 @@ +| test.py:32:8:32:23 | CrosstalkTestX() | test.py:9:5:9:23 | Function __init__ | test.py:32:8:32:23 | [pre] ControlFlowNode for CrosstalkTestX() | self | +| test.py:33:8:33:23 | CrosstalkTestY() | test.py:21:5:21:23 | Function __init__ | test.py:33:8:33:23 | [pre] ControlFlowNode for CrosstalkTestY() | self | +| test.py:43:1:43:8 | func() | test.py:13:5:13:26 | Function setx | test.py:36:12:36:15 | ControlFlowNode for objx | self | +| test.py:43:1:43:8 | func() | test.py:13:5:13:26 | Function setx | test.py:43:6:43:7 | ControlFlowNode for IntegerLiteral | position 0 | +| test.py:43:1:43:8 | func() | test.py:25:5:25:26 | Function sety | test.py:38:12:38:15 | ControlFlowNode for objy | self | +| test.py:43:1:43:8 | func() | test.py:25:5:25:26 | Function sety | test.py:43:6:43:7 | ControlFlowNode for IntegerLiteral | position 0 | +| test.py:51:1:51:8 | func() | test.py:16:5:16:30 | Function setvalue | test.py:47:12:47:15 | ControlFlowNode for objx | self | +| test.py:51:1:51:8 | func() | test.py:16:5:16:30 | Function setvalue | test.py:51:6:51:7 | ControlFlowNode for IntegerLiteral | position 0 | +| test.py:51:1:51:8 | func() | test.py:28:5:28:30 | Function setvalue | test.py:49:12:49:15 | ControlFlowNode for objy | self | +| test.py:51:1:51:8 | func() | test.py:28:5:28:30 | Function setvalue | test.py:51:6:51:7 | ControlFlowNode for IntegerLiteral | position 0 | +| test.py:70:1:70:8 | func() | test.py:58:5:58:33 | Function foo | test.py:63:12:63:12 | ControlFlowNode for a | self | +| test.py:70:1:70:8 | func() | test.py:58:5:58:33 | Function foo | test.py:70:6:70:7 | ControlFlowNode for IntegerLiteral | position 0 | +| test.py:70:1:70:8 | func() | test.py:58:5:58:33 | Function foo | test.py:70:6:70:7 | ControlFlowNode for IntegerLiteral | self | diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.ql b/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.ql new file mode 100644 index 00000000000..28699b1f9a7 --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/Arguments.ql @@ -0,0 +1,9 @@ +private import python +private import semmle.python.dataflow.new.internal.DataFlowPrivate +private import semmle.python.dataflow.new.internal.DataFlowPublic + +from DataFlowCall call, DataFlowCallable callable, ArgumentNode arg, ArgumentPosition apos +where + callable = call.getCallable() and + arg = call.getArgument(apos) +select call, callable, arg, apos diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected new file mode 100644 index 00000000000..410b626ffff --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected @@ -0,0 +1,24 @@ +uniqueEnclosingCallable +uniqueType +uniqueNodeLocation +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +readStepIsLocal +storeStepIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +argHasPostUpdate +postWithInFlow +viableImplInCallContextTooLarge +uniqueParameterNodeAtPosition +uniqueParameterNodePosition +uniqueContentApprox diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.ql new file mode 100644 index 00000000000..3dda6701a83 --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.ql @@ -0,0 +1,2 @@ +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/options b/python/ql/test/experimental/dataflow/callgraph_crosstalk/options new file mode 100644 index 00000000000..efa237f03c4 --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=0 diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/test.py b/python/ql/test/experimental/dataflow/callgraph_crosstalk/test.py new file mode 100644 index 00000000000..1b676d30b89 --- /dev/null +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/test.py @@ -0,0 +1,70 @@ +import random +cond = random.randint(0,1) == 1 + +# ------------------------------------------------------------------------------ +# Calling different bound-methods based on conditional +# ------------------------------------------------------------------------------ + +class CrosstalkTestX: + def __init__(self): + self.x = None + self.y = None + + def setx(self, value): + self.x = value + + def setvalue(self, value): + self.x = value + + +class CrosstalkTestY: + def __init__(self): + self.x = None + self.y = None + + def sety(self ,value): + self.y = value + + def setvalue(self, value): + self.y = value + + +objx = CrosstalkTestX() +objy = CrosstalkTestY() + +if cond: + func = objx.setx +else: + func = objy.sety + +# What we're testing for is whether both objects are passed as self to both methods, +# which is wrong. + +func(42) + + +if cond: + func = objx.setvalue +else: + func = objy.setvalue + +func(43) + +# ------------------------------------------------------------------------------ +# Calling methods in different ways +# ------------------------------------------------------------------------------ + +class A(object): + def foo(self, arg="Default"): + print("A.foo", self, arg) + +a = A() +if cond: + func = a.foo # `44` is passed as arg +else: + func = A.foo # `44` is passed as self + +# What we're testing for is whether a single call ends up having both `a` and `44` is +# passed as self to `A.foo`, which is wrong. + +func(44) diff --git a/python/ql/test/experimental/dataflow/calls/DataFlowCallTest.ql b/python/ql/test/experimental/dataflow/calls/DataFlowCallTest.ql index 4536e8f40ad..d939b3092e4 100644 --- a/python/ql/test/experimental/dataflow/calls/DataFlowCallTest.ql +++ b/python/ql/test/experimental/dataflow/calls/DataFlowCallTest.ql @@ -1,6 +1,6 @@ import python import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.internal.DataFlowPrivate +import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch import TestUtilities.InlineExpectationsTest private import semmle.python.dataflow.new.internal.PrintNode @@ -8,26 +8,29 @@ class DataFlowCallTest extends InlineExpectationsTest { DataFlowCallTest() { this = "DataFlowCallTest" } override string getARelevantTag() { - result in ["call", "qlclass"] + result in ["call", "callType"] or - result = "arg_" + [0 .. 10] + result = "arg[" + any(DataFlowDispatch::ArgumentPosition pos).toString() + "]" } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(location.getFile().getRelativePath()) and - exists(DataFlowCall call | + exists(DataFlowDispatch::DataFlowCall call | location = call.getLocation() and - element = call.toString() + element = call.toString() and + exists(call.getCallable()) | value = prettyExpr(call.getNode().getNode()) and tag = "call" or - value = call.getAQlClass() and - tag = "qlclass" + value = call.(DataFlowDispatch::NormalCall).getCallType().toString() and + tag = "callType" or - exists(int n, DataFlow::Node arg | arg = call.getArg(n) | + exists(DataFlowDispatch::ArgumentPosition pos, DataFlow::Node arg | + arg = call.getArgument(pos) + | value = prettyNodeForInlineTest(arg) and - tag = "arg_" + n + tag = "arg[" + pos + "]" ) ) } diff --git a/python/ql/test/experimental/dataflow/calls/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/calls/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/calls/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/calls/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/calls/new_cls_param.py b/python/ql/test/experimental/dataflow/calls/new_cls_param.py new file mode 100644 index 00000000000..c2ec88acd51 --- /dev/null +++ b/python/ql/test/experimental/dataflow/calls/new_cls_param.py @@ -0,0 +1,16 @@ +# We want to ensure that the __new__ method is considered a classmethod even though it +# doesn't have a decorator. This means that the `cls` parameter should be considered a +# reference to the class (or subclass), and not an instance of the class. We can detect +# this from looking at the arguments passed in the `cls.foo` call. if we see a `self` +# argument, this means it has correct behavior (because we're targeting a classmethod), +# if there is no `self` argument, this means we've only considered `cls` to be a class +# instance, since we don't want to pass that to the `cls` parameter of the classmethod `WithNewImpl.foo`. + +class WithNewImpl(object): + def __new__(cls): + print("WithNewImpl.foo") + cls.foo() # $ call=cls.foo() callType=CallTypeClassMethod arg[self]=cls + + @classmethod + def foo(cls): + print("WithNewImpl.foo") diff --git a/python/ql/test/experimental/dataflow/calls/test.py b/python/ql/test/experimental/dataflow/calls/test.py index 144a6a79fe1..0eb7e262cb4 100644 --- a/python/ql/test/experimental/dataflow/calls/test.py +++ b/python/ql/test/experimental/dataflow/calls/test.py @@ -14,24 +14,69 @@ class MyClass(object): def my_method(self, arg): pass + def other_method(self): + self.my_method(42) # $ arg[self]=self call=self.my_method(..) callType=CallTypeNormalMethod arg[position 0]=42 + self.sm(42) # $ call=self.sm(..) callType=CallTypeStaticMethod arg[position 0]=42 + + @staticmethod + def sm(arg): + pass + + @classmethod + def cm(cls, arg): + pass + + @classmethod + def other_classmethod(cls): + cls.cm(42) # $ call=cls.cm(..) callType=CallTypeClassMethod arg[position 0]=42 arg[self]=cls + cls.sm(42) # $ call=cls.sm(..) callType=CallTypeStaticMethod arg[position 0]=42 + def __getitem__(self, key): pass +func(0) # $ call=func(..) arg[position 0]=0 callType=CallTypePlainFunction -func("foo") # $ call=func(..) qlclass=FunctionCall arg_0="foo" -x = MyClass(1) # $ call=MyClass(..) qlclass=ClassCall arg_0=[pre]MyClass(..) arg_1=1 -x.my_method(2) # $ call=x.my_method(..) qlclass=MethodCall arg_0=x arg_1=2 +x = MyClass(1) # $ call=MyClass(..) arg[self]=[pre]MyClass(..) arg[position 0]=1 callType=CallTypeClass + +x.my_method(2) # $ call=x.my_method(..) arg[self]=x arg[position 0]=2 callType=CallTypeNormalMethod mm = x.my_method -mm(2) # $ call=mm(..) qlclass=MethodCall arg_1=2 MISSING: arg_0=x -x[3] # $ call=x[3] qlclass=SpecialCall arg_0=x arg_1=3 +mm(2) # $ call=mm(..) arg[self]=x arg[position 0]=2 callType=CallTypeNormalMethod +MyClass.my_method(x, 2) # $ call=MyClass.my_method(..) arg[position 0]=2 arg[self]=x callType=CallTypeMethodAsPlainFunction + +x.sm(3) # $ call=x.sm(..) arg[position 0]=3 callType=CallTypeStaticMethod +MyClass.sm(3) # $ call=MyClass.sm(..) arg[position 0]=3 callType=CallTypeStaticMethod + +x.cm(4) # $ call=x.cm(..) arg[position 0]=4 callType=CallTypeClassMethod +MyClass.cm(4) # $ call=MyClass.cm(..) arg[position 0]=4 arg[self]=MyClass callType=CallTypeClassMethod + +x[5] # $ MISSING: call=x[5] arg[self]=x arg[position 0]=5 + + +class Subclass(MyClass): + pass + +y = Subclass(1) # $ call=Subclass(..) arg[self]=[pre]Subclass(..) arg[position 0]=1 callType=CallTypeClass + +y.my_method(2) # $ call=y.my_method(..) arg[self]=y arg[position 0]=2 callType=CallTypeNormalMethod +mm = y.my_method +mm(2) # $ call=mm(..) arg[self]=y arg[position 0]=2 callType=CallTypeNormalMethod +Subclass.my_method(y, 2) # $ call=Subclass.my_method(..) arg[self]=y arg[position 0]=2 callType=CallTypeMethodAsPlainFunction + +y.sm(3) # $ call=y.sm(..) arg[position 0]=3 callType=CallTypeStaticMethod +Subclass.sm(3) # $ call=Subclass.sm(..) arg[position 0]=3 callType=CallTypeStaticMethod + +y.cm(4) # $ call=y.cm(..) arg[position 0]=4 callType=CallTypeClassMethod +Subclass.cm(4) # $ call=Subclass.cm(..) arg[self]=Subclass arg[position 0]=4 callType=CallTypeClassMethod + +y[5] # $ MISSING: call=y[5] arg[self]=y arg[position 0]=5 try: - # These are included to show how we handle absent things with points-to where - # `mypkg.foo` is a `missing module variable`, but `mypkg.subpkg.bar` is compeltely - # ignored. + # These are included to show whether we have a DataFlowCall for things we can't + # resolve. Both are interesting since with points-to we used to have a DataFlowCall + # for _one_ but not the other import mypkg - mypkg.foo(42) # $ call=mypkg.foo(..) qlclass=NormalCall - mypkg.subpkg.bar(43) # $ call=mypkg.subpkg.bar(..) qlclass=LibraryCall arg_0=43 + mypkg.foo(42) + mypkg.subpkg.bar(43) except: pass diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected index 2cbecf5ba66..e69de29bb2d 100644 --- a/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected @@ -1 +0,0 @@ -| test.py:239:27:239:27 | Parameter | There is no `ParameterNode` associated with this parameter. | diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 92b466cd25a..35695b01f03 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -38,6 +38,14 @@ SINK5 = functools.partial(SINK, expected=arg5) SINK6 = functools.partial(SINK, expected=arg6) SINK7 = functools.partial(SINK, expected=arg7) +SINK1_F = functools.partial(SINK_F, unexpected=arg1) +SINK2_F = functools.partial(SINK_F, unexpected=arg2) +SINK3_F = functools.partial(SINK_F, unexpected=arg3) +SINK4_F = functools.partial(SINK_F, unexpected=arg4) +SINK5_F = functools.partial(SINK_F, unexpected=arg5) +SINK6_F = functools.partial(SINK_F, unexpected=arg6) +SINK7_F = functools.partial(SINK_F, unexpected=arg7) + def argument_passing( a, @@ -64,12 +72,12 @@ def argument_passing( @expects(7) def test_argument_passing1(): - argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1 arg7 func=argument_passing MISSING: arg2 arg3="arg3 arg4 arg5 arg6 + argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1 arg5 arg6 arg7 func=argument_passing MISSING: arg2 arg3 arg4 @expects(7) def test_argument_passing2(): - argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1 arg2 arg3 + argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1 arg2 arg3 arg6 def with_pos_only(a, /, b): @@ -94,7 +102,7 @@ def with_multiple_kw_args(a, b, c): def test_multiple_kw_args(): with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1 arg2 arg3 with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1 MISSING: arg2 arg3 - with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg2 arg3 func=with_multiple_kw_args MISSING: + with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg2 arg3 func=with_multiple_kw_args with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1 arg2 arg3 func=with_multiple_kw_args @@ -112,32 +120,6 @@ def test_default_arguments(): with_default_arguments(**{"c": arg3}) #$ arg3 func=with_default_arguments -# Nested constructor pattern -def grab_foo_bar_baz(foo, **kwargs): - SINK1(foo) - grab_bar_baz(**kwargs) - - -# It is not possible to pass `bar` into `kwargs`, -# since `bar` is a valid keyword argument. -def grab_bar_baz(bar, **kwargs): - SINK2(bar) - try: - SINK2_F(kwargs["bar"]) - except: - print("OK") - grab_baz(**kwargs) - - -def grab_baz(baz): - SINK3(baz) - - -@expects(4) -def test_grab(): - grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1 arg2 arg3 func=grab_bar_baz func=grab_baz - - # All combinations def test_pos_pos(): def with_pos(a): @@ -183,7 +165,95 @@ def test_kw_kw(): def test_kw_doublestar(): - def with_doublestar(**a): - SINK1(a["a"]) + def with_doublestar(**kwargs): + SINK1(kwargs["a"]) with_doublestar(a=arg1) #$ arg1 func=test_kw_doublestar.with_doublestar + + +def only_kwargs(**kwargs): + SINK1(kwargs["a"]) + SINK2(kwargs["b"]) + # testing precise content tracking, that content from `a` or `b` does not end up here. + SINK3_F(kwargs["c"]) + +@expects(3) +def test_kwargs(): + args = {"a": arg1, "b": arg2, "c": "safe"} # $ arg1 arg2 func=only_kwargs + only_kwargs(**args) + + +def mixed(a, **kwargs): + SINK1(a) + try: + SINK1_F(kwargs["a"]) # since 'a' is a keyword argument, it cannot be part of **kwargs + except KeyError: + print("OK") + SINK2(kwargs["b"]) + # testing precise content tracking, that content from `a` or `b` does not end up here. + SINK3_F(kwargs["c"]) + +@expects(4*3) +def test_mixed(): + mixed(a=arg1, b=arg2, c="safe") # $ arg1 arg2 + + args = {"b": arg2, "c": "safe"} # $ arg2 func=mixed + mixed(a=arg1, **args) # $ arg1 + + args = {"a": arg1, "b": arg2, "c": "safe"} # $ arg1 arg2 func=mixed + mixed(**args) + + +def starargs_only(*args): + SINK1(args[0]) + SINK2(args[1]) + SINK3_F(args[2]) + +@expects(5*3) +def test_only_starargs(): + starargs_only(arg1, arg2, "safe") # $ arg1 arg2 SPURIOUS: bad2,bad3="arg1" bad1,bad3="arg2" + + args = (arg2, "safe") # $ MISSING: arg2 + starargs_only(arg1, *args) # $ arg1 SPURIOUS: bad2,bad3="arg1" + + args = (arg1, arg2, "safe") # $ arg1 arg2 func=starargs_only + starargs_only(*args) + + empty_args = () + + args = (arg1, arg2, "safe") # $ arg1 arg2 func=starargs_only + starargs_only(*args, *empty_args) + args = (arg1, arg2, "safe") # $ MISSING: arg1 arg2 func=starargs_only + starargs_only(*empty_args, *args) + + +def starargs_mixed(a, *args): + SINK1(a) + SINK2(args[0]) + SINK3_F(args[1]) + +@expects(3*8) +def test_stararg_mixed(): + starargs_mixed(arg1, arg2, "safe") # $ arg1 arg2 SPURIOUS: bad3="arg2" + + args = (arg2, "safe") # $ arg2 func=starargs_mixed + starargs_mixed(arg1, *args) # $ arg1 + + args = (arg1, arg2, "safe") + starargs_mixed(*args) # $ MISSING: arg1 arg2 + + args = (arg1, arg2, "safe") + more_args = ("foo", "bar") + starargs_mixed(*args, *more_args) # $ MISSING: arg1 arg2 + + empty_args = () + + # adding first/last + starargs_mixed(arg1, arg2, "safe", *empty_args) # $ arg1 arg2 SPURIOUS: bad3="arg2" + starargs_mixed(*empty_args, arg1, arg2, "safe") # $ MISSING: arg1 arg2 + + # adding before/after *args + args = (arg2, "safe") # $ arg2 func=starargs_mixed + starargs_mixed(arg1, *args, *empty_args) # $ arg1 + args = (arg2, "safe") + starargs_mixed(arg1, *empty_args, *args) # $ arg1 MISSING: arg2 diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing_bad_flow_test.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing_bad_flow_test.py new file mode 100644 index 00000000000..44451801a9e --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing_bad_flow_test.py @@ -0,0 +1,63 @@ +import sys +import os +import functools + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from testlib import expects + +arg = "source" +arg1 = "source1" +arg2 = "source2" +arg3 = "source3" +arg4 = "source4" +arg5 = "source5" +arg6 = "source6" +arg7 = "source7" + + +def SINK_TEST(x, test): + if test(x): + print("OK") + else: + print("Unexpected flow", x) + + +def SINK(x, expected=arg): + SINK_TEST(x, test=lambda x: x == expected) + + +def SINK_F(x, unexpected=arg): + SINK_TEST(x, test=lambda x: x != unexpected) + + +SINK1 = functools.partial(SINK, expected=arg1) +SINK2 = functools.partial(SINK, expected=arg2) +SINK3 = functools.partial(SINK, expected=arg3) +SINK4 = functools.partial(SINK, expected=arg4) +SINK5 = functools.partial(SINK, expected=arg5) +SINK6 = functools.partial(SINK, expected=arg6) +SINK7 = functools.partial(SINK, expected=arg7) + +SINK1_F = functools.partial(SINK_F, unexpected=arg1) +SINK2_F = functools.partial(SINK_F, unexpected=arg2) +SINK3_F = functools.partial(SINK_F, unexpected=arg3) +SINK4_F = functools.partial(SINK_F, unexpected=arg4) +SINK5_F = functools.partial(SINK_F, unexpected=arg5) +SINK6_F = functools.partial(SINK_F, unexpected=arg6) +SINK7_F = functools.partial(SINK_F, unexpected=arg7) + + +def bad_argument_flow_func(arg): + SINK1_F(arg) + +def bad_argument_flow_func2(arg): + SINK2(arg) + +def test_bad_argument_flow(): + # this is just a test to show that the testing setup works + + # in the first one, we pretend we expected no flow for arg1 + bad_argument_flow_func(arg1) # $ bad1="arg1" + + # in the second one, we pretend we wanted flow for arg2 instead + bad_argument_flow_func2(arg1) # $ bad2="arg1" diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql index 1a58715fc1c..2adbd635090 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql @@ -9,23 +9,64 @@ class Argument1RoutingTest extends RoutingTest { override string flowTag() { result = "arg1" } override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { - exists(Argument1RoutingConfig cfg | cfg.hasFlow(source, sink)) + exists(Argument1ExtraRoutingConfig cfg | cfg.hasFlow(source, sink)) + or + exists(ArgumentRoutingConfig cfg | + cfg.hasFlow(source, sink) and + cfg.isArgSource(source, 1) and + cfg.isGoodSink(sink, 1) + ) } } -/** - * A configuration to check routing of arguments through magic methods. - */ -class Argument1RoutingConfig extends DataFlow::Configuration { - Argument1RoutingConfig() { this = "Argument1RoutingConfig" } +class ArgNumber extends int { + ArgNumber() { this in [1 .. 7] } +} + +class ArgumentRoutingConfig extends DataFlow::Configuration { + ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" } + + predicate isArgSource(DataFlow::Node node, ArgNumber argNumber) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg" + argNumber + } + + override predicate isSource(DataFlow::Node node) { this.isArgSource(node, _) } + + predicate isGoodSink(DataFlow::Node node, ArgNumber argNumber) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK" + argNumber and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + predicate isBadSink(DataFlow::Node node, ArgNumber argNumber) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK" + argNumber + "_F" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + override predicate isSink(DataFlow::Node node) { + this.isGoodSink(node, _) or this.isBadSink(node, _) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } +} + +class Argument1ExtraRoutingConfig extends DataFlow::Configuration { + Argument1ExtraRoutingConfig() { this = "Argument1ExtraRoutingConfig" } override predicate isSource(DataFlow::Node node) { - node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg1" - or - exists(AssignmentDefinition def, DataFlowPrivate::DataFlowCall call | + exists(AssignmentDefinition def, DataFlow::CallCfgNode call | def.getVariable() = node.(DataFlow::EssaNode).getVar() and def.getValue() = call.getNode() and - call.getNode().(CallNode).getFunction().(NameNode).getId().matches("With\\_%") + call.getFunction().asCfgNode().(NameNode).getId().matches("With\\_%") ) and node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%") } @@ -46,57 +87,59 @@ class Argument1RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } } -// for argument 2 and up, we use a generic approach. Change `maxNumArgs` below if we -// need to increase the maximum number of arguments. -private int maxNumArgs() { result = 7 } - class RestArgumentRoutingTest extends RoutingTest { - int argNumber; + ArgNumber argNumber; RestArgumentRoutingTest() { - argNumber in [2 .. maxNumArgs()] and + argNumber > 1 and this = "Argument" + argNumber + "RoutingTest" } override string flowTag() { result = "arg" + argNumber } override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { - exists(RestArgumentRoutingConfig cfg | cfg.getArgNumber() = argNumber | - cfg.hasFlow(source, sink) + exists(ArgumentRoutingConfig cfg | + cfg.hasFlow(source, sink) and + cfg.isArgSource(source, argNumber) and + cfg.isGoodSink(sink, argNumber) ) } } -/** - * A configuration to check routing of arguments through magic methods. - */ -class RestArgumentRoutingConfig extends DataFlow::Configuration { - int argNumber; +/** Bad flow from `arg` to `SINK_F` */ +class BadArgumentRoutingTestSinkF extends RoutingTest { + ArgNumber argNumber; - RestArgumentRoutingConfig() { - argNumber in [2 .. maxNumArgs()] and - this = "Argument" + argNumber + "RoutingConfig" - } + BadArgumentRoutingTestSinkF() { this = "BadArgumentRoutingTestSinkF" + argNumber } - /** Gets the argument number this configuration is for. */ - int getArgNumber() { result = argNumber } + override string flowTag() { result = "bad" + argNumber } - override predicate isSource(DataFlow::Node node) { - node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg" + argNumber - } - - override predicate isSink(DataFlow::Node node) { - exists(CallNode call | - call.getFunction().(NameNode).getId() = "SINK" + argNumber and - node.(DataFlow::CfgNode).getNode() = call.getAnArg() + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(ArgumentRoutingConfig cfg | + cfg.hasFlow(source, sink) and + cfg.isArgSource(source, argNumber) and + cfg.isBadSink(sink, argNumber) + ) + } +} + +/** Bad flow from `arg` to `SINK` or `SINK_F`, where `n != m`. */ +class BadArgumentRoutingTestWrongSink extends RoutingTest { + ArgNumber argNumber; + + BadArgumentRoutingTestWrongSink() { this = "BadArgumentRoutingTestWrongSink" + argNumber } + + override string flowTag() { result = "bad" + argNumber } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(ArgumentRoutingConfig cfg | + cfg.hasFlow(source, sink) and + cfg.isArgSource(source, any(ArgNumber i | not i = argNumber)) and + ( + cfg.isGoodSink(sink, argNumber) + or + cfg.isBadSink(sink, argNumber) + ) ) } - - /** - * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. - * Use-use flow lets the argument to the first call reach the sink inside the second call, - * making it seem like we handle all cases even if we only handle the last one. - * We make the test honest by preventing flow into source nodes. - */ - override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } } diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 3fa717b6ff0..d74a632b7c3 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -506,7 +506,7 @@ class With_call: def test_call(): - with_call = With_call() #$ MISSING: arg1="SSA variable with_call" func=With_call.__call__ + with_call = With_call() #$ arg1="SSA variable with_call" func=With_call.__call__ with_call() @@ -560,9 +560,9 @@ class With_getitem: def test_getitem(): - with_getitem = With_getitem() #$ arg1="SSA variable with_getitem" func=With_getitem.__getitem__ + with_getitem = With_getitem() #$ MISSING: arg1="SSA variable with_getitem" func=With_getitem.__getitem__ arg2 = 0 - with_getitem[arg2] #$ arg2 func=With_getitem.__getitem__ + with_getitem[arg2] #$ MISSING: arg2 func=With_getitem.__getitem__ # object.__setitem__(self, key, value) @@ -575,10 +575,10 @@ class With_setitem: def test_setitem(): - with_setitem = With_setitem() #$ arg1="SSA variable with_setitem" func=With_setitem.__setitem__ + with_setitem = With_setitem() #$ MISSING: arg1="SSA variable with_setitem" func=With_setitem.__setitem__ arg2 = 0 arg3 = "" - with_setitem[arg2] = arg3 #$ arg2 arg3 func=With_setitem.__setitem__ + with_setitem[arg2] = arg3 #$ MISSING: arg2 arg3 func=With_setitem.__setitem__ # object.__delitem__(self, key) @@ -590,9 +590,9 @@ class With_delitem: def test_delitem(): - with_delitem = With_delitem() #$ arg1="SSA variable with_delitem" func=With_delitem.__delitem__ + with_delitem = With_delitem() #$ MISSING: arg1="SSA variable with_delitem" func=With_delitem.__delitem__ arg2 = 0 - del with_delitem[arg2] #$ arg2 func=With_delitem.__delitem__ + del with_delitem[arg2] #$ MISSING: arg2 func=With_delitem.__delitem__ # object.__missing__(self, key) @@ -662,9 +662,9 @@ class With_add: def test_add(): - with_add = With_add() #$ arg1="SSA variable with_add" func=With_add.__add__ + with_add = With_add() #$ MISSING: arg1="SSA variable with_add" func=With_add.__add__ arg2 = with_add - with_add + arg2 #$ arg2 func=With_add.__add__ + with_add + arg2 #$ MISSING: arg2 func=With_add.__add__ # object.__sub__(self, other) @@ -677,9 +677,9 @@ class With_sub: def test_sub(): - with_sub = With_sub() #$ arg1="SSA variable with_sub" func=With_sub.__sub__ + with_sub = With_sub() #$ MISSING: arg1="SSA variable with_sub" func=With_sub.__sub__ arg2 = with_sub - with_sub - arg2 #$ arg2 func=With_sub.__sub__ + with_sub - arg2 #$ MISSING: arg2 func=With_sub.__sub__ # object.__mul__(self, other) @@ -692,9 +692,9 @@ class With_mul: def test_mul(): - with_mul = With_mul() #$ arg1="SSA variable with_mul" func=With_mul.__mul__ + with_mul = With_mul() #$ MISSING: arg1="SSA variable with_mul" func=With_mul.__mul__ arg2 = with_mul - with_mul * arg2 #$ arg2 func=With_mul.__mul__ + with_mul * arg2 #$ MISSING: arg2 func=With_mul.__mul__ # object.__matmul__(self, other) @@ -707,9 +707,9 @@ class With_matmul: def test_matmul(): - with_matmul = With_matmul() #$ arg1="SSA variable with_matmul" func=With_matmul.__matmul__ + with_matmul = With_matmul() #$ MISSING: arg1="SSA variable with_matmul" func=With_matmul.__matmul__ arg2 = with_matmul - with_matmul @ arg2 #$ arg2 func=With_matmul.__matmul__ + with_matmul @ arg2 #$ MISSING: arg2 func=With_matmul.__matmul__ # object.__truediv__(self, other) @@ -722,9 +722,9 @@ class With_truediv: def test_truediv(): - with_truediv = With_truediv() #$ arg1="SSA variable with_truediv" func=With_truediv.__truediv__ + with_truediv = With_truediv() #$ MISSING: arg1="SSA variable with_truediv" func=With_truediv.__truediv__ arg2 = with_truediv - with_truediv / arg2 #$ arg2 func=With_truediv.__truediv__ + with_truediv / arg2 #$ MISSING: arg2 func=With_truediv.__truediv__ # object.__floordiv__(self, other) @@ -737,9 +737,9 @@ class With_floordiv: def test_floordiv(): - with_floordiv = With_floordiv() #$ arg1="SSA variable with_floordiv" func=With_floordiv.__floordiv__ + with_floordiv = With_floordiv() #$ MISSING: arg1="SSA variable with_floordiv" func=With_floordiv.__floordiv__ arg2 = with_floordiv - with_floordiv // arg2 #$ arg2 func=With_floordiv.__floordiv__ + with_floordiv // arg2 #$ MISSING: arg2 func=With_floordiv.__floordiv__ # object.__mod__(self, other) @@ -752,9 +752,9 @@ class With_mod: def test_mod(): - with_mod = With_mod() #$ arg1="SSA variable with_mod" func=With_mod.__mod__ + with_mod = With_mod() #$ MISSING: arg1="SSA variable with_mod" func=With_mod.__mod__ arg2 = with_mod - with_mod % arg2 #$ arg2 func=With_mod.__mod__ + with_mod % arg2 #$ MISSING: arg2 func=With_mod.__mod__ # object.__divmod__(self, other) @@ -788,9 +788,9 @@ def test_pow(): def test_pow_op(): - with_pow = With_pow() #$ arg1="SSA variable with_pow" func=With_pow.__pow__ + with_pow = With_pow() #$ MISSING: arg1="SSA variable with_pow" func=With_pow.__pow__ arg2 = with_pow - with_pow ** arg2 #$ arg2 func=With_pow.__pow__ + with_pow ** arg2 #$ MISSING: arg2 func=With_pow.__pow__ # object.__lshift__(self, other) @@ -803,9 +803,9 @@ class With_lshift: def test_lshift(): - with_lshift = With_lshift() #$ arg1="SSA variable with_lshift" func=With_lshift.__lshift__ + with_lshift = With_lshift() #$ MISSING: arg1="SSA variable with_lshift" func=With_lshift.__lshift__ arg2 = with_lshift - with_lshift << arg2 #$ arg2 func=With_lshift.__lshift__ + with_lshift << arg2 #$ MISSING: arg2 func=With_lshift.__lshift__ # object.__rshift__(self, other) @@ -818,9 +818,9 @@ class With_rshift: def test_rshift(): - with_rshift = With_rshift() #$ arg1="SSA variable with_rshift" func=With_rshift.__rshift__ + with_rshift = With_rshift() #$ MISSING: arg1="SSA variable with_rshift" func=With_rshift.__rshift__ arg2 = with_rshift - with_rshift >> arg2 #$ arg2 func=With_rshift.__rshift__ + with_rshift >> arg2 #$ MISSING: arg2 func=With_rshift.__rshift__ # object.__and__(self, other) @@ -833,9 +833,9 @@ class With_and: def test_and(): - with_and = With_and() #$ arg1="SSA variable with_and" func=With_and.__and__ + with_and = With_and() #$ MISSING: arg1="SSA variable with_and" func=With_and.__and__ arg2 = with_and - with_and & arg2 #$ arg2 func=With_and.__and__ + with_and & arg2 #$ MISSING: arg2 func=With_and.__and__ # object.__xor__(self, other) @@ -848,9 +848,9 @@ class With_xor: def test_xor(): - with_xor = With_xor() #$ arg1="SSA variable with_xor" func=With_xor.__xor__ + with_xor = With_xor() #$ MISSING: arg1="SSA variable with_xor" func=With_xor.__xor__ arg2 = with_xor - with_xor ^ arg2 #$ arg2 func=With_xor.__xor__ + with_xor ^ arg2 #$ MISSING: arg2 func=With_xor.__xor__ # object.__or__(self, other) @@ -863,9 +863,9 @@ class With_or: def test_or(): - with_or = With_or() #$ arg1="SSA variable with_or" func=With_or.__or__ + with_or = With_or() #$ MISSING: arg1="SSA variable with_or" func=With_or.__or__ arg2 = with_or - with_or | arg2 #$ arg2 func=With_or.__or__ + with_or | arg2 #$ MISSING: arg2 func=With_or.__or__ # object.__radd__(self, other) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index 364dbb299d7..370fb32ca99 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -124,6 +124,40 @@ def test_staticmethod_call(): C.staticmethod(arg1, arg2) # $ func=C.staticmethod arg1 arg2 +# subclass +class SC(C): + pass +sc = SC() + +@expects(6) +def test_subclass_method_call(): + func_obj = sc.method.__func__ + + sc.method(arg1, arg2) # $ func=C.method arg1 arg2 + SC.method(sc, arg1, arg2) # $ func=C.method arg1 arg2 + func_obj(sc, arg1, arg2) # $ MISSING: func=C.method arg1 arg2 + + +@expects(6) +def test_subclass_classmethod_call(): + c_func_obj = SC.classmethod.__func__ + + sc.classmethod(arg1, arg2) # $ func=C.classmethod arg1 arg2 + SC.classmethod(arg1, arg2) # $ func=C.classmethod arg1 arg2 + c_func_obj(SC, arg1, arg2) # $ MISSING: func=C.classmethod arg1 arg2 + + +@expects(5) +def test_subclass_staticmethod_call(): + try: + SC.staticmethod.__func__ + except AttributeError: + print("OK") + + sc.staticmethod(arg1, arg2) # $ func=C.staticmethod arg1 arg2 + SC.staticmethod(arg1, arg2) # $ func=C.staticmethod arg1 arg2 + + # Generator functions # A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. def gen(x, count): @@ -198,5 +232,16 @@ class Customized: customized = Customized() SINK(Customized.a) #$ MISSING:flow="SOURCE, l:-8 -> customized.a" SINK_F(Customized.b) -SINK(customized.a) #$ MISSING:flow="SOURCE, l:-10 -> customized.a" +SINK(customized.a) #$ MISSING: flow="SOURCE, l:-10 -> customized.a" SINK(customized.b) #$ flow="SOURCE, l:-7 -> customized.b" + + +class Test2: + + def __init__(self, arg): + self.x = SOURCE + self.y = arg + +t = Test2(SOURCE) +SINK(t.x) # $ flow="SOURCE, l:-4 -> t.x" +SINK(t.y) # $ flow="SOURCE, l:-2 -> t.y" diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.ql b/python/ql/test/experimental/dataflow/coverage/localFlow.ql index 6522dcf5c68..8fcbf74c64f 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.ql +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.ql @@ -4,5 +4,5 @@ import semmle.python.dataflow.new.DataFlow from DataFlow::Node nodeFrom, DataFlow::Node nodeTo where DataFlow::localFlowStep(nodeFrom, nodeTo) and - nodeFrom.getEnclosingCallable().getName().matches("%\\_with\\_local\\_flow") + nodeFrom.getEnclosingCallable().getQualifiedName().matches("%\\_with\\_local\\_flow") select nodeFrom, nodeTo diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index b09b2aa9984..65f915cfd9b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -697,9 +697,16 @@ def test_overflow_iteration(): s = SOURCE iterate_star_args(NONSOURCE, NONSOURCE, SOURCE, s) +@expects(6) def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py + # based on the fact that `test_deep_callgraph_defined_in_module` works the problem + # seems to be that we're defining these functions inside another function and that + # the flow of these function definitions DOESN'T flow into the body of the `f` + # functions (they DO flow into the body of `test_deep_callgraph`, otherwise the + # `f1` call wouldn't work). + def f1(arg): return arg @@ -720,8 +727,51 @@ def test_deep_callgraph(): x = f6(SOURCE) SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" + x = f5(SOURCE) + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" + x = f4(SOURCE) + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" + x = f3(SOURCE) + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" + x = f2(SOURCE) + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" + x = f1(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" +def wat_f1(arg): + return arg + +def wat_f2(arg): + return wat_f1(arg) + +def wat_f3(arg): + return wat_f2(arg) + +def wat_f4(arg): + return wat_f3(arg) + +def wat_f5(arg): + return wat_f4(arg) + +def wat_f6(arg): + return wat_f5(arg) + +@expects(6) +def test_deep_callgraph_defined_in_module(): + x = wat_f6(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + x = wat_f5(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + x = wat_f4(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + x = wat_f3(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + x = wat_f2(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + x = wat_f1(SOURCE) + SINK(x) #$ flow="SOURCE, l:-1 -> x" + @expects(2) def test_dynamic_tuple_creation_1(): tup = tuple() diff --git a/python/ql/test/experimental/dataflow/enclosing-callable/EnclosingCallable.expected b/python/ql/test/experimental/dataflow/enclosing-callable/EnclosingCallable.expected index a1e3de562f5..3bd4cd81d54 100644 --- a/python/ql/test/experimental/dataflow/enclosing-callable/EnclosingCallable.expected +++ b/python/ql/test/experimental/dataflow/enclosing-callable/EnclosingCallable.expected @@ -1,24 +1,24 @@ -| file://:0:0:0:0 | Function generator_func | generator.py:1:20:1:21 | ControlFlowNode for xs | -| file://:0:0:0:0 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 | -| file://:0:0:0:0 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 | -| file://:0:0:0:0 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for ListComp | -| file://:0:0:0:0 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for Yield | -| file://:0:0:0:0 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for x | -| file://:0:0:0:0 | Function generator_func | generator.py:2:19:2:19 | ControlFlowNode for x | -| file://:0:0:0:0 | Function generator_func | generator.py:2:24:2:25 | ControlFlowNode for xs | -| file://:0:0:0:0 | Module class_example | class_example.py:1:1:1:3 | ControlFlowNode for wat | -| file://:0:0:0:0 | Module class_example | class_example.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | -| file://:0:0:0:0 | Module class_example | class_example.py:3:1:3:10 | ControlFlowNode for ClassExpr | -| file://:0:0:0:0 | Module class_example | class_example.py:3:7:3:9 | ControlFlowNode for Wat | -| file://:0:0:0:0 | Module class_example | class_example.py:4:5:4:7 | ControlFlowNode for wat | -| file://:0:0:0:0 | Module class_example | class_example.py:4:11:4:11 | ControlFlowNode for IntegerLiteral | -| file://:0:0:0:0 | Module class_example | class_example.py:5:5:5:9 | ControlFlowNode for print | -| file://:0:0:0:0 | Module class_example | class_example.py:5:5:5:26 | ControlFlowNode for print() | -| file://:0:0:0:0 | Module class_example | class_example.py:5:11:5:20 | ControlFlowNode for Str | -| file://:0:0:0:0 | Module class_example | class_example.py:5:23:5:25 | ControlFlowNode for wat | -| file://:0:0:0:0 | Module class_example | class_example.py:7:1:7:5 | ControlFlowNode for print | -| file://:0:0:0:0 | Module class_example | class_example.py:7:1:7:23 | ControlFlowNode for print() | -| file://:0:0:0:0 | Module class_example | class_example.py:7:7:7:17 | ControlFlowNode for Str | -| file://:0:0:0:0 | Module class_example | class_example.py:7:20:7:22 | ControlFlowNode for wat | -| file://:0:0:0:0 | Module generator | generator.py:1:1:1:23 | ControlFlowNode for FunctionExpr | -| file://:0:0:0:0 | Module generator | generator.py:1:5:1:18 | ControlFlowNode for generator_func | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:1:1:1:3 | ControlFlowNode for wat | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:3:1:3:10 | ControlFlowNode for ClassExpr | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:3:7:3:9 | ControlFlowNode for Wat | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:4:5:4:7 | ControlFlowNode for wat | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:4:11:4:11 | ControlFlowNode for IntegerLiteral | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:5:5:5:9 | ControlFlowNode for print | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:5:5:5:26 | ControlFlowNode for print() | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:5:11:5:20 | ControlFlowNode for Str | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:5:23:5:25 | ControlFlowNode for wat | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:1:7:5 | ControlFlowNode for print | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:1:7:23 | ControlFlowNode for print() | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:7:7:17 | ControlFlowNode for Str | +| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:20:7:22 | ControlFlowNode for wat | +| generator.py:0:0:0:0 | Module generator | generator.py:1:1:1:23 | ControlFlowNode for FunctionExpr | +| generator.py:0:0:0:0 | Module generator | generator.py:1:5:1:18 | ControlFlowNode for generator_func | +| generator.py:1:1:1:23 | Function generator_func | generator.py:1:20:1:21 | ControlFlowNode for xs | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for ListComp | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for Yield | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for x | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:19:2:19 | ControlFlowNode for x | +| generator.py:1:1:1:23 | Function generator_func | generator.py:2:24:2:25 | ControlFlowNode for xs | diff --git a/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/fieldflow/test.py b/python/ql/test/experimental/dataflow/fieldflow/test.py index 100ab6aac70..c090aea2089 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/test.py +++ b/python/ql/test/experimental/dataflow/fieldflow/test.py @@ -84,10 +84,10 @@ def test_indirect_assign_bound_method(): sf = myobj.setFoo sf(SOURCE) - SINK(myobj.foo) # $ MISSING: flow="SOURCE, l:-1 -> myobj.foo" + SINK(myobj.foo) # $ flow="SOURCE, l:-1 -> myobj.foo" sf(NONSOURCE) - SINK_F(myobj.foo) + SINK_F(myobj.foo) # $ SPURIOUS: flow="SOURCE, l:-4 -> myobj.foo" @expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) @@ -167,6 +167,17 @@ def fields_with_local_flow(x): def test_fields(): SINK(fields_with_local_flow(SOURCE)) # $ flow="SOURCE -> fields_with_local_flow(..)" + +def call_with_source(func): + func(SOURCE) + + +def test_bound_method_passed_as_arg(): + myobj = MyObj(NONSOURCE) + call_with_source(myobj.setFoo) + SINK(myobj.foo) # $ MISSING: flow="SOURCE, l:-5 -> foo.x" + + # ------------------------------------------------------------------------------ # Nested Object # ------------------------------------------------------------------------------ @@ -244,6 +255,9 @@ class CrosstalkTestX: def setvalue(self, value): self.x = value + def do_nothing(self, value): + pass + class CrosstalkTestY: def __init__(self): @@ -295,10 +309,10 @@ def test_potential_crosstalk_different_name(cond=True): func(SOURCE) - SINK(objx.x) # $ MISSING: flow="SOURCE, l:-2 -> objx.x" + SINK(objx.x) # $ flow="SOURCE, l:-2 -> objx.x" SINK_F(objx.y) SINK_F(objy.x) - SINK(objy.y, not_present_at_runtime=True) # $ MISSING: flow="SOURCE, l:-5 -> objy.y" + SINK(objy.y, not_present_at_runtime=True) # $ flow="SOURCE, l:-5 -> objy.y" @expects(8) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) @@ -318,10 +332,10 @@ def test_potential_crosstalk_same_name(cond=True): func(SOURCE) - SINK(objx.x) # $ MISSING: flow="SOURCE, l:-2 -> objx.x" + SINK(objx.x) # $ flow="SOURCE, l:-2 -> objx.x" SINK_F(objx.y) SINK_F(objy.x) - SINK(objy.y, not_present_at_runtime=True) # $ MISSING: flow="SOURCE, l:-5 -> objy.y" + SINK(objy.y, not_present_at_runtime=True) # $ flow="SOURCE, l:-5 -> objy.y" @expects(10) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) @@ -350,6 +364,53 @@ def test_potential_crosstalk_same_name_object_reference(cond=True): SINK(obj.y, not_present_at_runtime=True) # $ flow="SOURCE, l:-8 -> obj.y" +@expects(4) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_potential_crosstalk_same_class(cond=True): + objx1 = CrosstalkTestX() + SINK_F(objx1.x) + + objx2 = CrosstalkTestX() + SINK_F(objx2.x) + + if cond: + func = objx1.setvalue + else: + func = objx2.do_nothing + + # We want to ensure that objx2.x does not end up getting tainted, since that would + # be cross-talk between the self arguments are their functions. + func(SOURCE) + + SINK(objx1.x) # $ flow="SOURCE, l:-2 -> objx1.x" + SINK_F(objx2.x) + + +class NewTest(object): + def __new__(cls, arg): + cls.foo = arg + return super().__new__(cls) # $ unresolved_call=super().__new__(..) + +@expects(4) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test__new__(): + # we want to make sure that we DON'T pass the synthetic pre-update node for + # the class instance to __new__, like we do for __init__. + nt = NewTest(SOURCE) + # the __new__ implementation sets the foo attribute on THE CLASS itself. The + # attribute lookup on the class instance will go to the class itself when the + # attribute isn't defined on the class instance, so we will actually see `nt.foo` + # contain the source, but the point of this test is that we should see identical + # behavior between NewTest.foo and nt.foo, which we dont! + # + # Also note that we currently (October 2022) dont' model writes to classes very + # well. + + SINK(NewTest.foo) # $ MISSING: flow="SOURCE, l:-10 -> NewTest.foo" + SINK(nt.foo) # $ MISSING: flow="SOURCE, l:-11 -> nt.foo" + + NewTest.foo = NONSOURCE + SINK_F(NewTest.foo) + SINK_F(nt.foo) + # ------------------------------------------------------------------------------ # Global scope # ------------------------------------------------------------------------------ @@ -400,7 +461,7 @@ SINK(obj2.foo) # $ flow="SOURCE, l:-1 -> obj2.foo" # apparently these if statements below makes a difference :O # but one is not enough -cond = os.urandom(1)[0] > 128 +cond = os.urandom(1)[0] > 128 # $ unresolved_call=os.urandom(..) if cond: pass diff --git a/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/match/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/match/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/match/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/match/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/regression/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/regression/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/regression/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/regression/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md deleted file mode 100644 index 59e9087ee49..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md +++ /dev/null @@ -1,96 +0,0 @@ -While working on the field-flow tests, I encountered some very strange behavior. By moving some tests into a new file, they suddenly started working :O - -This folder contains the artifacts from investigating this problem, so we can recall the facts (but besides that, don't have much value in itself). - -The test files can be found in `src/`, and I have set of a bunch of different tests with different extractor options in the `test-*` folders. - -The core of the problem is that in _some_ configuration of extractor options, after seeing the code below, points-to gives up trying to resolve calls :flushed: - -```py -import os -cond = os.urandom(1)[0] > 128 - -if cond: - pass - -if cond: - pass -``` - -This seems to have been caused by not allowing enough imports to be resolved. There is also some interaction with splitting, since turning that off also removes the problem. - -But allowing our test to see more imports is more representative of what happens when analyzing real code, so that's the better approach :+1: (and going above 3 does not seem to change anything in this case). - -I've thought about whether we can write a query to reliably cases such as this, but I don't see any solutions. However, we can easily try running all our tests with `--max-import-depth=100` and see if anything changes from this. - -# Seeing the solutions work - -Doing `diff -u -r test-1-normal/ test-5-max-import-depth-3/` shows that all the calls we should be able to resolve, are now resolved properly. and critically this line is added: - -```diff -+| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | -``` - -
    -full diff - -```diff -diff '--color=auto' -u -r test-1-normal/NormalDataflowTest.expected test-5-max-import-depth-3/NormalDataflowTest.expected ---- test-1-normal/NormalDataflowTest.expected 2022-02-27 10:33:00.603882599 +0100 -+++ test-5-max-import-depth-3/NormalDataflowTest.expected 2022-02-28 10:10:08.930743800 +0100 -@@ -1,2 +1,3 @@ - missingAnnotationOnSink - failures -+| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | -diff '--color=auto' -u -r test-1-normal/options test-5-max-import-depth-3/options ---- test-1-normal/options 2022-02-27 10:36:51.124793909 +0100 -+++ test-5-max-import-depth-3/options 2022-02-27 11:01:43.908098372 +0100 -@@ -1 +1 @@ --semmle-extractor-options: --max-import-depth=1 -R ../src -+semmle-extractor-options: --max-import-depth=3 -R ../src -diff '--color=auto' -u -r test-1-normal/UnresolvedCalls.expected test-5-max-import-depth-3/UnresolvedCalls.expected ---- test-1-normal/UnresolvedCalls.expected 2022-02-28 10:09:19.213742437 +0100 -+++ test-5-max-import-depth-3/UnresolvedCalls.expected 2022-02-28 10:10:08.638737921 +0100 -@@ -0,0 +1,5 @@ -+| ../src/isfile_no_problem.py:34:33:34:70 | Comment # $ unresolved_call=os.path.isfile(..) | Missing result:unresolved_call=os.path.isfile(..) | -+| ../src/urandom_no_if_no_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -+| ../src/urandom_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -+| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -+| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | -diff '--color=auto' -u -r test-1-normal/UnresolvedPointsToCalls.expected test-5-max-import-depth-3/UnresolvedPointsToCalls.expected ---- test-1-normal/UnresolvedPointsToCalls.expected 2022-02-28 10:09:19.033738812 +0100 -+++ test-5-max-import-depth-3/UnresolvedPointsToCalls.expected 2022-02-28 10:12:48.572752108 +0100 -@@ -1,5 +1 @@ --| ../src/urandom_no_if_no_problem.py:34:8:34:20 | ../src/urandom_no_if_no_problem.py:34 | os.urandom(..) | - | ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | --| ../src/urandom_problem.py:34:8:34:20 | ../src/urandom_problem.py:34 | os.urandom(..) | --| ../src/urandom_problem.py:42:7:42:16 | ../src/urandom_problem.py:42 | give_src() | --| ../src/urandom_problem.py:43:1:43:9 | ../src/urandom_problem.py:43 | SINK(..) | -``` - -
    - -There are no benefit in increasing import depth above 3 for this test-example: - -```diff -$ diff -u -r test-4-max-import-depth-100/ test-5-max-import-depth-3/ ---- test-4-max-import-depth-100/options 2022-02-28 10:02:09.269071781 +0100 -+++ test-5-max-import-depth-3/options 2022-02-27 11:01:43.908098372 +0100 -@@ -1 +1 @@ --semmle-extractor-options: --max-import-depth=100 -R ../src -+semmle-extractor-options: --max-import-depth=3 -R ../src -``` - -Also notice that using import depth 2 actually makes things worse, as we no longer handle the `isfile_no_problem.py` file properly :facepalm: :sweat_smile: NOTE: This was only for Python 3, for Python 2 there was no change :flushed: - -```diff -diff '--color=auto' -u -r test-4-max-import-depth-100/NormalDataflowTest.expected test-6-max-import-depth-2/NormalDataflowTest.expected ---- test-4-max-import-depth-100/NormalDataflowTest.expected 2022-02-28 10:10:02.206608379 +0100 -+++ test-6-max-import-depth-2/NormalDataflowTest.expected 2022-02-28 10:10:13.882716665 +0100 -@@ -1,3 +1,5 @@ - missingAnnotationOnSink -+| ../src/isfile_no_problem.py:43:6:43:8 | ../src/isfile_no_problem.py:43 | ERROR, you should add `# $ MISSING: flow` annotation | foo | - failures -+| ../src/isfile_no_problem.py:43:11:43:41 | Comment # $ flow="SOURCE, l:-15 -> foo" | Missing result:flow="SOURCE, l:-15 -> foo" | - | ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | -``` diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/eval_no_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/eval_no_problem.py deleted file mode 100644 index f64100c667b..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/eval_no_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -import os -cond = eval("False") - -if cond: - pass - -if cond: - pass - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/isfile_no_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/isfile_no_problem.py deleted file mode 100644 index 895763b7a88..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/isfile_no_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -import os -cond = os.path.isfile(__file__) # $ unresolved_call=os.path.isfile(..) - -if cond: - pass - -if cond: - pass - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/simple_no_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/simple_no_problem.py deleted file mode 100644 index 447d0258349..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/simple_no_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -import os -cond = 1 + 1 == 2 - -if cond: - pass - -if cond: - pass - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_if_no_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_if_no_problem.py deleted file mode 100644 index 5a2c71b1e47..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_if_no_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -import os -cond = os.urandom(1)[0] > 128 # $ unresolved_call=os.urandom(..) - -# if cond: -# pass -# -# if cond: -# pass - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_import_no_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_import_no_problem.py deleted file mode 100644 index 487170078ab..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_no_import_no_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -# import os -cond = os.urandom(1)[0] > 128 # $ unresolved_call=os.urandom(..) - -# if cond: -# pass -# -# if cond: -# pass - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_problem.py b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_problem.py deleted file mode 100644 index d4a06529cf6..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/src/urandom_problem.py +++ /dev/null @@ -1,43 +0,0 @@ -# These are defined so that we can evaluate the test code. -NONSOURCE = "not a source" -SOURCE = "source" - - -def is_source(x): - return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j - - -def SINK(x): - if is_source(x): - print("OK") - else: - print("Unexpected flow", x) - - -def SINK_F(x): - if is_source(x): - print("Unexpected flow", x) - else: - print("OK") - -# ------------------------------------------------------------------------------ -# Actual tests -# ------------------------------------------------------------------------------ - -def give_src(): - return SOURCE - -foo = give_src() -SINK(foo) # $ flow="SOURCE, l:-3 -> foo" - -import os -cond = os.urandom(1)[0] > 128 # $ unresolved_call=os.urandom(..) - -if cond: - pass - -if cond: - pass - -foo = give_src() # $ unresolved_call=give_src() -SINK(foo) # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.expected deleted file mode 100644 index 6d281f5f299..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | has splitting | -| ../src/isfile_no_problem.py | has splitting | -| ../src/simple_no_problem.py | has splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | has splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.expected deleted file mode 100644 index 5c3279e5b65..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1,5 +0,0 @@ -| ../src/urandom_no_if_no_problem.py:34:8:34:20 | ../src/urandom_no_if_no_problem.py:34 | os.urandom(..) | -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | -| ../src/urandom_problem.py:34:8:34:20 | ../src/urandom_problem.py:34 | os.urandom(..) | -| ../src/urandom_problem.py:42:7:42:16 | ../src/urandom_problem.py:42 | give_src() | -| ../src/urandom_problem.py:43:1:43:9 | ../src/urandom_problem.py:43 | SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/options deleted file mode 100644 index 2b7a8c5c0dd..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=1 -R ../src diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected deleted file mode 100644 index ceeb0ef30e0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected +++ /dev/null @@ -1,3 +0,0 @@ -missingAnnotationOnSink -failures -| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.ql deleted file mode 100644 index 3ee344d0b87..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.expected deleted file mode 100644 index 1669504bb58..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | does not have splitting | -| ../src/isfile_no_problem.py | does not have splitting | -| ../src/simple_no_problem.py | does not have splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | does not have splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.expected deleted file mode 100644 index 8078da5b640..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.expected +++ /dev/null @@ -1,2 +0,0 @@ -| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.expected deleted file mode 100644 index f145962da0d..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1,3 +0,0 @@ -| ../src/urandom_no_if_no_problem.py:34:8:34:20 | ../src/urandom_no_if_no_problem.py:34 | os.urandom(..) | -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | -| ../src/urandom_problem.py:34:8:34:20 | ../src/urandom_problem.py:34 | os.urandom(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/options deleted file mode 100644 index acbba69f1d5..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --dont-split-graph --max-import-depth=1 -R ../src diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected deleted file mode 100644 index ceeb0ef30e0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected +++ /dev/null @@ -1,3 +0,0 @@ -missingAnnotationOnSink -failures -| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.ql deleted file mode 100644 index 3ee344d0b87..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.expected deleted file mode 100644 index 6d281f5f299..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | has splitting | -| ../src/isfile_no_problem.py | has splitting | -| ../src/simple_no_problem.py | has splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | has splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.expected deleted file mode 100644 index 8078da5b640..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.expected +++ /dev/null @@ -1,2 +0,0 @@ -| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.expected deleted file mode 100644 index b9a1652ce68..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1,2 +0,0 @@ -| ../src/isfile_no_problem.py:34:8:34:31 | ../src/isfile_no_problem.py:34 | os.path.isfile(..) | -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/options deleted file mode 100644 index 762f1f95d9a..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=0 -R ../src diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected deleted file mode 100644 index ceeb0ef30e0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected +++ /dev/null @@ -1,3 +0,0 @@ -missingAnnotationOnSink -failures -| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.ql deleted file mode 100644 index 3ee344d0b87..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.expected deleted file mode 100644 index 6d281f5f299..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | has splitting | -| ../src/isfile_no_problem.py | has splitting | -| ../src/simple_no_problem.py | has splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | has splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.expected deleted file mode 100644 index d215a40ab29..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.expected +++ /dev/null @@ -1,5 +0,0 @@ -| ../src/isfile_no_problem.py:34:33:34:70 | Comment # $ unresolved_call=os.path.isfile(..) | Missing result:unresolved_call=os.path.isfile(..) | -| ../src/urandom_no_if_no_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.expected deleted file mode 100644 index ce3d7597c36..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1 +0,0 @@ -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/options deleted file mode 100644 index 82f44bce3c0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=100 -R ../src diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected deleted file mode 100644 index ceeb0ef30e0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected +++ /dev/null @@ -1,3 +0,0 @@ -missingAnnotationOnSink -failures -| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.ql deleted file mode 100644 index 3ee344d0b87..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.expected deleted file mode 100644 index 6d281f5f299..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | has splitting | -| ../src/isfile_no_problem.py | has splitting | -| ../src/simple_no_problem.py | has splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | has splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.expected deleted file mode 100644 index d215a40ab29..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.expected +++ /dev/null @@ -1,5 +0,0 @@ -| ../src/isfile_no_problem.py:34:33:34:70 | Comment # $ unresolved_call=os.path.isfile(..) | Missing result:unresolved_call=os.path.isfile(..) | -| ../src/urandom_no_if_no_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.expected deleted file mode 100644 index ce3d7597c36..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1 +0,0 @@ -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/options deleted file mode 100644 index fd080c5b1e1..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=3 -R ../src diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected deleted file mode 100644 index 7b5784017f3..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected +++ /dev/null @@ -1,5 +0,0 @@ -missingAnnotationOnSink -| ../src/isfile_no_problem.py:43:6:43:8 | ../src/isfile_no_problem.py:43 | ERROR, you should add `# $ MISSING: flow` annotation | foo | -failures -| ../src/isfile_no_problem.py:43:11:43:41 | Comment # $ flow="SOURCE, l:-15 -> foo" | Missing result:flow="SOURCE, l:-15 -> foo" | -| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.ql deleted file mode 100644 index 3ee344d0b87..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.NormalDataflowTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.expected deleted file mode 100644 index 6d281f5f299..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/eval_no_problem.py | has splitting | -| ../src/isfile_no_problem.py | has splitting | -| ../src/simple_no_problem.py | has splitting | -| ../src/urandom_no_if_no_problem.py | does not have splitting | -| ../src/urandom_no_import_no_problem.py | does not have splitting | -| ../src/urandom_problem.py | has splitting | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.ql deleted file mode 100644 index ce4cba33871..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/Splitting.ql +++ /dev/null @@ -1,16 +0,0 @@ -import python - -// this can be quick-eval to see which ones have splitting. But that's basically just -// anything from line 39 and further. -predicate exprWithSplitting(Expr e) { - exists(e.getLocation().getFile().getRelativePath()) and - 1 < count(ControlFlowNode cfn | cfn.getNode() = e) -} - -from File f, string msg -where - exists(f.getRelativePath()) and - if exists(Expr e | e.getLocation().getFile() = f and exprWithSplitting(e)) - then msg = "has splitting" - else msg = "does not have splitting" -select f.toString(), msg diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.expected deleted file mode 100644 index 7a80091654c..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.expected +++ /dev/null @@ -1,6 +0,0 @@ -| ../src/isfile_no_problem.py:42:7:42:16 | ControlFlowNode for give_src() | Unexpected result: unresolved_call=give_src() | -| ../src/isfile_no_problem.py:43:1:43:9 | ControlFlowNode for SINK() | Unexpected result: unresolved_call=SINK(..) | -| ../src/urandom_no_if_no_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:34:31:34:64 | Comment # $ unresolved_call=os.urandom(..) | Missing result:unresolved_call=os.urandom(..) | -| ../src/urandom_problem.py:42:18:42:47 | Comment # $ unresolved_call=give_src() | Missing result:unresolved_call=give_src() | -| ../src/urandom_problem.py:43:11:43:75 | Comment # $ unresolved_call=SINK(..) MISSING: flow="SOURCE, l:-15 -> foo" | Missing result:unresolved_call=SINK(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.ql deleted file mode 100644 index c31dc161620..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedCalls.ql +++ /dev/null @@ -1,2 +0,0 @@ -import python -import experimental.dataflow.TestUtil.UnresolvedCalls diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.expected deleted file mode 100644 index c8ec76401e0..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.expected +++ /dev/null @@ -1,4 +0,0 @@ -| ../src/isfile_no_problem.py:34:8:34:31 | ../src/isfile_no_problem.py:34 | os.path.isfile(..) | -| ../src/isfile_no_problem.py:42:7:42:16 | ../src/isfile_no_problem.py:42 | give_src() | -| ../src/isfile_no_problem.py:43:1:43:9 | ../src/isfile_no_problem.py:43 | SINK(..) | -| ../src/urandom_no_import_no_problem.py:34:8:34:20 | ../src/urandom_no_import_no_problem.py:34 | os.urandom(..) | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.ql b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.ql deleted file mode 100644 index 212b840decc..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/UnresolvedPointsToCalls.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python -private import semmle.python.dataflow.new.internal.PrintNode - -from CallNode call -where - exists(call.getLocation().getFile().getRelativePath()) and - not exists(Value value | call = value.getACall()) and - // somehow print is not resolved, but that is not the focus right now - not call.getFunction().(NameNode).getId() = "print" -select call.getLocation(), prettyExpr(call.getNode()) diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/options b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/options deleted file mode 100644 index d902599b806..00000000000 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --lang=3 --max-import-depth=2 -R ../src diff --git a/python/ql/test/experimental/dataflow/summaries/summaries.expected b/python/ql/test/experimental/dataflow/summaries/summaries.expected index 2d1190eb69c..b566cbdedc6 100644 --- a/python/ql/test/experimental/dataflow/summaries/summaries.expected +++ b/python/ql/test/experimental/dataflow/summaries/summaries.expected @@ -3,8 +3,12 @@ edges | summaries.py:32:20:32:25 | ControlFlowNode for SOURCE | summaries.py:32:11:32:26 | ControlFlowNode for identity() | | summaries.py:36:18:36:54 | ControlFlowNode for apply_lambda() | summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | | summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | summaries.py:36:18:36:54 | ControlFlowNode for apply_lambda() | +| summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | | summaries.py:44:25:44:32 | ControlFlowNode for List | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | +| summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | | summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List | +| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | +| summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | | summaries.py:51:18:51:46 | ControlFlowNode for list_map() [List element] | summaries.py:52:6:52:19 | ControlFlowNode for tainted_mapped [List element] | | summaries.py:51:38:51:45 | ControlFlowNode for List [List element] | summaries.py:51:18:51:46 | ControlFlowNode for list_map() [List element] | | summaries.py:51:39:51:44 | ControlFlowNode for SOURCE | summaries.py:51:38:51:45 | ControlFlowNode for List [List element] | @@ -31,8 +35,11 @@ nodes | summaries.py:36:18:36:54 | ControlFlowNode for apply_lambda() | semmle.label | ControlFlowNode for apply_lambda() | | summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | semmle.label | ControlFlowNode for tainted_lambda | +| summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | semmle.label | ControlFlowNode for reversed() [List element] | | summaries.py:44:25:44:32 | ControlFlowNode for List | semmle.label | ControlFlowNode for List | +| summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | semmle.label | ControlFlowNode for tainted_list [List element] | | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | summaries.py:51:18:51:46 | ControlFlowNode for list_map() [List element] | semmle.label | ControlFlowNode for list_map() [List element] | | summaries.py:51:38:51:45 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected index 3b3f18c5b9e..05b64297f71 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected @@ -1,3 +1,4 @@ +| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | test.py:3:1:3:7 | GSSA Variable tainted | test.py:4:6:4:12 | ControlFlowNode for tainted | | test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:3:1:3:7 | GSSA Variable tainted | | test.py:6:1:6:11 | ControlFlowNode for FunctionExpr | test.py:6:5:6:8 | GSSA Variable func | diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.expected b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.expected new file mode 100644 index 00000000000..79d760d87f4 --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.expected @@ -0,0 +1,3 @@ +argumentToEnsureNotTaintedNotMarkedAsSpurious +untaintedArgumentToEnsureTaintedNotMarkedAsMissing +failures diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.ql b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.ql new file mode 100644 index 00000000000..027ad8667be --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/InlineTaintTest.ql @@ -0,0 +1 @@ +import experimental.meta.InlineTaintTest diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/NormalDataflowTest.expected similarity index 100% rename from python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected rename to python/ql/test/experimental/dataflow/tainttracking/generator-flow/NormalDataflowTest.expected diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.ql b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/NormalDataflowTest.ql similarity index 100% rename from python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.ql rename to python/ql/test/experimental/dataflow/tainttracking/generator-flow/NormalDataflowTest.ql diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected new file mode 100644 index 00000000000..410b626ffff --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected @@ -0,0 +1,24 @@ +uniqueEnclosingCallable +uniqueType +uniqueNodeLocation +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +readStepIsLocal +storeStepIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +argHasPostUpdate +postWithInFlow +viableImplInCallContextTooLarge +uniqueParameterNodeAtPosition +uniqueParameterNodePosition +uniqueContentApprox diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.ql new file mode 100644 index 00000000000..3dda6701a83 --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.ql @@ -0,0 +1,2 @@ +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_dataflow.py b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_dataflow.py new file mode 100644 index 00000000000..d1becb7bbba --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_dataflow.py @@ -0,0 +1,34 @@ +def normal_helper(arg): + l = [arg] + return l[0] + + +def generator_helper(arg): + l = [arg] + l = [x for x in l] + return l[0] + + +def generator_helper_wo_source_use(arg): + l = [arg] + l = [x for x in l] + return l[0] + + +def test_source(): + x = normal_helper(SOURCE) + SINK(x) # $ flow="SOURCE, l:-1 -> x" + + x = generator_helper(SOURCE) + SINK(x) # $ flow="SOURCE, l:-1 -> x" + + +def test_non_source(): + x = normal_helper(NONSOURCE) + SINK_F(x) + + x = generator_helper(NONSOURCE) + SINK_F(x) + + x = generator_helper_wo_source_use(NONSOURCE) + SINK_F(x) diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_taint.py b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_taint.py new file mode 100644 index 00000000000..4ec13583dcc --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/test_taint.py @@ -0,0 +1,37 @@ +def normal_helper(arg): + l = [arg] + return l[0] + +# we had a regression where flow from a source to the argument of this function would +# cause _all_ returns from this function to be treated as tainted. That is, the +# `generator_helper(NONSOURCE)` call in `test_non_source` would result in taint :| This +# is specific to taint-tracking, and does NOT appear in pure data-flow (see the +# test_dataflow file) +def generator_helper(arg): + l = [arg] + l = [x for x in l] + return l[0] + + +def generator_helper_wo_source_use(arg): + l = [arg] + l = [x for x in l] + return l[0] + +def test_source(): + x = normal_helper(TAINTED_STRING) + ensure_tainted(x) # $ tainted + + x = generator_helper(TAINTED_STRING) + ensure_tainted(x) # $ tainted + + +def test_non_source(): + x = normal_helper(NONSOURCE) + ensure_not_tainted(x) + + x = generator_helper(NONSOURCE) + ensure_not_tainted(x) + + x = generator_helper_wo_source_use(NONSOURCE) + ensure_not_tainted(x) diff --git a/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index 5277450c151..8de0a3ded92 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -91,7 +91,7 @@ def unrelated_func(): return "foo" def use_funcs_with_decorators(): - x = get_tracked2() # $ MISSING: tracked + x = get_tracked2() # $ tracked y = unrelated_func() # ------------------------------------------------------------------------------ @@ -117,11 +117,11 @@ class Foo(object): def meth1(self): do_stuff(self) - def meth2(self): # $ MISSING: tracked_self - do_stuff(self) # $ MISSING: tracked_self + def meth2(self): # $ tracked_self + do_stuff(self) # $ tracked_self - def meth3(self): # $ MISSING: tracked_self - do_stuff(self) # $ MISSING: tracked_self + def meth3(self): # $ tracked_self + do_stuff(self) # $ tracked_self class Bar(Foo): diff --git a/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.ql b/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.ql +++ b/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/import-resolution/if_then_else.py b/python/ql/test/experimental/import-resolution/if_then_else.py new file mode 100644 index 00000000000..147033089c0 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/if_then_else.py @@ -0,0 +1,16 @@ +from trace import * +enter(__file__) + +# definition based on "random" choice in this case it will always go the the if-branch, +# but our analysis is not able to figure this out +if eval("True"): + if_then_else_defined = "if_defined" +else: + # we also check that nested if-then-else works, it would be easy to accidentally + # only support _one_ level of nesting. + if eval("True"): + if_then_else_defined = "else_defined_1" + else: + if_then_else_defined = "else_defined_2" + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/main.py b/python/ql/test/experimental/import-resolution/main.py index 45c84559fb6..840da95a03c 100644 --- a/python/ql/test/experimental/import-resolution/main.py +++ b/python/ql/test/experimental/import-resolution/main.py @@ -84,6 +84,15 @@ from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_cla check("clashing_attr", clashing_attr, "clashing_attr", globals()) #$ prints=clashing_attr SPURIOUS: prints="" check("non_clashing_submodule", non_clashing_submodule, "", globals()) #$ prints="" + +# check that import * from an __init__ file works +from package.subpackage2 import * +check("subpackage2_attr", subpackage2_attr, "subpackage2_attr", globals()) #$ prints=subpackage2_attr + +# check that definitions from within if-then-else are found +from if_then_else import if_then_else_defined +check("if_then_else_defined", if_then_else_defined, "if_defined", globals()) #$ prints=if_defined prints=else_defined_1 prints=else_defined_2 + exit(__file__) print() @@ -91,4 +100,4 @@ print() if status() == 0: print("PASS") else: - print("FAIL") + sys.exit("FAIL") diff --git a/python/ql/test/experimental/import-resolution/package/subpackage2/__init__.py b/python/ql/test/experimental/import-resolution/package/subpackage2/__init__.py new file mode 100644 index 00000000000..8f0b8fe857f --- /dev/null +++ b/python/ql/test/experimental/import-resolution/package/subpackage2/__init__.py @@ -0,0 +1,6 @@ +from trace import * +enter(__file__) + +subpackage2_attr = "subpackage2_attr" + +exit(__file__) diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.expected index c847f9a8aa2..d5ed453c51a 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.expected @@ -1,5 +1,4 @@ failures debug_callableNotUnique pointsTo_found_typeTracker_notFound -| example.py:22:1:22:16 | ControlFlowNode for explicit_afunc() | explicit_afunc | typeTracker_found_pointsTo_notFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py index 75ad8a9db11..f14669948bc 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py @@ -19,4 +19,4 @@ from foo_explicit.bar.a import explicit_afunc afunc() # $ MISSING: pt,tt=afunc -explicit_afunc() # $ pt=explicit_afunc MISSING: tt=explicit_afunc +explicit_afunc() # $ pt,tt="foo_explicit/bar/a.py:explicit_afunc" diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.expected b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.expected new file mode 100644 index 00000000000..d5ed453c51a --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.expected @@ -0,0 +1,4 @@ +failures +debug_callableNotUnique +pointsTo_found_typeTracker_notFound +typeTracker_found_pointsTo_notFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref new file mode 100644 index 00000000000..25117a4582b --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref @@ -0,0 +1 @@ +../CallGraph/InlineCallGraphTest.ql diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/README.md b/python/ql/test/experimental/library-tests/CallGraph-imports/README.md new file mode 100644 index 00000000000..4063a2851f9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/README.md @@ -0,0 +1,5 @@ +A testcase observed in real code, where mixing `from .this import that` with `from .other import *` (in that order) causes import resolution to not work properly. + +This needs to be in a separate folder, since using relative imports requires a valid top-level package. We emulate real extractor behavior using `-R` extractor option. + +From this directory, you can run the code with `python -m pkg.use`. diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/options b/python/ql/test/experimental/library-tests/CallGraph-imports/options new file mode 100644 index 00000000000..1bbc489d153 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 -R ./pkg/ diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/__init__.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_only_direct.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_only_direct.py new file mode 100644 index 00000000000..dc687a4344e --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_only_direct.py @@ -0,0 +1 @@ +from .func_def import func diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem.py new file mode 100644 index 00000000000..dd9f6a8f215 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem.py @@ -0,0 +1,2 @@ +from .func_def import func +from .other import * diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem_fixed.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem_fixed.py new file mode 100644 index 00000000000..5c57e676d44 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_problem_fixed.py @@ -0,0 +1,3 @@ +# this ordering makes the problem go away +from .other import * +from .func_def import func diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_star.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_star.py new file mode 100644 index 00000000000..c34c7f1df7e --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/alias_star.py @@ -0,0 +1,2 @@ +from .func_def import * +from .other import * diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/func_def.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/func_def.py new file mode 100644 index 00000000000..531031c0358 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/func_def.py @@ -0,0 +1,2 @@ +def func(): + print("func") diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/other.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/other.py new file mode 100644 index 00000000000..c652349c911 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/other.py @@ -0,0 +1,2 @@ +def something(): + pass diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/use.py b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/use.py new file mode 100644 index 00000000000..fd1d957ba81 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-imports/pkg/use.py @@ -0,0 +1,33 @@ +def test_direct_import(): + from .func_def import func + func() # $ pt,tt="pkg/func_def.py:func" + +test_direct_import() # $ pt,tt=test_direct_import + + +def test_alias_problem(): + from .alias_problem import func + func() # $ pt,tt="pkg/func_def.py:func" + +test_alias_problem() # $ pt,tt=test_alias_problem + + +def test_alias_problem_fixed(): + from .alias_problem_fixed import func + func() # $ pt,tt="pkg/func_def.py:func" + +test_alias_problem_fixed() # $ pt,tt=test_alias_problem_fixed + + +def test_alias_star(): + from .alias_star import func + func() # $ pt,tt="pkg/func_def.py:func" + +test_alias_star() # $ pt,tt=test_alias_star + + +def test_alias_only_direct(): + from .alias_only_direct import func + func() # $ pt,tt="pkg/func_def.py:func" + +test_alias_only_direct() # $ pt,tt=test_alias_only_direct diff --git a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected index 02d08ac4c81..72d792b6623 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected +++ b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected @@ -1,22 +1,53 @@ failures debug_callableNotUnique -| code/class_advanced.py:18:5:18:18 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. | -| code/class_advanced.py:23:5:23:25 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. | pointsTo_found_typeTracker_notFound -| code/class_simple.py:24:1:24:15 | ControlFlowNode for Attribute() | A.some_method | -| code/class_simple.py:25:1:25:21 | ControlFlowNode for Attribute() | A.some_staticmethod | -| code/class_simple.py:26:1:26:20 | ControlFlowNode for Attribute() | A.some_classmethod | -| code/class_simple.py:28:1:28:21 | ControlFlowNode for Attribute() | A.some_staticmethod | -| code/class_simple.py:29:1:29:20 | ControlFlowNode for Attribute() | A.some_classmethod | -| code/runtime_decision.py:18:1:18:6 | ControlFlowNode for func() | rd_bar | -| code/runtime_decision.py:18:1:18:6 | ControlFlowNode for func() | rd_foo | -| code/runtime_decision.py:26:1:26:7 | ControlFlowNode for func2() | rd_bar | -| code/runtime_decision.py:26:1:26:7 | ControlFlowNode for func2() | rd_foo | -| code/simple.py:15:1:15:5 | ControlFlowNode for foo() | foo | -| code/simple.py:16:1:16:14 | ControlFlowNode for indirect_foo() | foo | -| code/simple.py:17:1:17:5 | ControlFlowNode for bar() | bar | -| code/simple.py:18:1:18:5 | ControlFlowNode for lam() | lambda[simple.py:12:7] | -| code/underscore_prefix_func_name.py:18:5:18:19 | ControlFlowNode for some_function() | some_function | -| code/underscore_prefix_func_name.py:21:5:21:19 | ControlFlowNode for some_function() | some_function | -| code/underscore_prefix_func_name.py:24:1:24:21 | ControlFlowNode for _works_since_called() | _works_since_called | +| code/class_attr_assign.py:10:9:10:27 | ControlFlowNode for Attribute() | my_func | +| code/class_attr_assign.py:11:9:11:25 | ControlFlowNode for Attribute() | my_func | +| code/class_attr_assign.py:26:9:26:25 | ControlFlowNode for Attribute() | DummyObject.method | +| code/class_super.py:50:1:50:6 | ControlFlowNode for Attribute() | outside_def | +| code/conditional_in_argument.py:18:5:18:11 | ControlFlowNode for Attribute() | X.bar | +| code/func_defined_outside_class.py:21:1:21:11 | ControlFlowNode for Attribute() | A.foo | +| code/func_defined_outside_class.py:22:1:22:15 | ControlFlowNode for Attribute() | outside | +| code/func_defined_outside_class.py:24:1:24:14 | ControlFlowNode for Attribute() | outside_sm | +| code/func_defined_outside_class.py:25:1:25:14 | ControlFlowNode for Attribute() | outside_cm | +| code/func_defined_outside_class.py:38:11:38:21 | ControlFlowNode for _gen() | B._gen | +| code/func_defined_outside_class.py:39:11:39:21 | ControlFlowNode for _gen() | B._gen | +| code/func_defined_outside_class.py:42:1:42:7 | ControlFlowNode for Attribute() | B._gen.func | +| code/func_defined_outside_class.py:43:1:43:7 | ControlFlowNode for Attribute() | B._gen.func | +| code/funky_regression.py:15:9:15:17 | ControlFlowNode for Attribute() | Wat.f2 | +| code/runtime_decision.py:44:1:44:7 | ControlFlowNode for func4() | "code/runtime_decision_defns.py:4:func4" | +| code/runtime_decision.py:44:1:44:7 | ControlFlowNode for func4() | "code/runtime_decision_defns.py:7:func4" | +| code/tuple_function_return.py:15:1:15:4 | ControlFlowNode for f2() | func | +| code/type_tracking_limitation.py:8:1:8:3 | ControlFlowNode for x() | my_func | typeTracker_found_pointsTo_notFound +| code/callable_as_argument.py:29:5:29:12 | ControlFlowNode for Attribute() | test_class.InsideTestFunc.sm | +| code/class_construction.py:44:9:44:26 | ControlFlowNode for Attribute() | WithNew.some_method | +| code/class_construction.py:61:9:61:26 | ControlFlowNode for Attribute() | WithNew.some_method | +| code/class_construction.py:75:9:75:27 | ControlFlowNode for Attribute() | ExtraCallToInit.__init__ | +| code/class_special_methods.py:22:9:22:16 | ControlFlowNode for self() | Base.__call__ | +| code/class_special_methods.py:22:9:22:16 | ControlFlowNode for self() | Sub.__call__ | +| code/class_special_methods.py:33:1:33:5 | ControlFlowNode for b() | Base.__call__ | +| code/class_special_methods.py:59:1:59:7 | ControlFlowNode for sub() | Sub.__call__ | +| code/class_super.py:43:9:43:21 | ControlFlowNode for Attribute() | A.bar | +| code/class_super.py:44:9:44:27 | ControlFlowNode for Attribute() | A.bar | +| code/class_super.py:63:1:63:18 | ControlFlowNode for Attribute() | A.foo | +| code/class_super.py:78:9:78:28 | ControlFlowNode for Attribute() | A.foo | +| code/class_super.py:81:1:81:12 | ControlFlowNode for Attribute() | C.foo_on_A | +| code/class_super.py:92:9:92:21 | ControlFlowNode for Attribute() | X.foo | +| code/class_super.py:97:9:97:21 | ControlFlowNode for Attribute() | X.foo | +| code/class_super.py:97:9:97:21 | ControlFlowNode for Attribute() | Y.foo | +| code/class_super.py:101:1:101:7 | ControlFlowNode for Attribute() | Z.foo | +| code/class_super.py:108:1:108:8 | ControlFlowNode for Attribute() | Z.foo | +| code/def_in_function.py:22:5:22:11 | ControlFlowNode for Attribute() | test.A.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | A.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | ASub.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | A.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | ASub.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | B.foo | +| code/isinstance.py:17:13:17:22 | ControlFlowNode for Attribute() | A.foo | +| code/nested_class.py:83:9:83:16 | ControlFlowNode for Attribute() | X.class_def_in_func.Y.meth | +| code/self_passing.py:16:9:16:18 | ControlFlowNode for Attribute() | A.foo | +| code/self_passing.py:16:9:16:18 | ControlFlowNode for Attribute() | B.foo | +| code/self_passing.py:67:9:67:16 | ControlFlowNode for Attribute() | Y.cm | +| code/self_passing.py:69:9:69:17 | ControlFlowNode for Attribute() | X.foo | +| code/underscore_prefix_func_name.py:14:5:14:19 | ControlFlowNode for some_function() | some_function | diff --git a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql index 50ad10bd191..fa658d892f0 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql +++ b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql @@ -1,8 +1,15 @@ import python import TestUtilities.InlineExpectationsTest +private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT /** Holds when `call` is resolved to `callable` using points-to based call-graph. */ predicate pointsToCallEdge(CallNode call, Function callable) { + exists(call.getLocation().getFile().getRelativePath()) and + exists(callable.getLocation().getFile().getRelativePath()) and + // I did try using viableCallable from `DataFlowDispatchPointsTo` (from temporary copy + // of `dataflow.new.internal` that still uses points-to) instead of direct + // `getACall()` on a Value, but it only added results for `__init__` methods, not for + // anything else. exists(PythonFunctionValue funcValue | funcValue.getScope() = callable and call = funcValue.getACall() @@ -10,7 +17,25 @@ predicate pointsToCallEdge(CallNode call, Function callable) { } /** Holds when `call` is resolved to `callable` using type-tracking based call-graph. */ -predicate typeTrackerCallEdge(CallNode call, Function callable) { none() } +predicate typeTrackerCallEdge(CallNode call, Function callable) { + exists(call.getLocation().getFile().getRelativePath()) and + exists(callable.getLocation().getFile().getRelativePath()) and + exists(TT::DataFlowCallable dfCallable, TT::DataFlowCall dfCall | + dfCallable.getScope() = callable and + dfCall.getNode() = call and + dfCallable = TT::viableCallable(dfCall) + ) +} + +/** Holds if the call edge is from a class call. */ +predicate typeTrackerClassCall(CallNode call, Function callable) { + exists(call.getLocation().getFile().getRelativePath()) and + exists(callable.getLocation().getFile().getRelativePath()) and + exists(TT::NormalCall cc | + cc = TT::TNormalCall(call, _, any(TT::TCallType t | t instanceof TT::CallTypeClass)) and + TT::TFunction(callable) = TT::viableCallable(cc) + ) +} class CallGraphTest extends InlineExpectationsTest { CallGraphTest() { this = "CallGraphTest" } @@ -28,16 +53,36 @@ class CallGraphTest extends InlineExpectationsTest { | location = call.getLocation() and element = call.toString() and - value = betterQualName(target) + value = getCallEdgeValue(call, target) ) } } +bindingset[call, target] +string getCallEdgeValue(CallNode call, Function target) { + if call.getLocation().getFile() = target.getLocation().getFile() + then result = betterQualName(target) + else + exists(string fixedRelativePath | + fixedRelativePath = + target.getLocation().getFile().getRelativePath().regexpCapture(".*/CallGraph[^/]*/(.*)", 1) + | + // the value needs to be enclosed in quotes to allow special characters + result = "\"" + fixedRelativePath + ":" + betterQualName(target) + "\"" + ) +} + bindingset[func] string betterQualName(Function func) { // note: `target.getQualifiedName` for Lambdas is just "lambda", so is not very useful :| not func.isLambda() and - result = func.getQualifiedName() + if + strictcount(Function f | + f.getEnclosingModule() = func.getEnclosingModule() and + f.getQualifiedName() = func.getQualifiedName() + ) = 1 + then result = func.getQualifiedName() + else result = func.getLocation().getStartLine() + ":" + func.getQualifiedName() or func.isLambda() and result = @@ -46,16 +91,29 @@ string betterQualName(Function func) { } query predicate debug_callableNotUnique(Function callable, string message) { - exists(Function f | f != callable and f.getQualifiedName() = callable.getQualifiedName()) and + exists(callable.getLocation().getFile().getRelativePath()) and + exists(Function f | + f != callable and + betterQualName(f) = betterQualName(callable) and + f.getLocation().getFile() = callable.getLocation().getFile() + ) and message = - "Qualified function name '" + callable.getQualifiedName() + "' is not unique. Please fix." + "Qualified function name '" + callable.getQualifiedName() + + "' is not unique within its file. Please fix." } query predicate pointsTo_found_typeTracker_notFound(CallNode call, string qualname) { exists(Function target | pointsToCallEdge(call, target) and not typeTrackerCallEdge(call, target) and - qualname = betterQualName(target) + qualname = getCallEdgeValue(call, target) and + // ignore SPURIOUS call edges + not exists(FalsePositiveExpectation spuriousResult | + spuriousResult.getTag() = "pt" and + spuriousResult.getValue() = getCallEdgeValue(call, target) and + spuriousResult.getLocation().getFile() = call.getLocation().getFile() and + spuriousResult.getLocation().getStartLine() = call.getLocation().getStartLine() + ) ) } @@ -63,6 +121,17 @@ query predicate typeTracker_found_pointsTo_notFound(CallNode call, string qualna exists(Function target | not pointsToCallEdge(call, target) and typeTrackerCallEdge(call, target) and - qualname = betterQualName(target) + qualname = getCallEdgeValue(call, target) and + // We filter out result differences for points-to and type-tracking for class calls, + // since otherwise it gives too much noise (these are just handled differently + // between the two). + not typeTrackerClassCall(call, target) and + // ignore SPURIOUS call edges + not exists(FalsePositiveExpectation spuriousResult | + spuriousResult.getTag() = "tt" and + spuriousResult.getValue() = getCallEdgeValue(call, target) and + spuriousResult.getLocation().getFile() = call.getLocation().getFile() and + spuriousResult.getLocation().getStartLine() = call.getLocation().getStartLine() + ) ) } diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/aliased_import.py b/python/ql/test/experimental/library-tests/CallGraph/code/aliased_import.py new file mode 100644 index 00000000000..ac0c7184881 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/aliased_import.py @@ -0,0 +1 @@ +from .simple import foo diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/bound_method_arg.py b/python/ql/test/experimental/library-tests/CallGraph/code/bound_method_arg.py new file mode 100644 index 00000000000..a59510ec681 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/bound_method_arg.py @@ -0,0 +1,16 @@ +class Foo(object): + def meth(self, arg): + print("Foo.meth", arg) + + @classmethod + def cm(cls, arg): + print("Foo.cm", arg) + + +def call_func(func): + func(42) # $ pt,tt=Foo.meth pt,tt=Foo.cm + + +foo = Foo() +call_func(foo.meth) # $ pt,tt=call_func +call_func(Foo.cm) # $ pt,tt=call_func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/callable_as_argument.py b/python/ql/test/experimental/library-tests/CallGraph/code/callable_as_argument.py new file mode 100644 index 00000000000..ab8e0cf6ba9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/callable_as_argument.py @@ -0,0 +1,55 @@ +# ============================================================================== +# function +# ============================================================================== + +def call_func(f): + f() # $ pt,tt=my_func pt,tt=test_func.inside_test_func + + +def my_func(): + print("my_func") + +call_func(my_func) # $ pt,tt=call_func + + +def test_func(): + def inside_test_func(): + print("inside_test_func") + + call_func(inside_test_func) # $ pt,tt=call_func + +test_func() # $ pt,tt=test_func + + +# ============================================================================== +# class +# ============================================================================== + +def class_func(cls): + cls.sm() # $ pt,tt=MyClass.sm tt=test_class.InsideTestFunc.sm + cls(42) # $ tt=MyClass.__init__ tt=test_class.InsideTestFunc.__init__ + + +class MyClass(object): + def __init__(self, arg): + print(self, arg) + + @staticmethod + def sm(): + print("MyClass.staticmethod") + +class_func(MyClass) # $ pt,tt=class_func + + +def test_class(): + class InsideTestFunc(object): + def __init__(self, arg): + print(self, arg) + + @staticmethod + def sm(): + print("InsideTestFunc.staticmethod") + + class_func(InsideTestFunc) # $ pt,tt=class_func + +test_class() # $ pt,tt=test_class diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_advanced.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_advanced.py deleted file mode 100644 index 94667621f34..00000000000 --- a/python/ql/test/experimental/library-tests/CallGraph/code/class_advanced.py +++ /dev/null @@ -1,40 +0,0 @@ -class B(object): - - def __init__(self, arg): - print('B.__init__', arg) - self._arg = arg - - def __str__(self): - print('B.__str__') - return 'B (arg={})'.format(self.arg) - - def __add__(self, other): - print('B.__add__') - if isinstance(other, B): - return B(self.arg + other.arg) - return B(self.arg + other) - - @property - def arg(self): - print('B.arg getter') - return self._arg - - @arg.setter - def arg(self, value): - print('B.arg setter') - self._arg = value - - -b1 = B(1) -b2 = B(2) -b3 = b1 + b2 - -print('value printing:', str(b1)) -print('value printing:', str(b2)) -print('value printing:', str(b3)) - -b3.arg = 42 -b4 = b3 + 100 - -# this calls `str(b4)` inside -print('value printing:', b4) diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_attr_assign.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_attr_assign.py new file mode 100644 index 00000000000..605375925f7 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_attr_assign.py @@ -0,0 +1,30 @@ +def my_func(): + print("my_func") + +class Foo(object): + def __init__(self, func): + self.indirect_ref = func + self.direct_ref = my_func + + def later(self): + self.indirect_ref() # $ pt=my_func MISSING: tt=my_func + self.direct_ref() # $ pt=my_func MISSING: tt=my_func + +foo = Foo(my_func) # $ tt=Foo.__init__ +foo.later() # $ pt,tt=Foo.later + + +class DummyObject(object): + def method(self): + print("DummyObject.method") + +class Bar(object): + def __init__(self): + self.obj = DummyObject() + + def later(self): + self.obj.method() # $ pt=DummyObject.method MISSING: tt=DummyObject.method + + +bar = Bar(my_func) # $ tt=Bar.__init__ +bar.later() # $ pt,tt=Bar.later diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_construction.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_construction.py new file mode 100644 index 00000000000..1ae696edf61 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_construction.py @@ -0,0 +1,98 @@ +class X(object): + def __init__(self, arg): + print("X.__init__", arg) + self.arg = arg + + def foo(self): + print("X.foo", self.arg) + + def meth(self): + print("X.meth") + return type(self)(42.1) # $ tt=X.__init__ tt=Y.__init__ + + @classmethod + def cm(cls): + print("X.cm") + cls(42.2) # $ tt=X.__init__ tt=Y.__init__ + +x = X(42.0) # $ tt=X.__init__ +x_421 = x.meth() # $ pt,tt=X.meth +X.cm() # $ pt,tt=X.cm +x.foo() # $ pt,tt=X.foo +print() +x_421.foo() # $ pt=X.foo tt=X.foo +print() + + +class Y(X): + def __init__(self, arg): + print("Y.__init__", arg) + super().__init__(-arg) # $ pt,tt=X.__init__ + +y = Y(43) # $ tt=Y.__init__ +y.meth() # $ pt,tt=X.meth +y.cm() # $ pt,tt=X.cm +print() + +# --- + +class WithNew(object): + def __new__(cls, arg): + print("WithNew.__new__", arg) + inst = super().__new__(cls) + assert isinstance(inst, cls) + inst.some_method() # $ tt=WithNew.some_method + return inst + + def __init__(self, arg=None): + print("WithNew.__init__", arg) + + def some_method(self): + print("WithNew.some_method") + +WithNew(44) # $ tt=WithNew.__new__ tt=WithNew.__init__ +print() + +class WithNewSub(WithNew): + def __new__(cls): + print("WithNewSub.__new__") + inst = super().__new__(cls, 44.1) # $ pt,tt=WithNew.__new__ + assert isinstance(inst, cls) + inst.some_method() # $ tt=WithNew.some_method + return inst + +WithNewSub() # $ tt=WithNewSub.__new__ tt=WithNew.__init__ +print() + +# ------------------------------------------------------------------------------ + +class ExtraCallToInit(object): + def __new__(cls, arg): + print("ExtraCallToInit.__new__", arg) + inst = super().__new__(cls) + assert isinstance(inst, cls) + # you're not supposed to do this, since it will cause the __init__ method will be run twice. + inst.__init__(1001) # $ tt=ExtraCallToInit.__init__ + return inst + + def __init__(self, arg): + print("ExtraCallToInit.__init__", arg, self) + +ExtraCallToInit(1000) # $ tt=ExtraCallToInit.__new__ tt=ExtraCallToInit.__init__ +print() + + +class InitNotCalled(object): + """as described in https://docs.python.org/3/reference/datamodel.html#object.__new__ + __init__ will only be called when the returned object from __new__ is an instance of + the `cls` parameter... + """ + def __new__(cls, arg): + print("InitNotCalled.__new__", arg) + return False + + def __init__(self, arg): + print("InitNotCalled.__init__", arg) + +InitNotCalled(2000) # $ tt=InitNotCalled.__new__ SPURIOUS: tt=InitNotCalled.__init__ +print() diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_decorator.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_decorator.py new file mode 100644 index 00000000000..910e24d2519 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_decorator.py @@ -0,0 +1,34 @@ +# decorated class + +def my_class_decorator(cls): + print("dummy decorator") + return cls + +@my_class_decorator # $ pt=my_class_decorator tt=my_class_decorator +class A(object): + def foo(self): + pass + +a = A() +a.foo() # $ pt,tt=A.foo + +class B(A): + def bar(self): + self.foo() # $ pt,tt=A.foo + + +# decorated class, unknown decorator + +from some_unknown_module import unknown_class_decorator + +@unknown_class_decorator +class X(object): + def foo(self): + pass + +x = X() +x.foo() # $ pt,tt=X.foo + +class Y(X): + def bar(self): + self.foo() # $ pt,tt=X.foo diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro.py new file mode 100644 index 00000000000..d8eae002cb4 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro.py @@ -0,0 +1,35 @@ +class Base(object): + def foo(self): + print("Base.foo") + + +class A(Base): + def foo(self): + print("A.foo") + super().foo() # $ pt,tt=Base.foo + +class ASub(A): + pass + +class B(Base): + def foo(self): + print("B.foo") + # NOTE: If this missing result is fixed, please update the QLDoc for + # `getNextClassInMro` as well + super().foo() # $ pt,tt=Base.foo MISSING: pt,tt=A.foo + +class BSub(B): + def bar(self): + print("BSub.bar") + super().foo() # $ pt,tt=B.foo SPURIOUS: tt=A.foo + +bs = BSub() +bs.foo() # $ pt,tt=B.foo +bs.bar() # $ pt,tt=BSub.bar + +print("! Indirect") +class Indirect(BSub, ASub): + pass + +Indirect().foo() # $ pt,tt=B.foo SPURIOUS: tt=A.foo +Indirect().bar() # $ pt,tt=BSub.bar diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro2.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro2.py new file mode 100644 index 00000000000..6a64f905412 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_more_mro2.py @@ -0,0 +1,22 @@ +class A(object): + def foo(self): + print("A.foo") + +class B(A): + pass + +b = B() +b.foo() # $ pt,tt=A.foo + +class C(A): + def foo(self): + print("C.foo") + +class BC(B, C): + def bar(self): + print("BC.bar") + super().foo() # $ pt,tt=C.foo SPURIOUS: tt=A.foo + +bc = BC() +bc.foo() # $ pt,tt=C.foo SPURIOUS: tt=A.foo +bc.bar() # $ pt,tt=BC.bar diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_properties.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_properties.py new file mode 100644 index 00000000000..ea7d7847adb --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_properties.py @@ -0,0 +1,54 @@ +def func(): + print("func") + +class Prop(object): + def __init__(self, arg): + self._arg = arg + self._arg2 = arg + + @property + def arg(self): + print('Prop.arg getter') + return self._arg + + @arg.setter + def arg(self, value): + print('Prop.arg setter') + self._arg = value + + @arg.deleter + def arg(self): + print('Prop.arg deleter') + # haha, you cannot delete me! + + def _arg2_getter(self): + print('Prop.arg2 getter') + return self._arg2 + + def _arg2_setter(self, value): + print('Prop.arg2 setter') + self._arg2 = value + + def _arg2_deleter(self): + print('Prop.arg2 deleter') + # haha, you cannot delete me! + + arg2 = property(_arg2_getter, _arg2_setter, _arg2_deleter) + + @property + def func_prop(self): + print("Prop.func_prop getter") + return func + +prop = Prop(42) # $ tt=Prop.__init__ + +prop.arg +prop.arg = 43 +del prop.arg + +prop.arg2 +prop.arg2 = 43 +del prop.arg2 + +f = prop.func_prop +f() # $ MISSING: tt=func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_simple.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_simple.py deleted file mode 100644 index f201e648e3a..00000000000 --- a/python/ql/test/experimental/library-tests/CallGraph/code/class_simple.py +++ /dev/null @@ -1,29 +0,0 @@ -class A(object): - - def __init__(self, arg): - print('A.__init__', arg) - self.arg = arg - - def some_method(self): - print('A.some_method', self) - - @staticmethod - def some_staticmethod(): - print('A.some_staticmethod') - - @classmethod - def some_classmethod(cls): - print('A.some_classmethod', cls) - - -# TODO: Figure out how to annotate class instantiation (and add one here). -# Current points-to says it's a call to the class (instead of __init__/__new__/metaclass-something). -# However, current test setup uses "callable" for naming, and expects things to be Function. -a = A(42) - -a.some_method() # $ pt=A.some_method -a.some_staticmethod() # $ pt=A.some_staticmethod -a.some_classmethod() # $ pt=A.some_classmethod - -A.some_staticmethod() # $ pt=A.some_staticmethod -A.some_classmethod() # $ pt=A.some_classmethod diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_special_methods.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_special_methods.py new file mode 100644 index 00000000000..23dcefdb852 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_special_methods.py @@ -0,0 +1,66 @@ +class Base(object): + + def __init__(self, arg): + print("Base.__init__", arg) + self.arg = arg + + def __str__(self): + print("Base.__str__") + return 'Base STR (arg={})'.format(self.arg) + + def __add__(self, other): + print("Base.__add__") + if isinstance(other, Base): + return Base(self.arg + other.arg) # $ tt=Base.__init__ + return Base(self.arg + other) # $ tt=Base.__init__ + + def __call__(self, val): + print("Base.__call__", val) + + def wat(self): + print("Base.wat") + self(43) # $ tt=Base.__call__ tt=Sub.__call__ + + +b = Base(1) # $ tt=Base.__init__ + +print(str(b)) +# this calls `str(b)` inside +print(b) + +print("\n! calls") + +b(42) # $ tt=Base.__call__ +b.wat() # $ pt,tt=Base.wat + +b.__call__(44) # $ pt,tt=Base.__call__ + +print("\n! b2") +b2 = Base(2) # $ tt=Base.__init__ + + +b + b2 # $ MISSING: tt=Base.__add__ +b + 100 # $ MISSING: tt=Base.__add__ + + +# ======== +print("\n! Sub") + +class Sub(Base): + def __add__(self, other): + print("Sub.__add__") + + def __call__(self, arg): + print("Sub.__call__", arg) + +sub = Sub(10) # $ tt=Base.__init__ +sub + 42 + +sub(55) # $ tt=Sub.__call__ +sub.wat() # $ pt,tt=Base.wat + +# not possible to indirectly access addition of subclass +try: + super(Sub, sub) + 143 +except TypeError: + print("TypeError as expected") diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass.py new file mode 100644 index 00000000000..cd2ee42fa03 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass.py @@ -0,0 +1,178 @@ +class A(object): + + def __init__(self, arg): + print('A.__init__', arg) + self.arg = arg + + def some_method(self): + print('A.some_method', self) + + @staticmethod + def some_staticmethod(): + print('A.some_staticmethod') + + @classmethod + def some_classmethod(cls): + print('A.some_classmethod', cls) + + +a = A(42) # $ tt=A.__init__ + +a.some_method() # $ pt,tt=A.some_method +a.some_staticmethod() # $ pt,tt=A.some_staticmethod +a.some_classmethod() # $ pt,tt=A.some_classmethod + +A.some_method(a) # $ pt,tt=A.some_method +A.some_staticmethod() # $ pt,tt=A.some_staticmethod +A.some_classmethod() # $ pt,tt=A.some_classmethod + +print("- type()") +type(a).some_method(a) # $ pt,tt=A.some_method +type(a).some_staticmethod() # $ pt,tt=A.some_staticmethod +type(a).some_classmethod() # $ pt,tt=A.some_classmethod + +# Subclass test +print("\n! B") +class B(A): + pass + +b = B(42) # $ tt=A.__init__ + +b.some_method() # $ pt,tt=A.some_method +b.some_staticmethod() # $ pt,tt=A.some_staticmethod +b.some_classmethod() # $ pt,tt=A.some_classmethod + +B.some_method(b) # $ pt,tt=A.some_method +B.some_staticmethod() # $ pt,tt=A.some_staticmethod +B.some_classmethod() # $ pt,tt=A.some_classmethod + +print("- type()") +type(b).some_method(b) # $ pt,tt=A.some_method +type(b).some_staticmethod() # $ pt,tt=A.some_staticmethod +type(b).some_classmethod() # $ pt,tt=A.some_classmethod + +# Subclass with method override +print("\n! Subclass with method override") +class C(A): + def some_method(self): + print('C.some_method', self) + +c = C(42) # $ tt=A.__init__ +c.some_method() # $ pt,tt=C.some_method + + +class D(object): + def some_method(self): + print('D.some_method', self) + +class E(C, D): + pass + +e = E(42) # $ tt=A.__init__ +e.some_method() # $ pt,tt=C.some_method + +class F(D, C): + pass + +f = F(42) # $ tt=A.__init__ +f.some_method() # $ pt,tt=D.some_method + +# ------------------------------------------------------------------------------ +# self/cls in methods +# ------------------------------------------------------------------------------ + +class Base(object): + def foo(self): + print('Base.foo') + + def bar(self): + print('Base.bar') + + def call_stuff(self): + self.foo() # $ pt,tt=Base.foo pt,tt=Sub.foo pt,tt=Mixin.foo + self.bar() # $ pt,tt=Base.bar + + self.sm() # $ pt,tt=Base.sm + self.cm() # $ pt,tt=Base.cm + + self.sm2() # $ pt,tt=Base.sm2 pt,tt=Sub.sm2 + self.cm2() # $ pt,tt=Base.cm2 pt,tt=Sub.cm2 + + type(self).sm2() # $ pt,tt=Base.sm2 pt,tt=Sub.sm2 + type(self).cm2() # $ pt,tt=Base.cm2 pt,tt=Sub.cm2 + + @staticmethod + def sm(): + print("Base.sm") + + @classmethod + def cm(cls): + print("Base.cm") + + @staticmethod + def sm2(): + print("Base.sm2") + + @classmethod + def cm2(cls): + print("Base.cm2") + + @classmethod + def call_from_cm(cls): + cls.sm() # $ pt,tt=Base.sm + cls.cm() # $ pt,tt=Base.cm + + cls.sm2() # $ pt,tt=Base.sm2 pt,tt=Sub.sm2 + cls.cm2() # $ pt,tt=Base.cm2 pt,tt=Sub.cm2 + +base = Base() +print("! base.call_stuff()") +base.call_stuff() # $ pt,tt=Base.call_stuff +print("! Base.call_from_cm()") +Base.call_from_cm() # $ pt,tt=Base.call_from_cm + +class Sub(Base): + def foo(self): + print("Sub.foo") + + def foo_on_super(self): + sup = super() + sup.foo() # $ pt,tt=Base.foo + + def also_call_stuff(self): + self.sm() # $ pt,tt=Base.sm + self.cm() # $ pt,tt=Base.cm + + self.sm2() # $ pt,tt=Sub.sm2 + self.cm2() # $ pt,tt=Sub.cm2 + + @staticmethod + def sm2(): + print("Sub.sm2") + + @classmethod + def cm2(cls): + print("Sub.cm2") + +sub = Sub() +print("! sub.foo_on_super()") +sub.foo_on_super() # $ pt,tt=Sub.foo_on_super +print("! sub.call_stuff()") +sub.call_stuff() # $ pt,tt=Base.call_stuff +print("! sub.also_call_stuff()") +sub.also_call_stuff() # $ pt,tt=Sub.also_call_stuff +print("! Sub.call_from_cm()") +Sub.call_from_cm() # $ pt,tt=Base.call_from_cm + + +class Mixin(object): + def foo(self): + print("Mixin.foo") + +class SubWithMixin(Mixin, Base): + # the ordering here means that in Base.call_stuff, the call to self.foo will go to Mixin.foo + pass + +swm = SubWithMixin() +print("! swm.call_stuff()") +swm.call_stuff() # $ pt,tt=Base.call_stuff diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass2.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass2.py new file mode 100644 index 00000000000..43f5c2d81f8 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_subclass2.py @@ -0,0 +1,38 @@ +class Base(object): + def foo(self): + print("Base.foo") + + def call_stuff(self): + print("Base.call_stuff") + self.foo() # $ pt,tt=Base.foo pt,tt=X.foo + +class X(object): + def __init__(self): + print("X.__init__") + + def foo(self): + print("X.foo") + +class Y(object): + def __init__(self): + print("Y.__init__") + + def foo(self): + print("Y.foo") + +class Contrived(X, Y, Base): + pass + +contrived = Contrived() # $ tt=X.__init__ +contrived.foo() # $ pt,tt=X.foo +contrived.call_stuff() # $ pt,tt=Base.call_stuff + +# Ensure that we don't mix up __init__ resolution for Contrived() due to MRO +# approximation + +class HasInit(object): + def __init__(self): + pass + +class TryingToTrickYou(Contrived, HasInit): + pass diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/class_super.py b/python/ql/test/experimental/library-tests/CallGraph/code/class_super.py new file mode 100644 index 00000000000..dc3a58fb36c --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/class_super.py @@ -0,0 +1,108 @@ +def outside_def(self): + print("outside_def") + try: + super().foo() + except RuntimeError: + pass + + +class A(object): + def foo(self): + print("A.foo") + + @classmethod + def bar(cls): + print("A.bar") + +class B(A): + def foo(self): + print("B.foo") + + def foo_on_super(self): + print("B.foo_on_super") + super().foo() # $ pt,tt=A.foo + super(B, self).foo() # $ pt,tt=A.foo + + od = outside_def + + @staticmethod + def sm(): + try: + super().foo() + except RuntimeError: + print("B.sm") + pass + + @classmethod + def bar(cls): + print("B.bar") + + @classmethod + def bar_on_super(cls): + print("B.bar_on_super") + super().bar() # $ tt=A.bar + super(B, cls).bar() # $ tt=A.bar + + +b = B() +b.foo() # $ pt,tt=B.foo +b.foo_on_super() # $ pt,tt=B.foo_on_super +b.od() # $ pt=outside_def +b.sm() # $ pt,tt=B.sm + +print("="*10, "static method") +B.bar() # $ pt,tt=B.bar +B.bar_on_super() # $ pt,tt=B.bar_on_super + + +print("="*10, "Manual calls to super") + +super(B, b).foo() # $ pt,tt=A.foo + +assert A.foo == super(B, B).foo +super(B, B).foo(b) # $ tt=A.foo + +try: + super(B, 42).foo() +except TypeError: + pass + +# For some reason, points-to isn't able to resolve any calls from here on. I've tried to +# comment out both try-except blocks, but that did not solve the problem :| + +print("="*10, "C") + +class C(B): + def foo_on_A(self): + print('C.foo_on_A') + super(B, self).foo() # $ tt=A.foo + +c = C() +c.foo_on_A() # $ tt=C.foo_on_A + +print("="*10, "Diamon hierachy") + +class X(object): + def foo(self): + print('X.foo') + +class Y(X): + def foo(self): + print('Y.foo') + super().foo() # $ tt=X.foo + +class Z(X): + def foo(self): + print('Z.foo') + super().foo() # $ tt=X.foo tt=Y.foo + +print("! z.foo()") +z = Z() +z.foo() # $ tt=Z.foo + +class ZY(Z, Y): + pass + +print("! zy.foo()") +zy = ZY() +zy.foo() # $ tt=Z.foo diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/conditional_in_argument.py b/python/ql/test/experimental/library-tests/CallGraph/code/conditional_in_argument.py new file mode 100644 index 00000000000..885393fae90 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/conditional_in_argument.py @@ -0,0 +1,36 @@ +class X(object): + def foo(self, *args): + print("X.foo", args) + + def bar(self, *args): + print("X.bar", args) + + +def func(cond=True): + x = X() + + # ok + x.foo() # $ pt,tt=X.foo + x.bar() # $ pt,tt=X.bar + + # the conditional in the argument makes us stop tracking the class instance :| + x.foo(1 if cond else 0) # $ pt,tt=X.foo + x.bar() # $ pt=X.bar MISSING: tt=X.bar + + +func() # $ pt,tt=func + +def func2(cond=True): + y = X() + + # ok + y.foo() # $ pt,tt=X.foo + y.bar() # $ pt,tt=X.bar + + if cond: + arg = 1 + else: + arg = 0 + + y.foo(arg) # $ pt,tt=X.foo + y.bar() # $ pt,tt=X.bar diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/def_in_function.py b/python/ql/test/experimental/library-tests/CallGraph/code/def_in_function.py new file mode 100644 index 00000000000..8b7e0dcfb89 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/def_in_function.py @@ -0,0 +1,24 @@ +def test(): + def foo(): + print("foo") + + foo() # $ pt,tt=test.foo + + def bar(): + print("bar") + def baz(): + print("baz") + baz() # $ pt,tt=test.bar.baz + return baz + + baz_ref = bar() # $ pt,tt=test.bar + baz_ref() # $ pt,tt=test.bar.baz + + class A(object): + def foo(self): + print("A.foo") + + a = A() + a.foo() # $ tt=test.A.foo + +test() # $ pt,tt=test diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/func_defined_outside_class.py b/python/ql/test/experimental/library-tests/CallGraph/code/func_defined_outside_class.py new file mode 100644 index 00000000000..c0ff09d4987 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/func_defined_outside_class.py @@ -0,0 +1,43 @@ +def outside(self): + print("outside", self) + +def outside_sm(): + print("outside_sm") + +def outside_cm(cls): + print("outside_cm", cls) + +class A(object): + def foo(self): + print("A.foo") + + foo_ref = foo + + outside_ref = outside + outside_sm = staticmethod(outside_sm) + outside_cm = classmethod(outside_cm) + +a = A() +a.foo_ref() # $ pt=A.foo +a.outside_ref() # $ pt=outside + +a.outside_sm() # $ pt=outside_sm +a.outside_cm() # $ pt=outside_cm + +# === + +print("\n! B") + +# this pattern was seen in django +class B(object): + def _gen(value): + def func(self): + print("B._gen.func", value) + return func + + foo = _gen("foo") # $ pt=B._gen + bar = _gen("bar") # $ pt=B._gen + +b = B() +b.foo() # $ pt=B._gen.func +b.bar() # $ pt=B._gen.func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/funky_regression.py b/python/ql/test/experimental/library-tests/CallGraph/code/funky_regression.py new file mode 100644 index 00000000000..bb87bfb47e9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/funky_regression.py @@ -0,0 +1,63 @@ +# When this regression was discovered, we did not resolve the `self.f2()` call after the +# try-except block, but ONLY when passing an attribute to a method, as indicated in the +# other tests below. + +class Wat(object): + def f1(self, arg): pass + def f2(self): pass + + def func(self, foo): + try: + self.f1(foo.bar) # $ pt,tt=Wat.f1 + except Exception as e: + raise e + + self.f2() # $ pt=Wat.f2 MISSING: tt=Wat.f2 + + +# ============================================================================== +# variants that we are able to handle +# ============================================================================== + + +class Works(object): + "not using attribute" + def f1(self, arg): pass + def f2(self): pass + + def func(self, foo): + try: + self.f1(foo) # $ pt,tt=Works.f1 + except Exception as e: + raise e + + self.f2() # $ pt,tt=Works.f2 + + +class AlsoWorks(object): + "no exception" + def f1(self, arg): pass + def f2(self): pass + + def func(self, foo): + self.f1(foo.bar) # $ pt,tt=AlsoWorks.f1 + + self.f2() # $ pt,tt=AlsoWorks.f2 + + +def safe_func(arg): + pass + + +class Works3(object): + "call to non-self function" + def f1(self, arg): pass + def f2(self): pass + + def func(self, foo): + try: + safe_func(foo.bar) # $ pt,tt=safe_func + except Exception as e: + raise e + + self.f2() # $ pt,tt=Works3.f2 diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py b/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py new file mode 100644 index 00000000000..a8fbcc32d43 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py @@ -0,0 +1,40 @@ +import os + +class Base: + def foo(self): + print("Base.foo") + + def call(self): + if isinstance(self, A): + self.foo() # $ tt=A.foo tt=ASub.foo SPURIOUS: tt=B.foo tt=Base.foo + + # This is a silly test, but just to show that second argument of isinstance as + # tuple is handled + if isinstance(self, (A, B)): + self.foo() # $ tt=A.foo tt=ASub.foo tt=B.foo SPURIOUS: tt=Base.foo + + if isinstance(self, ASubNoDef): + self.foo() # $ tt=A.foo SPURIOUS: tt=ASub.foo tt=B.foo tt=Base.foo + + +class A(Base): + def foo(self): + print("A.foo") + +class ASub(A): + def foo(self): + print("ASub.foo") + +class ASubNoDef(A): pass + +class B(Base): + def foo(self): + print("B.foo") + +cond = os.urandom(1)[0] > 128 + +x = A() if cond else B() +x.foo() # $ pt,tt=A.foo pt,tt=B.foo + +if isinstance(x, A): + x.foo() # $ pt,tt=A.foo SPURIOUS: tt=B.foo diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/nested_class.py b/python/ql/test/experimental/library-tests/CallGraph/code/nested_class.py new file mode 100644 index 00000000000..1248dbdb426 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/nested_class.py @@ -0,0 +1,87 @@ +class A(object): + class B(object): + @staticmethod + def foo(): + print("A.B.foo") + + @staticmethod + def bar(): + print("A.B.bar") + A.B.foo() # $ pt,tt=A.B.foo + + +A.B.bar() # $ pt,tt=A.B.bar + + +ab = A.B() +ab.bar() # $ pt,tt=A.B.bar + +# ============================================================================== + +class OuterBase(object): + def foo(self): + print("OuterBase.foo") + +class InnerBase(object): + def foo(self): + print("InnerBase.foo") + +class Outer(OuterBase): + def foo(self): + print("Outer.foo") + super().foo() # $ pt,tt=OuterBase.foo + + class Inner(InnerBase): + def foo(self): + print("Inner.foo") + super().foo() # $ pt,tt=InnerBase.foo + +outer = Outer() +outer.foo() # $ pt,tt=Outer.foo + +inner = Outer.Inner() +inner.foo() # $ pt,tt=Outer.Inner.foo + +# ============================================================================== + +class Base(object): + def foo(self): + print("Base.foo") + +class Base2(object): + def foo(self): + print("Base2.foo") + +class X(Base): + def meth(self): + print("X.meth") + super().foo() # $ pt,tt=Base.foo + + def inner_func(): + print("inner_func") + try: + super().foo() + except RuntimeError: + print("RuntimeError, as expected") + + inner_func() # $ pt,tt=X.meth.inner_func + + def inner_func2(this_works): + print("inner_func2") + super().foo() # $ MISSING: tt=Base.foo + + inner_func2(self) # $ pt,tt=X.meth.inner_func2 + + def class_def_in_func(self): + print("X.class_def_in_func") + class Y(Base2): + def meth(self): + print("Y.meth") + super().foo() # $ pt,tt=Base2.foo + + y = Y() + y.meth() # $ tt=X.class_def_in_func.Y.meth + +x = X() +x.meth() # $ pt,tt=X.meth +x.class_def_in_func() # $ pt=X.class_def_in_func tt=X.class_def_in_func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/relative_import.py b/python/ql/test/experimental/library-tests/CallGraph/code/relative_import.py new file mode 100644 index 00000000000..06191fed7e9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/relative_import.py @@ -0,0 +1,7 @@ +def test_relative_import(): + from .simple import foo + foo() # $ pt,tt="code/simple.py:foo" + +def test_aliased_relative_import(): + from .aliased_import import foo + foo() # $ pt,tt="code/simple.py:foo" diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py index 3c4ebbb73e1..d3800080589 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py +++ b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py @@ -15,7 +15,7 @@ if len(sys.argv) >= 2 and not sys.argv[1] in ['0', 'False', 'false']: else: func = rd_bar -func() # $ pt=rd_foo pt=rd_bar +func() # $ pt,tt=rd_foo pt,tt=rd_bar # Random doesn't work with points-to :O if random.random() < 0.5: @@ -23,4 +23,22 @@ if random.random() < 0.5: else: func2 = rd_bar -func2() # $ pt=rd_foo pt=rd_bar +func2() # $ pt,tt=rd_foo pt,tt=rd_bar + + +# ============================================================================== +# definition is random + +if random.random() < 0.5: + def func3(): + print("func3 A") +else: + def func3(): + print("func3 B") + +func3() # $ pt,tt=33:func3 pt,tt=36:func3 + + +# func4 uses same setup as func3, it's just defined in an other file +from code.runtime_decision_defns import func4 +func4() # $ pt="code/runtime_decision_defns.py:4:func4" pt="code/runtime_decision_defns.py:7:func4" MISSING: tt diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision_defns.py b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision_defns.py new file mode 100644 index 00000000000..931d9246fa1 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision_defns.py @@ -0,0 +1,8 @@ +import random + +if random.random() < 0.5: + def func4(): + print("func4 A") +else: + def func4(): + print("func4 B") diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/self_passing.py b/python/ql/test/experimental/library-tests/CallGraph/code/self_passing.py new file mode 100644 index 00000000000..f5618450033 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/self_passing.py @@ -0,0 +1,94 @@ +# These test-cases illustrates what can happen if we allow the type trackers that are used +# for tracking class instances to flow into self parameters. + +# This first case shows the problem of the call to `self.bar` inside A.foo, could be +# considered a call to B.bar, if we allow the flow from the `self` parameter of +# `Base.base_meth` to flow into A.foo (through the `self.foo` call). This is +# problematic, and causes us to have different results for the `self.bar()` calls in +# `A.foo` and `A.not_called`. + +from inspect import isclass + + +class Base(object): + def base_meth(self): + print("Base.base_meth") + self.foo() # $ pt,tt=Base.foo tt=A.foo tt=B.foo + + def foo(self): + print("Base.foo") + +class A(Base): + def foo(self): + print("A.foo") + self.bar() # $ pt,tt=A.bar + + def not_called(self): + self.bar() #$ pt,tt=A.bar + + def bar(self): + print("A.bar") + +class B(Base): + def foo(self): + print("B.foo") + + def bar(self): + print("B.bar") + +a = A() +a.foo() # $ pt,tt=A.foo + +# Another problem is mixing up class instances and class references. In the example +# below since `func` takes BOTH an instance of X, and the class Y, we used to end up +# tracking _both_ to the self argument of X.foo, which meant that the self.meth() call +# in X.foo was resolved to BOTH X.meth and Y.meth. + +class X(object): + def meth(self): + print("X.meth") + + def foo(self): + print("X.foo") + self.meth() # $ pt,tt=X.meth + + +class Y(object): + def meth(self): + print("Y.meth") + + @classmethod + def cm(cls): + print("Y.cm") + + +def func(obj): + if isclass(obj): + obj.cm() # $ tt=Y.cm + else: + obj.foo() # $ tt=X.foo + +func(Y) # $ pt,tt=func +x = X() +func(x) # $ pt,tt=func + + +# While avoiding the two problems above is good, we have to be careful not to prune away +# _all_ type-tracking flow to the self parameter (since it's the local source node for +# all references to it within the function). So in the example below, we still want to +# be able to resolve that some_function is assigned to the attribute `func` on self. + + +class Example3(object): + def wat(self, f): + print("Example3.wat") + self.func = f + self.func() # $ pt,tt=some_function + + +def some_function(): + print("some_function") + + +ex3 = Example3() +ex3.wat(some_function) # $ pt,tt=Example3.wat diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/shadowing.py b/python/ql/test/experimental/library-tests/CallGraph/code/shadowing.py new file mode 100644 index 00000000000..ad91712c481 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/shadowing.py @@ -0,0 +1,22 @@ +def foo(n=0): + print("foo", n) + if n > 0: + foo(n-1) # $ pt,tt=foo + +foo(1) # $ pt,tt=foo + + +def test(): + def foo(): + print("test.foo") + + foo() # $ pt,tt=test.foo + + +class A(object): + def foo(self): + print("A.foo") + foo() # $ pt,tt=foo + +a = A() +a.foo() # $ pt,tt=A.foo diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/simple.py b/python/ql/test/experimental/library-tests/CallGraph/code/simple.py index ac07ace93b2..7d7d4865049 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/code/simple.py +++ b/python/ql/test/experimental/library-tests/CallGraph/code/simple.py @@ -12,9 +12,9 @@ def bar(): lam = lambda: print("lambda called") -foo() # $ pt=foo -indirect_foo() # $ pt=foo -bar() # $ pt=bar -lam() # $ pt=lambda[simple.py:12:7] +foo() # $ pt,tt=foo +indirect_foo() # $ pt,tt=foo +bar() # $ pt,tt=bar +lam() # $ pt,tt=lambda[simple.py:12:7] # python -m trace --trackcalls simple.py diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/through_content.py b/python/ql/test/experimental/library-tests/CallGraph/code/through_content.py new file mode 100644 index 00000000000..f449c4bd6da --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/through_content.py @@ -0,0 +1,6 @@ +def my_func(): + print("my_func") + +funcs = [my_func] +for f in funcs: + f() # $ MISSING: tt=my_func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/tuple_function_return.py b/python/ql/test/experimental/library-tests/CallGraph/code/tuple_function_return.py new file mode 100644 index 00000000000..f87b1aa23e8 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/tuple_function_return.py @@ -0,0 +1,15 @@ +def func(): + print("func()") + +def return_func(): + return func + +def return_func_in_tuple(): + return (func, 42) + +f1 = return_func() # $ pt,tt=return_func +f1() # $ pt,tt=func + + +f2, _ = return_func_in_tuple() # $ pt,tt=return_func_in_tuple +f2() # $ pt=func MISSING: tt diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/type_tracking_limitation.py b/python/ql/test/experimental/library-tests/CallGraph/code/type_tracking_limitation.py new file mode 100644 index 00000000000..4831cf74291 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/type_tracking_limitation.py @@ -0,0 +1,8 @@ +def return_arg(arg): + return arg + +def my_func(): + print("my_func") + +x = return_arg(my_func) # $ pt,tt=return_arg +x() # $ pt=my_func MISSING: tt=my_func diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/underscore_prefix_func_name.py b/python/ql/test/experimental/library-tests/CallGraph/code/underscore_prefix_func_name.py index fb3f5fc45a8..0331dbb30c4 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/code/underscore_prefix_func_name.py +++ b/python/ql/test/experimental/library-tests/CallGraph/code/underscore_prefix_func_name.py @@ -11,14 +11,14 @@ def some_function(): def _ignored(): print('_ignored') - some_function() + some_function() # $ tt=some_function def _works_since_called(): print('_works_since_called') - some_function() # $ pt=some_function + some_function() # $ pt,tt=some_function def works_even_though_not_called(): - some_function() # $ pt=some_function + some_function() # $ pt,tt=some_function globals()['_ignored']() -_works_since_called() # $ pt=_works_since_called +_works_since_called() # $ pt,tt=_works_since_called diff --git a/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected new file mode 100644 index 00000000000..410b626ffff --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected @@ -0,0 +1,24 @@ +uniqueEnclosingCallable +uniqueType +uniqueNodeLocation +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +readStepIsLocal +storeStepIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +argHasPostUpdate +postWithInFlow +viableImplInCallContextTooLarge +uniqueParameterNodeAtPosition +uniqueParameterNodePosition +uniqueContentApprox diff --git a/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.ql b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.ql new file mode 100644 index 00000000000..3dda6701a83 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.ql @@ -0,0 +1,2 @@ +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/TarSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/TarSlip.expected rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/TarSlip.qlref b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/TarSlip.qlref rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/TarSlipImprov.py b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/TarSlipImprov.py rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.qlref b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.qlref rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/zipslip_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/zipslip_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/zipslip_good.py b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-022/zipslip_good.py rename to python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected new file mode 100644 index 00000000000..3875da4e143 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected @@ -0,0 +1,2 @@ +missingAnnotationOnSink +failures diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql new file mode 100644 index 00000000000..f02f8529c96 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql @@ -0,0 +1,3 @@ +import python +import experimental.dataflow.TestUtil.DataflowQueryTest +import experimental.Security.UnsafeUnpackQuery diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected new file mode 100644 index 00000000000..94bd7276631 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected @@ -0,0 +1,83 @@ +edges +| UnsafeUnpack.py:0:0:0:0 | ModuleVariableNode for UnsafeUnpack.request | UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | +| UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | +| UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | UnsafeUnpack.py:0:0:0:0 | ModuleVariableNode for UnsafeUnpack.request | +| UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | +| UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | +| UnsafeUnpack.py:47:20:47:34 | ControlFlowNode for compressed_file | UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:51:19:51:36 | ControlFlowNode for Attribute() | UnsafeUnpack.py:52:23:52:37 | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:65:19:65:31 | ControlFlowNode for Attribute | UnsafeUnpack.py:66:23:66:37 | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute | UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath | +| UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath | +| UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript | +| UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript | UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | +| UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path | +| UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | +| UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute | UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path | +| UnsafeUnpack.py:140:23:140:35 | ControlFlowNode for Attribute | UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar | +| UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | UnsafeUnpack.py:163:23:163:28 | SSA variable member | +| UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript | +| UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript | UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | +| UnsafeUnpack.py:163:23:163:28 | SSA variable member | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | +| UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute | UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() | +| UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute | +nodes +| UnsafeUnpack.py:0:0:0:0 | ModuleVariableNode for UnsafeUnpack.request | semmle.label | ModuleVariableNode for UnsafeUnpack.request | +| UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath | +| UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | semmle.label | ControlFlowNode for local_ziped_path | +| UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | semmle.label | ControlFlowNode for local_ziped_path | +| UnsafeUnpack.py:47:20:47:34 | ControlFlowNode for compressed_file | semmle.label | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file | semmle.label | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:51:19:51:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| UnsafeUnpack.py:52:23:52:37 | ControlFlowNode for compressed_file | semmle.label | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:65:19:65:31 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:66:23:66:37 | ControlFlowNode for compressed_file | semmle.label | ControlFlowNode for compressed_file | +| UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath | +| UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | semmle.label | SSA variable chunk | +| UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath | semmle.label | ControlFlowNode for savepath | +| UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path | +| UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | semmle.label | SSA variable ufile | +| UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path | semmle.label | ControlFlowNode for uploaded_file_path | +| UnsafeUnpack.py:140:23:140:35 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar | +| UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | semmle.label | SSA variable chunk | +| UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| UnsafeUnpack.py:163:23:163:28 | SSA variable member | semmle.label | SSA variable member | +| UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | semmle.label | ControlFlowNode for result | +| UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | semmle.label | ControlFlowNode for tmp | +| UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +subpaths +#select +| UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file | UnsafeUnpack.py:47:20:47:34 | ControlFlowNode for compressed_file | UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:52:23:52:37 | ControlFlowNode for compressed_file | UnsafeUnpack.py:51:19:51:36 | ControlFlowNode for Attribute() | UnsafeUnpack.py:52:23:52:37 | ControlFlowNode for compressed_file | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:66:23:66:37 | ControlFlowNode for compressed_file | UnsafeUnpack.py:65:19:65:31 | ControlFlowNode for Attribute | UnsafeUnpack.py:66:23:66:37 | ControlFlowNode for compressed_file | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath | UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath | UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path | UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path | UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar | UnsafeUnpack.py:140:23:140:35 | ControlFlowNode for Attribute | UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() | UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() | Unsafe extraction from a malicious tarball retrieved from a remote location. | +| UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute | UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute | Unsafe extraction from a malicious tarball retrieved from a remote location. | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.py b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.py new file mode 100644 index 00000000000..6b533462d23 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.py @@ -0,0 +1,201 @@ +import requests +import shutil +import os + +from flask import Flask, request +app = Flask(__name__) + +# Consider any RemoteFlowSource as a source +@app.route("/download_from_url") +def download_from_url(): + filename = request.args.get('filename', '') + if not filename: + response = requests.get(filename, stream=True) + + tarpath = "/tmp/tmp456/tarball.tar.gz" + with open(tarpath, "wb") as f: + f.write(response.raw.read()) + untarredpath = "/tmp/tmp123" + shutil.unpack_archive(tarpath, untarredpath) # $result=BAD + + +# A source catching an S3 filename download +# see boto3: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.download_file +import boto3 +import os + +remote_ziped_name = "remote_name.tar.gz" +base_dir = "/tmp/basedir" +local_ziped_path = os.path.join(base_dir, remote_ziped_name) +bucket_name = "mybucket" + +s3 = boto3.client('s3') +s3.download_file(bucket_name, remote_ziped_name, local_ziped_path) +shutil.unpack_archive(local_ziped_path, base_dir) # $result=BAD + + +# wget +# see wget: https://pypi.org/project/wget/ +import wget +import os + +url = "https://some.remote/location/remote_name.tar.xz" +compressed_file = "/tmp/basedir/local_name.tar.xz" +base_dir = "/tmp/basedir" + +# download(url, out, bar) contains out parameter +wget.download(url, compressed_file) +shutil.unpack_archive(compressed_file, base_dir) # $result=BAD + +# download(url) returns filename +compressed_file = wget.download(url) +shutil.unpack_archive(compressed_file, base_dir) # $result=BAD + + +# A source coming from a CLI argparse module +# see argparse: https://docs.python.org/3/library/argparse.html +import argparse + +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('integers', metavar='N', type=int, nargs='+', + help='an integer for the accumulator') +parser.add_argument('filename', help='filename to be provided') + +args = parser.parse_args() +compressed_file = args.filename +shutil.unpack_archive(compressed_file, base_dir) # $result=BAD + + +# A source coming from a CLI and downloaded +import argparse +import requests + +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('integers', metavar='N', type=int, nargs='+', + help='an integer for the accumulator') +parser.add_argument('filename', help='url to filename to be provided') + +args = parser.parse_args() +url_filename = args.filename + +response = requests.get(url_filename, stream=True) + +tarpath = "/tmp/tmp456/tarball.tar.gz" +with open(tarpath, "wb") as f: + f.write(response.raw.read()) + +shutil.unpack_archive(tarpath, base_dir) # $result=BAD + +# the django upload functionality +# see HttpRequest.FILES: https://docs.djangoproject.com/en/4.1/ref/request-response/#django.http.HttpRequest.FILES +from django.shortcuts import render +from django.core.files.storage import FileSystemStorage +import shutil + +def simple_upload(request): + + base_dir = "/tmp/baase_dir" + if request.method == 'POST': + # Read uploaded files by chunks of data + # see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks + savepath = os.path.join(base_dir, "tarball_compressed.tar.gz") + with open(savepath, 'wb+') as wfile: + for chunk in request.FILES["ufile1"].chunks(): + wfile.write(chunk) + shutil.unpack_archive(savepath, base_dir) # $result=BAD + + # Write in binary the uploaded tarball + myfile = request.FILES.get("ufile1") + file_path = os.path.join(base_dir, "tarball.tar") + with file_path.open('wb') as f: + f.write(myfile.read()) + shutil.unpack_archive(file_path, base_dir) # $result=BAD + + # Save uploaded files using FileSystemStorage Django API + # see FileSystemStorage: https://docs.djangoproject.com/en/4.1/ref/files/storage/#django.core.files.storage.FileSystemStorage + for ufile in request.FILES.getlist(): + fs = FileSystemStorage() + filename = fs.save(ufile.name, ufile) + uploaded_file_path = fs.path(filename) + shutil.unpack_archive(uploaded_file_path, base_dir) # $result=BAD + + return render(request, 'simple_upload.html') + + elif request.method == 'GET': + return render(request, 'simple_upload.html') + + +import shutil +import os +import tarfile +import tempfile +import argparse + +parser = argparse.ArgumentParser(description='Process some integers.') +parser.add_argument('integers', metavar='N', type=int, nargs='+', + help='an integer for the accumulator') +parser.add_argument('filename', help='filename to be provided') + +args = parser.parse_args() +unsafe_filename_tar = args.filename +with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar: + tar.extractall(path="/tmp/unpack/", members=tar) # $result=BAD +tar = tarfile.open(unsafe_filename_tar) + + +from django.shortcuts import render +from django.core.files.storage import FileSystemStorage +import shutil + +def simple_upload(request): + + base_dir = "/tmp/baase_dir" + if request.method == 'POST': + # Read uploaded files by chunks of data + # see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks + savepath = os.path.join(base_dir, "tarball_compressed.tar.gz") + with open(savepath, 'wb+') as wfile: + for chunk in request.FILES["ufile1"].chunks(): + wfile.write(chunk) + + tar = tarfile.open(savepath) + result = [] + for member in tar: + if member.issym(): + raise ValueError("But it is a symlink") + result.append(member) + tar.extractall(path=tempfile.mkdtemp(), members=result) # $result=BAD + tar.close() + + +response = requests.get(url_filename, stream=True) +tarpath = "/tmp/tmp456/tarball.tar.gz" +with open(tarpath, "wb") as f: + f.write(response.raw.read()) +target_dir = "/tmp/unpack" +tarfile.TarFile(tarpath, mode="r").extractall(path=target_dir) # $result=BAD + + +from pathlib import Path +import tempfile +import boto3 + +def default_session() -> boto3.Session: + _SESSION = None + if _SESSION is None: + _SESSION = boto3.Session() + return _SESSION + +cache = False +cache_dir = "/tmp/artifacts" +object_path = "/objects/obj1" +s3 = default_session().client("s3") +with tempfile.NamedTemporaryFile(suffix=".tar.gz") as tmp: + s3.download_fileobj(bucket_name, object_path, tmp) + tmp.seek(0) + if cache: + cache_dir.mkdir(exist_ok=True, parents=True) + target = cache_dir + else: + target = Path(tempfile.mkdtemp()) + shutil.unpack_archive(tmp.name, target) # $result=BAD \ No newline at end of file diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.qlref b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.qlref new file mode 100644 index 00000000000..90e5db651a0 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-022bis/UnsafeUnpack.ql \ No newline at end of file diff --git a/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.ql b/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.ql +++ b/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.expected b/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.expected index 5dcf739c068..0c2bd1b4ce0 100644 --- a/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.expected +++ b/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.expected @@ -5,11 +5,6 @@ | code/l_calls.py:12:1:12:20 | ControlFlowNode for ClassExpr | code/l_calls.py:25:16:25:16 | ControlFlowNode for a | | code/l_calls.py:33:5:33:23 | ControlFlowNode for FunctionExpr | code/l_calls.py:39:1:39:3 | ControlFlowNode for Attribute | | code/l_calls.py:48:5:48:30 | ControlFlowNode for FunctionExpr | code/l_calls.py:53:1:53:3 | ControlFlowNode for Attribute | -| code/q_super.py:10:18:10:21 | ControlFlowNode for self | code/q_super.py:4:22:4:25 | ControlFlowNode for self | -| code/q_super.py:26:14:26:17 | ControlFlowNode for self | code/q_super.py:22:32:22:35 | ControlFlowNode for self | -| code/q_super.py:31:14:31:17 | ControlFlowNode for self | code/q_super.py:22:32:22:35 | ControlFlowNode for self | -| code/q_super.py:37:14:37:17 | ControlFlowNode for self | code/q_super.py:22:32:22:35 | ControlFlowNode for self | -| code/q_super.py:37:14:37:17 | ControlFlowNode for self | code/q_super.py:27:32:27:35 | ControlFlowNode for self | | code/q_super.py:48:5:48:17 | ControlFlowNode for ClassExpr | code/q_super.py:51:25:51:29 | ControlFlowNode for Attribute | | code/q_super.py:63:5:63:17 | ControlFlowNode for ClassExpr | code/q_super.py:66:19:66:23 | ControlFlowNode for Attribute | | code/t_type.py:3:1:3:16 | ControlFlowNode for ClassExpr | code/t_type.py:6:1:6:9 | ControlFlowNode for type() | diff --git a/python/ql/test/library-tests/filters/tests/Filter.ql b/python/ql/test/library-tests/filters/tests/Filter.ql index 0528a318f77..967ed8d12f7 100644 --- a/python/ql/test/library-tests/filters/tests/Filter.ql +++ b/python/ql/test/library-tests/filters/tests/Filter.ql @@ -2,4 +2,5 @@ import python import semmle.python.filters.Tests from TestScope t +where exists(t.getLocation().getFile().getRelativePath()) select t diff --git a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected index dc055e4a08f..c56e9c8a3f6 100644 --- a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected +++ b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected @@ -5,13 +5,13 @@ edges | testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute name] | testapp/orm_security_tests.py:47:14:47:53 | ControlFlowNode for Attribute() [Attribute name] | | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:22:23:22:34 | ControlFlowNode for Attribute | | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:23:22:23:33 | ControlFlowNode for Attribute | -| testapp/orm_security_tests.py:22:9:22:14 | [post store] ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:23:9:23:14 | ControlFlowNode for person [Attribute name] | +| testapp/orm_security_tests.py:22:9:22:14 | [post] ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:23:9:23:14 | ControlFlowNode for person [Attribute name] | | testapp/orm_security_tests.py:22:23:22:34 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:22:23:22:42 | ControlFlowNode for Subscript | -| testapp/orm_security_tests.py:22:23:22:42 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:22:9:22:14 | [post store] ControlFlowNode for person [Attribute name] | +| testapp/orm_security_tests.py:22:23:22:42 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:22:9:22:14 | [post] ControlFlowNode for person [Attribute name] | | testapp/orm_security_tests.py:23:9:23:14 | ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute name] | -| testapp/orm_security_tests.py:23:9:23:14 | [post store] ControlFlowNode for person [Attribute age] | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute age] | +| testapp/orm_security_tests.py:23:9:23:14 | [post] ControlFlowNode for person [Attribute age] | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute age] | | testapp/orm_security_tests.py:23:22:23:33 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:23:22:23:40 | ControlFlowNode for Subscript | -| testapp/orm_security_tests.py:23:22:23:40 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:23:9:23:14 | [post store] ControlFlowNode for person [Attribute age] | +| testapp/orm_security_tests.py:23:22:23:40 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:23:9:23:14 | [post] ControlFlowNode for person [Attribute age] | | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute age] | testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute age] | | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute name] | | testapp/orm_security_tests.py:42:13:42:18 | SSA variable person [Attribute age] | testapp/orm_security_tests.py:43:62:43:67 | ControlFlowNode for person [Attribute age] | @@ -48,11 +48,11 @@ nodes | testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute age] | semmle.label | [orm-model] Class Person [Attribute age] | | testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute name] | semmle.label | [orm-model] Class Person [Attribute name] | | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| testapp/orm_security_tests.py:22:9:22:14 | [post store] ControlFlowNode for person [Attribute name] | semmle.label | [post store] ControlFlowNode for person [Attribute name] | +| testapp/orm_security_tests.py:22:9:22:14 | [post] ControlFlowNode for person [Attribute name] | semmle.label | [post] ControlFlowNode for person [Attribute name] | | testapp/orm_security_tests.py:22:23:22:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | testapp/orm_security_tests.py:22:23:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | testapp/orm_security_tests.py:23:9:23:14 | ControlFlowNode for person [Attribute name] | semmle.label | ControlFlowNode for person [Attribute name] | -| testapp/orm_security_tests.py:23:9:23:14 | [post store] ControlFlowNode for person [Attribute age] | semmle.label | [post store] ControlFlowNode for person [Attribute age] | +| testapp/orm_security_tests.py:23:9:23:14 | [post] ControlFlowNode for person [Attribute age] | semmle.label | [post] ControlFlowNode for person [Attribute age] | | testapp/orm_security_tests.py:23:22:23:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | testapp/orm_security_tests.py:23:22:23:40 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | testapp/orm_security_tests.py:28:9:28:14 | ControlFlowNode for person [Attribute age] | semmle.label | ControlFlowNode for person [Attribute age] | diff --git a/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.ql b/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.ql index 6743fa10d27..3dda6701a83 100644 --- a/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.ql +++ b/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.ql @@ -1 +1,2 @@ -import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency +import python +import experimental.dataflow.TestUtil.DataFlowConsistency diff --git a/python/ql/test/library-tests/frameworks/django-v2-v3/testproj/settings.py b/python/ql/test/library-tests/frameworks/django-v2-v3/testproj/settings.py index f376ae752d8..d88ce4c05e3 100644 --- a/python/ql/test/library-tests/frameworks/django-v2-v3/testproj/settings.py +++ b/python/ql/test/library-tests/frameworks/django-v2-v3/testproj/settings.py @@ -40,7 +40,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', ] -MIDDLEWARE = [ # $CsrfProtectionSetting=false +MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -48,7 +48,7 @@ MIDDLEWARE = [ # $CsrfProtectionSetting=false 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', -] +] # $CsrfProtectionSetting=false ROOT_URLCONF = 'testproj.urls' diff --git a/python/ql/test/library-tests/frameworks/flask/old_test.py b/python/ql/test/library-tests/frameworks/flask/old_test.py index d86c75019e5..556467fad9b 100644 --- a/python/ql/test/library-tests/frameworks/flask/old_test.py +++ b/python/ql/test/library-tests/frameworks/flask/old_test.py @@ -21,8 +21,8 @@ class MyView(MethodView): the_view = MyView.as_view('my_view') -app.add_url_rule('/the/', defaults={'user_id': None}, # $routeSetup="/the/" - view_func=the_view, methods=['GET',]) +app.add_url_rule('/the/', defaults={'user_id': None}, + view_func=the_view, methods=['GET',]) # $routeSetup="/the/" @app.route("/dangerous") # $routeSetup="/dangerous" def dangerous(): # $requestHandler diff --git a/python/ql/test/library-tests/frameworks/stdlib/test_hmac.py b/python/ql/test/library-tests/frameworks/stdlib/test_hmac.py new file mode 100644 index 00000000000..ff8b30329a7 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/stdlib/test_hmac.py @@ -0,0 +1,33 @@ +import hmac +import hashlib + +key = b"" + +hmac_obj = hmac.new(key, b"secret message", "sha256") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(hmac_obj.digest()) +print(hmac_obj.hexdigest()) + +hmac_obj = hmac.new(key, msg=b"secret message", digestmod="sha256") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(hmac_obj.hexdigest()) + + +hmac_obj = hmac.new(key, digestmod="sha256") +hmac_obj.update(b"secret") # $ CryptographicOperation CryptographicOperationInput=b"secret" CryptographicOperationAlgorithm=SHA256 +hmac_obj.update(msg=b" message") # $ CryptographicOperation CryptographicOperationInput=b" message" CryptographicOperationAlgorithm=SHA256 +print(hmac_obj.hexdigest()) + + +hmac_obj = hmac.new(key, b"secret message", hashlib.sha256) # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(hmac_obj.hexdigest()) + + +# like hmac.new +hmac_obj = hmac.HMAC(key, digestmod="sha256") +hmac_obj.update(b"secret message") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(hmac_obj.hexdigest()) + + +dig = hmac.digest(key, b"secret message", "sha256") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(dig) +dig = hmac.digest(key, msg=b"secret message", digest="sha256") # $ CryptographicOperation CryptographicOperationInput=b"secret message" CryptographicOperationAlgorithm=SHA256 +print(dig) diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected index 7438c415858..a346aef9d22 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected @@ -1 +1,4 @@ -| hmac.new [param 1] | 2 | 1 | +| hmac.new [keyword msg] | 1 | 1 | +| hmac.new [position 1] | 1 | 1 | +| unknown.lib.func [keyword kw] | 2 | 1 | +| unknown.lib.func [position 0] | 2 | 1 | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected index e024ef20cba..bb6ffaab366 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected @@ -1,12 +1,25 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:13:16:13:22 | ControlFlowNode for request | | test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:23:16:23:22 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:34:12:34:18 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:42:12:42:18 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:54:12:54:18 | ControlFlowNode for request | | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:5:26:5:32 | GSSA Variable request | | test.py:5:26:5:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:13:16:13:22 | ControlFlowNode for request | test.py:13:16:13:27 | ControlFlowNode for Attribute | | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data | | test.py:23:16:23:22 | ControlFlowNode for request | test.py:23:16:23:27 | ControlFlowNode for Attribute | | test.py:23:16:23:27 | ControlFlowNode for Attribute | test.py:25:44:25:47 | ControlFlowNode for data | +| test.py:34:12:34:18 | ControlFlowNode for request | test.py:34:12:34:23 | ControlFlowNode for Attribute | +| test.py:34:12:34:23 | ControlFlowNode for Attribute | test.py:35:10:35:13 | ControlFlowNode for data | +| test.py:34:12:34:23 | ControlFlowNode for Attribute | test.py:36:13:36:16 | ControlFlowNode for data | +| test.py:42:12:42:18 | ControlFlowNode for request | test.py:42:12:42:23 | ControlFlowNode for Attribute | +| test.py:42:12:42:23 | ControlFlowNode for Attribute | test.py:43:22:43:25 | ControlFlowNode for data | +| test.py:42:12:42:23 | ControlFlowNode for Attribute | test.py:44:25:44:28 | ControlFlowNode for data | +| test.py:47:17:47:19 | ControlFlowNode for arg | test.py:50:32:50:34 | ControlFlowNode for arg | +| test.py:54:12:54:18 | ControlFlowNode for request | test.py:54:12:54:23 | ControlFlowNode for Attribute | +| test.py:54:12:54:23 | ControlFlowNode for Attribute | test.py:55:17:55:20 | ControlFlowNode for data | +| test.py:55:17:55:20 | ControlFlowNode for data | test.py:47:17:47:19 | ControlFlowNode for arg | nodes | test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | | test.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | @@ -17,7 +30,24 @@ nodes | test.py:23:16:23:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:23:16:23:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:25:44:25:47 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:34:12:34:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:34:12:34:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:35:10:35:13 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:36:13:36:16 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:42:12:42:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:42:12:42:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:43:22:43:25 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:44:25:44:28 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:47:17:47:19 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg | +| test.py:50:32:50:34 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg | +| test.py:54:12:54:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| test.py:54:12:54:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:55:17:55:20 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | subpaths #select -| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | -| test.py:25:44:25:47 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:25:44:25:47 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [position 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:25:44:25:47 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:25:44:25:47 | ControlFlowNode for data | Call to hmac.new [keyword msg] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:35:10:35:13 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:35:10:35:13 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:36:13:36:16 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:36:13:36:16 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:43:22:43:25 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:43:22:43:25 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | +| test.py:44:25:44:28 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:44:25:44:28 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py index ca4191ded85..18b46298d8a 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py @@ -32,18 +32,28 @@ def hmac_example2(): def unknown_lib_1(): from unknown.lib import func data = request.args.get("data") - func(data) # TODO: currently not recognized - func(kw=data) # TODO: currently not recognized + func(data) + func(kw=data) @app.route("/unknown-lib-2") def unknown_lib_2(): import unknown.lib data = request.args.get("data") - unknown.lib.func(data) # TODO: currently not recognized - unknown.lib.func(kw=data) # TODO: currently not recognized + unknown.lib.func(data) + unknown.lib.func(kw=data) +def handle_this(arg, application = None): + if application: + # since application could be None, we could end up reporting `None.json.dumps` + application.json.dumps(arg) + +@app.route("/optional-arg") +def optional_arg(): + data = request.args.get("data") + handle_this(data) + if __name__ == "__main__": # http://127.0.0.1:5000/hmac-example?data=aGVsbG8gd29ybGQh app.run(debug=True) diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected index 4d92275ff36..a824d44adfa 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected @@ -49,6 +49,12 @@ edges | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:142:14:142:17 | ControlFlowNode for path | | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:152:18:152:21 | ControlFlowNode for path | +| pathlib_use.py:0:0:0:0 | ModuleVariableNode for pathlib_use.request | pathlib_use.py:12:16:12:22 | ControlFlowNode for request | +| pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | pathlib_use.py:3:26:3:32 | GSSA Variable request | +| pathlib_use.py:3:26:3:32 | GSSA Variable request | pathlib_use.py:0:0:0:0 | ModuleVariableNode for pathlib_use.request | +| pathlib_use.py:12:16:12:22 | ControlFlowNode for request | pathlib_use.py:12:16:12:27 | ControlFlowNode for Attribute | +| pathlib_use.py:12:16:12:27 | ControlFlowNode for Attribute | pathlib_use.py:14:5:14:5 | ControlFlowNode for p | +| pathlib_use.py:12:16:12:27 | ControlFlowNode for Attribute | pathlib_use.py:17:5:17:6 | ControlFlowNode for p2 | | test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:9:12:9:18 | ControlFlowNode for request | | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:3:26:3:32 | GSSA Variable request | | test.py:3:26:3:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | @@ -125,6 +131,13 @@ nodes | path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:152:18:152:21 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| pathlib_use.py:0:0:0:0 | ModuleVariableNode for pathlib_use.request | semmle.label | ModuleVariableNode for pathlib_use.request | +| pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| pathlib_use.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| pathlib_use.py:12:16:12:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| pathlib_use.py:12:16:12:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| pathlib_use.py:14:5:14:5 | ControlFlowNode for p | semmle.label | ControlFlowNode for p | +| pathlib_use.py:17:5:17:6 | ControlFlowNode for p2 | semmle.label | ControlFlowNode for p2 | | test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | | test.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | | test.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | @@ -164,6 +177,8 @@ subpaths | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| pathlib_use.py:14:5:14:5 | ControlFlowNode for p | pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | pathlib_use.py:14:5:14:5 | ControlFlowNode for p | This path depends on a $@. | pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| pathlib_use.py:17:5:17:6 | ControlFlowNode for p2 | pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | pathlib_use.py:17:5:17:6 | ControlFlowNode for p2 | This path depends on a $@. | pathlib_use.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | test.py:19:10:19:10 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | test.py:26:10:26:10 | ControlFlowNode for y | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | test.py:33:14:33:14 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/pathlib_use.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/pathlib_use.py new file mode 100644 index 00000000000..6f703f903dc --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/pathlib_use.py @@ -0,0 +1,17 @@ +import pathlib + +from flask import Flask, request +app = Flask(__name__) + + +STATIC_DIR = pathlib.Path("/server/static/") + + +@app.route("/pathlib_use") +def path_injection(): + filename = request.args.get('filename', '') + p = STATIC_DIR / filename + p.open() # $ result=BAD + + p2 = pathlib.Path(STATIC_DIR, filename) + p2.open() # $ result=BAD diff --git a/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected index 762d2599c2d..3bfb6fe4f88 100644 --- a/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected +++ b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected @@ -2,5 +2,6 @@ | test.py:8:1:8:20 | ControlFlowNode for Attribute() | Overly permissive mask in chmod sets file to world writable. | | test.py:9:1:9:21 | ControlFlowNode for Attribute() | Overly permissive mask in chmod sets file to world writable. | | test.py:11:1:11:21 | ControlFlowNode for Attribute() | Overly permissive mask in chmod sets file to group readable. | +| test.py:13:1:13:28 | ControlFlowNode for Attribute() | Overly permissive mask in chmod sets file to group writable. | | test.py:14:1:14:19 | ControlFlowNode for Attribute() | Overly permissive mask in chmod sets file to group writable. | | test.py:16:1:16:25 | ControlFlowNode for Attribute() | Overly permissive mask in open sets file to world readable. | diff --git a/ql/Cargo.lock b/ql/Cargo.lock index b0c217453ed..ff29ea1c323 100644 Binary files a/ql/Cargo.lock and b/ql/Cargo.lock differ diff --git a/ql/Cargo.toml b/ql/Cargo.toml index 7acbd36afa6..4bc60c3333d 100644 --- a/ql/Cargo.toml +++ b/ql/Cargo.toml @@ -4,4 +4,5 @@ members = [ "extractor", "generator", "node-types", + "buramu", ] diff --git a/ql/autobuilder/src/main.rs b/ql/autobuilder/src/main.rs index df47cc33184..0d9605c4c1d 100644 --- a/ql/autobuilder/src/main.rs +++ b/ql/autobuilder/src/main.rs @@ -18,8 +18,12 @@ fn main() -> std::io::Result<()> { .arg("--include-extension=.ql") .arg("--include-extension=.qll") .arg("--include-extension=.dbscheme") + .arg("--include-extension=.json") + .arg("--include-extension=.jsonc") + .arg("--include-extension=.jsonl") .arg("--include=**/qlpack.yml") - .arg("--size-limit=5m") + .arg("--include=deprecated.blame") + .arg("--size-limit=10m") .arg("--language=ql") .arg("--working-dir=.") .arg(db); diff --git a/ql/buramu/Cargo.toml b/ql/buramu/Cargo.toml new file mode 100644 index 00000000000..8e09c6c1395 --- /dev/null +++ b/ql/buramu/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "buramu" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4.0" +chrono = "0.4.23" +rayon = "1.5.0" +regex = "1.7.1" diff --git a/ql/buramu/README.md b/ql/buramu/README.md new file mode 100644 index 00000000000..0c2bcb7ed3c --- /dev/null +++ b/ql/buramu/README.md @@ -0,0 +1,22 @@ +Gathers up `git blame` information for all lines with `deprecated` annotations in QL files in the +codebase. + +## Usage + +From within the root of the `codeql` repo (having first run the `create-extractor-pack.sh` script): +``` + ./ql/target/release/buramu > deprecated.blame +``` + +## Output +The contents of the `deprecated.blame` file will look something like this: +``` +today: 2023-02-17 +file: cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll + last_modified: 2022-11-25 124 167 173 184 188 329 358 400 415 546 553 584 593 +file: go/ql/lib/semmle/go/security/FlowSources.qll + last_modified: 2022-12-19 33 +file: python/ql/src/experimental/semmle/python/Concepts.qll + last_modified: 2022-08-18 172 202 + last_modified: 2022-03-11 94 110 129 145 177 206 225 241 258 272 289 303 454 485 529 570 +``` diff --git a/ql/buramu/src/main.rs b/ql/buramu/src/main.rs new file mode 100644 index 00000000000..f91ba8352ef --- /dev/null +++ b/ql/buramu/src/main.rs @@ -0,0 +1,108 @@ +use lazy_static::lazy_static; +use rayon::prelude::*; +use regex::Regex; +use std::collections::HashMap; +use std::{io::BufRead, process::Command}; + +// A map from filenames to lists of line numbers (for just the lines with deprecations) +type FileDeprecations = HashMap>; + +fn get_filename_and_lineno(line: &str) -> (String, String) { + let mut parts = line.splitn(3, ':'); + let file = parts.next().unwrap().to_string(); + let lineno = parts.next().unwrap().to_string(); + (file, lineno) +} + +#[test] +fn test_get_filename_and_lineno() { + let line = "path/to/file.ql:61:deprecated class Foo = Bar;"; + let (file, lineno) = get_filename_and_lineno(line); + assert_eq!(file, "path/to/file.ql"); + assert_eq!(lineno, "61"); +} + +fn get_files_with_deprecations() -> FileDeprecations { + let output = Command::new("git") + .args(&[ + "grep", + "-n", + "-E", + "^[^*]*deprecated", // skip lines that have a `*` before `deprecated`, as they are probably comments + "--", + "*.ql", + "*.qll", + ]) + .output() + .expect("failed to execute process"); + let mut file_deprecations: FileDeprecations = HashMap::new(); + for line in output.stdout.lines() { + let (file, lineno) = get_filename_and_lineno(&line.unwrap()); + file_deprecations + .entry(file) + .or_insert_with(Vec::new) + .push(lineno); + } + file_deprecations +} + +struct LastModifiedLine { + date: String, + lineno: String, +} +type LastModifiedMap = HashMap>; + +fn get_blame_dates_for_filedeprecation(file: &str, linenos: &[String]) -> LastModifiedMap { + let mut command = Command::new("git"); + command.arg("blame"); + for lineno in linenos { + command.arg("-L").arg(format!("{},{}", lineno, lineno)); + } + command.arg(file); + let output = command.output().expect("failed to execute process"); + let mut blame_dates = HashMap::new(); + for line in output.stdout.lines() { + let line = line.unwrap(); + let LastModifiedLine { date, lineno } = get_last_modified(&line); + blame_dates + .entry(date) + .or_insert_with(Vec::new) + .push(lineno); + } + blame_dates +} + +lazy_static! { + static ref BLAME_RE: Regex = + Regex::new("(\\d{4}-\\d{2}-\\d{2}).*[+-]\\d{4}\\s+(\\d+)\\)").unwrap(); +} + +fn get_last_modified(line: &str) -> LastModifiedLine { + let caps = BLAME_RE.captures(line).unwrap(); + let date = caps.get(1).unwrap().as_str().into(); + let lineno = caps.get(2).unwrap().as_str().into(); + LastModifiedLine { date, lineno } +} + +#[test] +fn test_get_date_and_lineno() { + let line = "cc7a9ef97a78 (john doe 2022-08-24 12:59:07 +0200 61) deprecated class Foo = Bar;"; + let LastModifiedLine { date, lineno } = get_last_modified(line); + assert_eq!(date, "2022-08-24"); + assert_eq!(lineno, "61"); +} + +fn main() { + let filedeprecations = get_files_with_deprecations(); + let filedeprecations: Vec<(String, Vec)> = filedeprecations.into_iter().collect(); + println!("today: {}", chrono::Local::now().format("%Y-%m-%d")); + let deprecations = filedeprecations + .par_iter() + .map(|(file, linenos)| (file, get_blame_dates_for_filedeprecation(file, linenos))); + deprecations.for_each(|(file, linenos_and_dates)| { + println!("file: {}", file); + for (date, linenos) in linenos_and_dates.iter() { + println!(" last_modified: {} {}", date, linenos.join(" ")); + } + }); +} diff --git a/ql/buramu/tree-sitter-blame/Cargo.toml b/ql/buramu/tree-sitter-blame/Cargo.toml new file mode 100644 index 00000000000..95dc42c3e74 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "tree-sitter-blame" +description = "blame grammar for the tree-sitter parsing library" +version = "0.0.1" +keywords = ["incremental", "parsing", "blame"] +categories = ["parsing", "text-editors"] +repository = "https://github.com/tree-sitter/tree-sitter-blame" +edition = "2018" +license = "MIT" + +build = "bindings/rust/build.rs" +include = [ + "bindings/rust/*", + "grammar.js", + "queries/*", + "src/*", +] + +[lib] +path = "bindings/rust/lib.rs" + +[dependencies] +tree-sitter = "~0.20.3" + +[build-dependencies] +cc = "1.0" diff --git a/ql/buramu/tree-sitter-blame/binding.gyp b/ql/buramu/tree-sitter-blame/binding.gyp new file mode 100644 index 00000000000..d6cc395af07 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/binding.gyp @@ -0,0 +1,19 @@ +{ + "targets": [ + { + "target_name": "tree_sitter_blame_binding", + "include_dirs": [ + " +#include "nan.h" + +using namespace v8; + +extern "C" TSLanguage * tree_sitter_blame(); + +namespace { + +NAN_METHOD(New) {} + +void Init(Local exports, Local module) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("Language").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); + Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); + Nan::SetInternalFieldPointer(instance, 0, tree_sitter_blame()); + + Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("blame").ToLocalChecked()); + Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); +} + +NODE_MODULE(tree_sitter_blame_binding, Init) + +} // namespace diff --git a/ql/buramu/tree-sitter-blame/bindings/node/index.js b/ql/buramu/tree-sitter-blame/bindings/node/index.js new file mode 100644 index 00000000000..23af3bb321c --- /dev/null +++ b/ql/buramu/tree-sitter-blame/bindings/node/index.js @@ -0,0 +1,19 @@ +try { + module.exports = require("../../build/Release/tree_sitter_blame_binding"); +} catch (error1) { + if (error1.code !== 'MODULE_NOT_FOUND') { + throw error1; + } + try { + module.exports = require("../../build/Debug/tree_sitter_blame_binding"); + } catch (error2) { + if (error2.code !== 'MODULE_NOT_FOUND') { + throw error2; + } + throw error1 + } +} + +try { + module.exports.nodeTypeInfo = require("../../src/node-types.json"); +} catch (_) {} diff --git a/ql/buramu/tree-sitter-blame/bindings/rust/build.rs b/ql/buramu/tree-sitter-blame/bindings/rust/build.rs new file mode 100644 index 00000000000..c6061f09953 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/bindings/rust/build.rs @@ -0,0 +1,40 @@ +fn main() { + let src_dir = std::path::Path::new("src"); + + let mut c_config = cc::Build::new(); + c_config.include(&src_dir); + c_config + .flag_if_supported("-Wno-unused-parameter") + .flag_if_supported("-Wno-unused-but-set-variable") + .flag_if_supported("-Wno-trigraphs"); + let parser_path = src_dir.join("parser.c"); + c_config.file(&parser_path); + + // If your language uses an external scanner written in C, + // then include this block of code: + + /* + let scanner_path = src_dir.join("scanner.c"); + c_config.file(&scanner_path); + println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); + */ + + c_config.compile("parser"); + println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); + + // If your language uses an external scanner written in C++, + // then include this block of code: + + /* + let mut cpp_config = cc::Build::new(); + cpp_config.cpp(true); + cpp_config.include(&src_dir); + cpp_config + .flag_if_supported("-Wno-unused-parameter") + .flag_if_supported("-Wno-unused-but-set-variable"); + let scanner_path = src_dir.join("scanner.cc"); + cpp_config.file(&scanner_path); + cpp_config.compile("scanner"); + println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); + */ +} diff --git a/ql/buramu/tree-sitter-blame/bindings/rust/lib.rs b/ql/buramu/tree-sitter-blame/bindings/rust/lib.rs new file mode 100644 index 00000000000..268243b164f --- /dev/null +++ b/ql/buramu/tree-sitter-blame/bindings/rust/lib.rs @@ -0,0 +1,52 @@ +//! This crate provides blame language support for the [tree-sitter][] parsing library. +//! +//! Typically, you will use the [language][language func] function to add this language to a +//! tree-sitter [Parser][], and then use the parser to parse some code: +//! +//! ``` +//! let code = ""; +//! let mut parser = tree_sitter::Parser::new(); +//! parser.set_language(tree_sitter_blame::language()).expect("Error loading blame grammar"); +//! let tree = parser.parse(code, None).unwrap(); +//! ``` +//! +//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html +//! [language func]: fn.language.html +//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html +//! [tree-sitter]: https://tree-sitter.github.io/ + +use tree_sitter::Language; + +extern "C" { + fn tree_sitter_blame() -> Language; +} + +/// Get the tree-sitter [Language][] for this grammar. +/// +/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html +pub fn language() -> Language { + unsafe { tree_sitter_blame() } +} + +/// The content of the [`node-types.json`][] file for this grammar. +/// +/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types +pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json"); + +// Uncomment these to include any queries that this grammar contains + +// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm"); +// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm"); +// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm"); +// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm"); + +#[cfg(test)] +mod tests { + #[test] + fn test_can_load_grammar() { + let mut parser = tree_sitter::Parser::new(); + parser + .set_language(super::language()) + .expect("Error loading blame language"); + } +} diff --git a/ql/buramu/tree-sitter-blame/dep.out b/ql/buramu/tree-sitter-blame/dep.out new file mode 100644 index 00000000000..4e87db56088 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/dep.out @@ -0,0 +1,20160 @@ +(blame_info [0, 0] - [2442, 0] + today: (date [0, 7] - [0, 17]) + (file_entry [1, 0] - [19, 25] + file_name: (filename [1, 6] - [1, 76]) + (blame_entry [2, 4] - [2, 25] + line: (number [2, 11] - [2, 14]) + date: (date [2, 15] - [2, 25])) + (blame_entry [3, 4] - [3, 25] + line: (number [3, 11] - [3, 14]) + date: (date [3, 15] - [3, 25])) + (blame_entry [4, 4] - [4, 25] + line: (number [4, 11] - [4, 14]) + date: (date [4, 15] - [4, 25])) + (blame_entry [5, 4] - [5, 25] + line: (number [5, 11] - [5, 14]) + date: (date [5, 15] - [5, 25])) + (blame_entry [6, 4] - [6, 25] + line: (number [6, 11] - [6, 14]) + date: (date [6, 15] - [6, 25])) + (blame_entry [7, 4] - [7, 25] + line: (number [7, 11] - [7, 14]) + date: (date [7, 15] - [7, 25])) + (blame_entry [8, 4] - [8, 25] + line: (number [8, 11] - [8, 14]) + date: (date [8, 15] - [8, 25])) + (blame_entry [9, 4] - [9, 25] + line: (number [9, 11] - [9, 14]) + date: (date [9, 15] - [9, 25])) + (blame_entry [10, 4] - [10, 25] + line: (number [10, 11] - [10, 14]) + date: (date [10, 15] - [10, 25])) + (blame_entry [11, 4] - [11, 25] + line: (number [11, 11] - [11, 14]) + date: (date [11, 15] - [11, 25])) + (blame_entry [12, 4] - [12, 25] + line: (number [12, 11] - [12, 14]) + date: (date [12, 15] - [12, 25])) + (blame_entry [13, 4] - [13, 25] + line: (number [13, 11] - [13, 14]) + date: (date [13, 15] - [13, 25])) + (blame_entry [14, 4] - [14, 25] + line: (number [14, 11] - [14, 14]) + date: (date [14, 15] - [14, 25])) + (blame_entry [15, 4] - [15, 25] + line: (number [15, 11] - [15, 14]) + date: (date [15, 15] - [15, 25])) + (blame_entry [16, 4] - [16, 25] + line: (number [16, 11] - [16, 14]) + date: (date [16, 15] - [16, 25])) + (blame_entry [17, 4] - [17, 25] + line: (number [17, 11] - [17, 14]) + date: (date [17, 15] - [17, 25])) + (blame_entry [18, 4] - [18, 25] + line: (number [18, 11] - [18, 14]) + date: (date [18, 15] - [18, 25])) + (blame_entry [19, 4] - [19, 25] + line: (number [19, 11] - [19, 14]) + date: (date [19, 15] - [19, 25]))) + (file_entry [20, 0] - [21, 24] + file_name: (filename [20, 6] - [20, 58]) + (blame_entry [21, 4] - [21, 24] + line: (number [21, 11] - [21, 13]) + date: (date [21, 14] - [21, 24]))) + (file_entry [22, 0] - [25, 24] + file_name: (filename [22, 6] - [22, 43]) + (blame_entry [23, 4] - [23, 24] + line: (number [23, 11] - [23, 13]) + date: (date [23, 14] - [23, 24])) + (blame_entry [24, 4] - [24, 24] + line: (number [24, 11] - [24, 13]) + date: (date [24, 14] - [24, 24])) + (blame_entry [25, 4] - [25, 24] + line: (number [25, 11] - [25, 13]) + date: (date [25, 14] - [25, 24]))) + (file_entry [26, 0] - [27, 24] + file_name: (filename [26, 6] - [26, 64]) + (blame_entry [27, 4] - [27, 24] + line: (number [27, 11] - [27, 13]) + date: (date [27, 14] - [27, 24]))) + (file_entry [28, 0] - [29, 24] + file_name: (filename [28, 6] - [28, 57]) + (blame_entry [29, 4] - [29, 24] + line: (number [29, 11] - [29, 13]) + date: (date [29, 14] - [29, 24]))) + (file_entry [30, 0] - [35, 25] + file_name: (filename [30, 6] - [30, 42]) + (blame_entry [31, 4] - [31, 24] + line: (number [31, 11] - [31, 13]) + date: (date [31, 14] - [31, 24])) + (blame_entry [32, 4] - [32, 24] + line: (number [32, 11] - [32, 13]) + date: (date [32, 14] - [32, 24])) + (blame_entry [33, 4] - [33, 25] + line: (number [33, 11] - [33, 14]) + date: (date [33, 15] - [33, 25])) + (blame_entry [34, 4] - [34, 25] + line: (number [34, 11] - [34, 14]) + date: (date [34, 15] - [34, 25])) + (blame_entry [35, 4] - [35, 25] + line: (number [35, 11] - [35, 14]) + date: (date [35, 15] - [35, 25]))) + (file_entry [36, 0] - [38, 24] + file_name: (filename [36, 6] - [36, 67]) + (blame_entry [37, 4] - [37, 24] + line: (number [37, 11] - [37, 13]) + date: (date [37, 14] - [37, 24])) + (blame_entry [38, 4] - [38, 24] + line: (number [38, 11] - [38, 13]) + date: (date [38, 14] - [38, 24]))) + (file_entry [39, 0] - [41, 25] + file_name: (filename [39, 6] - [39, 57]) + (blame_entry [40, 4] - [40, 25] + line: (number [40, 11] - [40, 14]) + date: (date [40, 15] - [40, 25])) + (blame_entry [41, 4] - [41, 25] + line: (number [41, 11] - [41, 14]) + date: (date [41, 15] - [41, 25]))) + (file_entry [42, 0] - [43, 23] + file_name: (filename [42, 6] - [42, 68]) + (blame_entry [43, 4] - [43, 23] + line: (number [43, 11] - [43, 12]) + date: (date [43, 13] - [43, 23]))) + (file_entry [44, 0] - [45, 24] + file_name: (filename [44, 6] - [44, 73]) + (blame_entry [45, 4] - [45, 24] + line: (number [45, 11] - [45, 13]) + date: (date [45, 14] - [45, 24]))) + (file_entry [46, 0] - [47, 24] + file_name: (filename [46, 6] - [46, 59]) + (blame_entry [47, 4] - [47, 24] + line: (number [47, 11] - [47, 13]) + date: (date [47, 14] - [47, 24]))) + (file_entry [48, 0] - [49, 24] + file_name: (filename [48, 6] - [48, 81]) + (blame_entry [49, 4] - [49, 24] + line: (number [49, 11] - [49, 13]) + date: (date [49, 14] - [49, 24]))) + (file_entry [50, 0] - [52, 25] + file_name: (filename [50, 6] - [50, 78]) + (blame_entry [51, 4] - [51, 25] + line: (number [51, 11] - [51, 14]) + date: (date [51, 15] - [51, 25])) + (blame_entry [52, 4] - [52, 25] + line: (number [52, 11] - [52, 14]) + date: (date [52, 15] - [52, 25]))) + (file_entry [53, 0] - [56, 25] + file_name: (filename [53, 6] - [53, 79]) + (blame_entry [54, 4] - [54, 24] + line: (number [54, 11] - [54, 13]) + date: (date [54, 14] - [54, 24])) + (blame_entry [55, 4] - [55, 24] + line: (number [55, 11] - [55, 13]) + date: (date [55, 14] - [55, 24])) + (blame_entry [56, 4] - [56, 25] + line: (number [56, 11] - [56, 14]) + date: (date [56, 15] - [56, 25]))) + (file_entry [57, 0] - [59, 25] + file_name: (filename [57, 6] - [57, 76]) + (blame_entry [58, 4] - [58, 24] + line: (number [58, 11] - [58, 13]) + date: (date [58, 14] - [58, 24])) + (blame_entry [59, 4] - [59, 25] + line: (number [59, 11] - [59, 14]) + date: (date [59, 15] - [59, 25]))) + (file_entry [60, 0] - [65, 25] + file_name: (filename [60, 6] - [60, 82]) + (blame_entry [61, 4] - [61, 25] + line: (number [61, 11] - [61, 14]) + date: (date [61, 15] - [61, 25])) + (blame_entry [62, 4] - [62, 25] + line: (number [62, 11] - [62, 14]) + date: (date [62, 15] - [62, 25])) + (blame_entry [63, 4] - [63, 25] + line: (number [63, 11] - [63, 14]) + date: (date [63, 15] - [63, 25])) + (blame_entry [64, 4] - [64, 25] + line: (number [64, 11] - [64, 14]) + date: (date [64, 15] - [64, 25])) + (blame_entry [65, 4] - [65, 25] + line: (number [65, 11] - [65, 14]) + date: (date [65, 15] - [65, 25]))) + (file_entry [66, 0] - [68, 25] + file_name: (filename [66, 6] - [66, 120]) + (blame_entry [67, 4] - [67, 24] + line: (number [67, 11] - [67, 13]) + date: (date [67, 14] - [67, 24])) + (blame_entry [68, 4] - [68, 25] + line: (number [68, 11] - [68, 14]) + date: (date [68, 15] - [68, 25]))) + (file_entry [69, 0] - [94, 25] + file_name: (filename [69, 6] - [69, 45]) + (blame_entry [70, 4] - [70, 23] + line: (number [70, 11] - [70, 12]) + date: (date [70, 13] - [70, 23])) + (blame_entry [71, 4] - [71, 24] + line: (number [71, 11] - [71, 13]) + date: (date [71, 14] - [71, 24])) + (blame_entry [72, 4] - [72, 24] + line: (number [72, 11] - [72, 13]) + date: (date [72, 14] - [72, 24])) + (blame_entry [73, 4] - [73, 24] + line: (number [73, 11] - [73, 13]) + date: (date [73, 14] - [73, 24])) + (blame_entry [74, 4] - [74, 24] + line: (number [74, 11] - [74, 13]) + date: (date [74, 14] - [74, 24])) + (blame_entry [75, 4] - [75, 24] + line: (number [75, 11] - [75, 13]) + date: (date [75, 14] - [75, 24])) + (blame_entry [76, 4] - [76, 25] + line: (number [76, 11] - [76, 14]) + date: (date [76, 15] - [76, 25])) + (blame_entry [77, 4] - [77, 25] + line: (number [77, 11] - [77, 14]) + date: (date [77, 15] - [77, 25])) + (blame_entry [78, 4] - [78, 25] + line: (number [78, 11] - [78, 14]) + date: (date [78, 15] - [78, 25])) + (blame_entry [79, 4] - [79, 25] + line: (number [79, 11] - [79, 14]) + date: (date [79, 15] - [79, 25])) + (blame_entry [80, 4] - [80, 25] + line: (number [80, 11] - [80, 14]) + date: (date [80, 15] - [80, 25])) + (blame_entry [81, 4] - [81, 25] + line: (number [81, 11] - [81, 14]) + date: (date [81, 15] - [81, 25])) + (blame_entry [82, 4] - [82, 25] + line: (number [82, 11] - [82, 14]) + date: (date [82, 15] - [82, 25])) + (blame_entry [83, 4] - [83, 25] + line: (number [83, 11] - [83, 14]) + date: (date [83, 15] - [83, 25])) + (blame_entry [84, 4] - [84, 25] + line: (number [84, 11] - [84, 14]) + date: (date [84, 15] - [84, 25])) + (blame_entry [85, 4] - [85, 25] + line: (number [85, 11] - [85, 14]) + date: (date [85, 15] - [85, 25])) + (blame_entry [86, 4] - [86, 25] + line: (number [86, 11] - [86, 14]) + date: (date [86, 15] - [86, 25])) + (blame_entry [87, 4] - [87, 25] + line: (number [87, 11] - [87, 14]) + date: (date [87, 15] - [87, 25])) + (blame_entry [88, 4] - [88, 25] + line: (number [88, 11] - [88, 14]) + date: (date [88, 15] - [88, 25])) + (blame_entry [89, 4] - [89, 25] + line: (number [89, 11] - [89, 14]) + date: (date [89, 15] - [89, 25])) + (blame_entry [90, 4] - [90, 25] + line: (number [90, 11] - [90, 14]) + date: (date [90, 15] - [90, 25])) + (blame_entry [91, 4] - [91, 25] + line: (number [91, 11] - [91, 14]) + date: (date [91, 15] - [91, 25])) + (blame_entry [92, 4] - [92, 25] + line: (number [92, 11] - [92, 14]) + date: (date [92, 15] - [92, 25])) + (blame_entry [93, 4] - [93, 25] + line: (number [93, 11] - [93, 14]) + date: (date [93, 15] - [93, 25])) + (blame_entry [94, 4] - [94, 25] + line: (number [94, 11] - [94, 14]) + date: (date [94, 15] - [94, 25]))) + (file_entry [95, 0] - [98, 25] + file_name: (filename [95, 6] - [95, 41]) + (blame_entry [96, 4] - [96, 24] + line: (number [96, 11] - [96, 13]) + date: (date [96, 14] - [96, 24])) + (blame_entry [97, 4] - [97, 25] + line: (number [97, 11] - [97, 14]) + date: (date [97, 15] - [97, 25])) + (blame_entry [98, 4] - [98, 25] + line: (number [98, 11] - [98, 14]) + date: (date [98, 15] - [98, 25]))) + (file_entry [99, 0] - [102, 26] + file_name: (filename [99, 6] - [99, 61]) + (blame_entry [100, 4] - [100, 26] + line: (number [100, 11] - [100, 15]) + date: (date [100, 16] - [100, 26])) + (blame_entry [101, 4] - [101, 26] + line: (number [101, 11] - [101, 15]) + date: (date [101, 16] - [101, 26])) + (blame_entry [102, 4] - [102, 26] + line: (number [102, 11] - [102, 15]) + date: (date [102, 16] - [102, 26]))) + (file_entry [103, 0] - [104, 25] + file_name: (filename [103, 6] - [103, 57]) + (blame_entry [104, 4] - [104, 25] + line: (number [104, 11] - [104, 14]) + date: (date [104, 15] - [104, 25]))) + (file_entry [105, 0] - [108, 24] + file_name: (filename [105, 6] - [105, 80]) + (blame_entry [106, 4] - [106, 24] + line: (number [106, 11] - [106, 13]) + date: (date [106, 14] - [106, 24])) + (blame_entry [107, 4] - [107, 24] + line: (number [107, 11] - [107, 13]) + date: (date [107, 14] - [107, 24])) + (blame_entry [108, 4] - [108, 24] + line: (number [108, 11] - [108, 13]) + date: (date [108, 14] - [108, 24]))) + (file_entry [109, 0] - [114, 25] + file_name: (filename [109, 6] - [109, 49]) + (blame_entry [110, 4] - [110, 25] + line: (number [110, 11] - [110, 14]) + date: (date [110, 15] - [110, 25])) + (blame_entry [111, 4] - [111, 25] + line: (number [111, 11] - [111, 14]) + date: (date [111, 15] - [111, 25])) + (blame_entry [112, 4] - [112, 25] + line: (number [112, 11] - [112, 14]) + date: (date [112, 15] - [112, 25])) + (blame_entry [113, 4] - [113, 25] + line: (number [113, 11] - [113, 14]) + date: (date [113, 15] - [113, 25])) + (blame_entry [114, 4] - [114, 25] + line: (number [114, 11] - [114, 14]) + date: (date [114, 15] - [114, 25]))) + (file_entry [115, 0] - [120, 26] + file_name: (filename [115, 6] - [115, 93]) + (blame_entry [116, 4] - [116, 25] + line: (number [116, 11] - [116, 14]) + date: (date [116, 15] - [116, 25])) + (blame_entry [117, 4] - [117, 25] + line: (number [117, 11] - [117, 14]) + date: (date [117, 15] - [117, 25])) + (blame_entry [118, 4] - [118, 26] + line: (number [118, 11] - [118, 15]) + date: (date [118, 16] - [118, 26])) + (blame_entry [119, 4] - [119, 26] + line: (number [119, 11] - [119, 15]) + date: (date [119, 16] - [119, 26])) + (blame_entry [120, 4] - [120, 26] + line: (number [120, 11] - [120, 15]) + date: (date [120, 16] - [120, 26]))) + (file_entry [121, 0] - [125, 25] + file_name: (filename [121, 6] - [121, 73]) + (blame_entry [122, 4] - [122, 24] + line: (number [122, 11] - [122, 13]) + date: (date [122, 14] - [122, 24])) + (blame_entry [123, 4] - [123, 25] + line: (number [123, 11] - [123, 14]) + date: (date [123, 15] - [123, 25])) + (blame_entry [124, 4] - [124, 25] + line: (number [124, 11] - [124, 14]) + date: (date [124, 15] - [124, 25])) + (blame_entry [125, 4] - [125, 25] + line: (number [125, 11] - [125, 14]) + date: (date [125, 15] - [125, 25]))) + (file_entry [126, 0] - [127, 24] + file_name: (filename [126, 6] - [126, 50]) + (blame_entry [127, 4] - [127, 24] + line: (number [127, 11] - [127, 13]) + date: (date [127, 14] - [127, 24]))) + (file_entry [128, 0] - [136, 24] + file_name: (filename [128, 6] - [128, 57]) + (blame_entry [129, 4] - [129, 24] + line: (number [129, 11] - [129, 13]) + date: (date [129, 14] - [129, 24])) + (blame_entry [130, 4] - [130, 24] + line: (number [130, 11] - [130, 13]) + date: (date [130, 14] - [130, 24])) + (blame_entry [131, 4] - [131, 24] + line: (number [131, 11] - [131, 13]) + date: (date [131, 14] - [131, 24])) + (blame_entry [132, 4] - [132, 24] + line: (number [132, 11] - [132, 13]) + date: (date [132, 14] - [132, 24])) + (blame_entry [133, 4] - [133, 24] + line: (number [133, 11] - [133, 13]) + date: (date [133, 14] - [133, 24])) + (blame_entry [134, 4] - [134, 24] + line: (number [134, 11] - [134, 13]) + date: (date [134, 14] - [134, 24])) + (blame_entry [135, 4] - [135, 24] + line: (number [135, 11] - [135, 13]) + date: (date [135, 14] - [135, 24])) + (blame_entry [136, 4] - [136, 24] + line: (number [136, 11] - [136, 13]) + date: (date [136, 14] - [136, 24]))) + (file_entry [137, 0] - [138, 25] + file_name: (filename [137, 6] - [137, 71]) + (blame_entry [138, 4] - [138, 25] + line: (number [138, 11] - [138, 14]) + date: (date [138, 15] - [138, 25]))) + (file_entry [139, 0] - [149, 25] + file_name: (filename [139, 6] - [139, 48]) + (blame_entry [140, 4] - [140, 24] + line: (number [140, 11] - [140, 13]) + date: (date [140, 14] - [140, 24])) + (blame_entry [141, 4] - [141, 24] + line: (number [141, 11] - [141, 13]) + date: (date [141, 14] - [141, 24])) + (blame_entry [142, 4] - [142, 24] + line: (number [142, 11] - [142, 13]) + date: (date [142, 14] - [142, 24])) + (blame_entry [143, 4] - [143, 24] + line: (number [143, 11] - [143, 13]) + date: (date [143, 14] - [143, 24])) + (blame_entry [144, 4] - [144, 24] + line: (number [144, 11] - [144, 13]) + date: (date [144, 14] - [144, 24])) + (blame_entry [145, 4] - [145, 24] + line: (number [145, 11] - [145, 13]) + date: (date [145, 14] - [145, 24])) + (blame_entry [146, 4] - [146, 24] + line: (number [146, 11] - [146, 13]) + date: (date [146, 14] - [146, 24])) + (blame_entry [147, 4] - [147, 24] + line: (number [147, 11] - [147, 13]) + date: (date [147, 14] - [147, 24])) + (blame_entry [148, 4] - [148, 24] + line: (number [148, 11] - [148, 13]) + date: (date [148, 14] - [148, 24])) + (blame_entry [149, 4] - [149, 25] + line: (number [149, 11] - [149, 14]) + date: (date [149, 15] - [149, 25]))) + (file_entry [150, 0] - [166, 25] + file_name: (filename [150, 6] - [150, 67]) + (blame_entry [151, 4] - [151, 24] + line: (number [151, 11] - [151, 13]) + date: (date [151, 14] - [151, 24])) + (blame_entry [152, 4] - [152, 24] + line: (number [152, 11] - [152, 13]) + date: (date [152, 14] - [152, 24])) + (blame_entry [153, 4] - [153, 24] + line: (number [153, 11] - [153, 13]) + date: (date [153, 14] - [153, 24])) + (blame_entry [154, 4] - [154, 24] + line: (number [154, 11] - [154, 13]) + date: (date [154, 14] - [154, 24])) + (blame_entry [155, 4] - [155, 24] + line: (number [155, 11] - [155, 13]) + date: (date [155, 14] - [155, 24])) + (blame_entry [156, 4] - [156, 24] + line: (number [156, 11] - [156, 13]) + date: (date [156, 14] - [156, 24])) + (blame_entry [157, 4] - [157, 24] + line: (number [157, 11] - [157, 13]) + date: (date [157, 14] - [157, 24])) + (blame_entry [158, 4] - [158, 24] + line: (number [158, 11] - [158, 13]) + date: (date [158, 14] - [158, 24])) + (blame_entry [159, 4] - [159, 24] + line: (number [159, 11] - [159, 13]) + date: (date [159, 14] - [159, 24])) + (blame_entry [160, 4] - [160, 24] + line: (number [160, 11] - [160, 13]) + date: (date [160, 14] - [160, 24])) + (blame_entry [161, 4] - [161, 24] + line: (number [161, 11] - [161, 13]) + date: (date [161, 14] - [161, 24])) + (blame_entry [162, 4] - [162, 25] + line: (number [162, 11] - [162, 14]) + date: (date [162, 15] - [162, 25])) + (blame_entry [163, 4] - [163, 25] + line: (number [163, 11] - [163, 14]) + date: (date [163, 15] - [163, 25])) + (blame_entry [164, 4] - [164, 25] + line: (number [164, 11] - [164, 14]) + date: (date [164, 15] - [164, 25])) + (blame_entry [165, 4] - [165, 25] + line: (number [165, 11] - [165, 14]) + date: (date [165, 15] - [165, 25])) + (blame_entry [166, 4] - [166, 25] + line: (number [166, 11] - [166, 14]) + date: (date [166, 15] - [166, 25]))) + (file_entry [167, 0] - [169, 26] + file_name: (filename [167, 6] - [167, 46]) + (blame_entry [168, 4] - [168, 25] + line: (number [168, 11] - [168, 14]) + date: (date [168, 15] - [168, 25])) + (blame_entry [169, 4] - [169, 26] + line: (number [169, 11] - [169, 15]) + date: (date [169, 16] - [169, 26]))) + (file_entry [170, 0] - [174, 25] + file_name: (filename [170, 6] - [170, 70]) + (blame_entry [171, 4] - [171, 24] + line: (number [171, 11] - [171, 13]) + date: (date [171, 14] - [171, 24])) + (blame_entry [172, 4] - [172, 25] + line: (number [172, 11] - [172, 14]) + date: (date [172, 15] - [172, 25])) + (blame_entry [173, 4] - [173, 25] + line: (number [173, 11] - [173, 14]) + date: (date [173, 15] - [173, 25])) + (blame_entry [174, 4] - [174, 25] + line: (number [174, 11] - [174, 14]) + date: (date [174, 15] - [174, 25]))) + (file_entry [175, 0] - [176, 23] + file_name: (filename [175, 6] - [175, 52]) + (blame_entry [176, 4] - [176, 23] + line: (number [176, 11] - [176, 12]) + date: (date [176, 13] - [176, 23]))) + (file_entry [177, 0] - [179, 24] + file_name: (filename [177, 6] - [177, 61]) + (blame_entry [178, 4] - [178, 24] + line: (number [178, 11] - [178, 13]) + date: (date [178, 14] - [178, 24])) + (blame_entry [179, 4] - [179, 24] + line: (number [179, 11] - [179, 13]) + date: (date [179, 14] - [179, 24]))) + (file_entry [180, 0] - [182, 25] + file_name: (filename [180, 6] - [180, 59]) + (blame_entry [181, 4] - [181, 24] + line: (number [181, 11] - [181, 13]) + date: (date [181, 14] - [181, 24])) + (blame_entry [182, 4] - [182, 25] + line: (number [182, 11] - [182, 14]) + date: (date [182, 15] - [182, 25]))) + (file_entry [183, 0] - [184, 23] + file_name: (filename [183, 6] - [183, 64]) + (blame_entry [184, 4] - [184, 23] + line: (number [184, 11] - [184, 12]) + date: (date [184, 13] - [184, 23]))) + (file_entry [185, 0] - [198, 25] + file_name: (filename [185, 6] - [185, 46]) + (blame_entry [186, 4] - [186, 24] + line: (number [186, 11] - [186, 13]) + date: (date [186, 14] - [186, 24])) + (blame_entry [187, 4] - [187, 24] + line: (number [187, 11] - [187, 13]) + date: (date [187, 14] - [187, 24])) + (blame_entry [188, 4] - [188, 25] + line: (number [188, 11] - [188, 14]) + date: (date [188, 15] - [188, 25])) + (blame_entry [189, 4] - [189, 25] + line: (number [189, 11] - [189, 14]) + date: (date [189, 15] - [189, 25])) + (blame_entry [190, 4] - [190, 25] + line: (number [190, 11] - [190, 14]) + date: (date [190, 15] - [190, 25])) + (blame_entry [191, 4] - [191, 25] + line: (number [191, 11] - [191, 14]) + date: (date [191, 15] - [191, 25])) + (blame_entry [192, 4] - [192, 25] + line: (number [192, 11] - [192, 14]) + date: (date [192, 15] - [192, 25])) + (blame_entry [193, 4] - [193, 25] + line: (number [193, 11] - [193, 14]) + date: (date [193, 15] - [193, 25])) + (blame_entry [194, 4] - [194, 25] + line: (number [194, 11] - [194, 14]) + date: (date [194, 15] - [194, 25])) + (blame_entry [195, 4] - [195, 25] + line: (number [195, 11] - [195, 14]) + date: (date [195, 15] - [195, 25])) + (blame_entry [196, 4] - [196, 25] + line: (number [196, 11] - [196, 14]) + date: (date [196, 15] - [196, 25])) + (blame_entry [197, 4] - [197, 25] + line: (number [197, 11] - [197, 14]) + date: (date [197, 15] - [197, 25])) + (blame_entry [198, 4] - [198, 25] + line: (number [198, 11] - [198, 14]) + date: (date [198, 15] - [198, 25]))) + (file_entry [199, 0] - [201, 25] + file_name: (filename [199, 6] - [199, 59]) + (blame_entry [200, 4] - [200, 25] + line: (number [200, 11] - [200, 14]) + date: (date [200, 15] - [200, 25])) + (blame_entry [201, 4] - [201, 25] + line: (number [201, 11] - [201, 14]) + date: (date [201, 15] - [201, 25]))) + (file_entry [202, 0] - [205, 24] + file_name: (filename [202, 6] - [202, 56]) + (blame_entry [203, 4] - [203, 24] + line: (number [203, 11] - [203, 13]) + date: (date [203, 14] - [203, 24])) + (blame_entry [204, 4] - [204, 24] + line: (number [204, 11] - [204, 13]) + date: (date [204, 14] - [204, 24])) + (blame_entry [205, 4] - [205, 24] + line: (number [205, 11] - [205, 13]) + date: (date [205, 14] - [205, 24]))) + (file_entry [206, 0] - [210, 25] + file_name: (filename [206, 6] - [206, 80]) + (blame_entry [207, 4] - [207, 25] + line: (number [207, 11] - [207, 14]) + date: (date [207, 15] - [207, 25])) + (blame_entry [208, 4] - [208, 25] + line: (number [208, 11] - [208, 14]) + date: (date [208, 15] - [208, 25])) + (blame_entry [209, 4] - [209, 25] + line: (number [209, 11] - [209, 14]) + date: (date [209, 15] - [209, 25])) + (blame_entry [210, 4] - [210, 25] + line: (number [210, 11] - [210, 14]) + date: (date [210, 15] - [210, 25]))) + (file_entry [211, 0] - [212, 24] + file_name: (filename [211, 6] - [211, 82]) + (blame_entry [212, 4] - [212, 24] + line: (number [212, 11] - [212, 13]) + date: (date [212, 14] - [212, 24]))) + (file_entry [213, 0] - [214, 23] + file_name: (filename [213, 6] - [213, 76]) + (blame_entry [214, 4] - [214, 23] + line: (number [214, 11] - [214, 12]) + date: (date [214, 13] - [214, 23]))) + (file_entry [215, 0] - [216, 25] + file_name: (filename [215, 6] - [215, 64]) + (blame_entry [216, 4] - [216, 25] + line: (number [216, 11] - [216, 14]) + date: (date [216, 15] - [216, 25]))) + (file_entry [217, 0] - [221, 25] + file_name: (filename [217, 6] - [217, 50]) + (blame_entry [218, 4] - [218, 25] + line: (number [218, 11] - [218, 14]) + date: (date [218, 15] - [218, 25])) + (blame_entry [219, 4] - [219, 25] + line: (number [219, 11] - [219, 14]) + date: (date [219, 15] - [219, 25])) + (blame_entry [220, 4] - [220, 25] + line: (number [220, 11] - [220, 14]) + date: (date [220, 15] - [220, 25])) + (blame_entry [221, 4] - [221, 25] + line: (number [221, 11] - [221, 14]) + date: (date [221, 15] - [221, 25]))) + (file_entry [222, 0] - [223, 24] + file_name: (filename [222, 6] - [222, 85]) + (blame_entry [223, 4] - [223, 24] + line: (number [223, 11] - [223, 13]) + date: (date [223, 14] - [223, 24]))) + (file_entry [224, 0] - [228, 25] + file_name: (filename [224, 6] - [224, 83]) + (blame_entry [225, 4] - [225, 24] + line: (number [225, 11] - [225, 13]) + date: (date [225, 14] - [225, 24])) + (blame_entry [226, 4] - [226, 25] + line: (number [226, 11] - [226, 14]) + date: (date [226, 15] - [226, 25])) + (blame_entry [227, 4] - [227, 25] + line: (number [227, 11] - [227, 14]) + date: (date [227, 15] - [227, 25])) + (blame_entry [228, 4] - [228, 25] + line: (number [228, 11] - [228, 14]) + date: (date [228, 15] - [228, 25]))) + (file_entry [229, 0] - [230, 24] + file_name: (filename [229, 6] - [229, 67]) + (blame_entry [230, 4] - [230, 24] + line: (number [230, 11] - [230, 13]) + date: (date [230, 14] - [230, 24]))) + (file_entry [231, 0] - [246, 25] + file_name: (filename [231, 6] - [231, 64]) + (blame_entry [232, 4] - [232, 25] + line: (number [232, 11] - [232, 14]) + date: (date [232, 15] - [232, 25])) + (blame_entry [233, 4] - [233, 25] + line: (number [233, 11] - [233, 14]) + date: (date [233, 15] - [233, 25])) + (blame_entry [234, 4] - [234, 25] + line: (number [234, 11] - [234, 14]) + date: (date [234, 15] - [234, 25])) + (blame_entry [235, 4] - [235, 25] + line: (number [235, 11] - [235, 14]) + date: (date [235, 15] - [235, 25])) + (blame_entry [236, 4] - [236, 25] + line: (number [236, 11] - [236, 14]) + date: (date [236, 15] - [236, 25])) + (blame_entry [237, 4] - [237, 25] + line: (number [237, 11] - [237, 14]) + date: (date [237, 15] - [237, 25])) + (blame_entry [238, 4] - [238, 25] + line: (number [238, 11] - [238, 14]) + date: (date [238, 15] - [238, 25])) + (blame_entry [239, 4] - [239, 25] + line: (number [239, 11] - [239, 14]) + date: (date [239, 15] - [239, 25])) + (blame_entry [240, 4] - [240, 25] + line: (number [240, 11] - [240, 14]) + date: (date [240, 15] - [240, 25])) + (blame_entry [241, 4] - [241, 25] + line: (number [241, 11] - [241, 14]) + date: (date [241, 15] - [241, 25])) + (blame_entry [242, 4] - [242, 25] + line: (number [242, 11] - [242, 14]) + date: (date [242, 15] - [242, 25])) + (blame_entry [243, 4] - [243, 25] + line: (number [243, 11] - [243, 14]) + date: (date [243, 15] - [243, 25])) + (blame_entry [244, 4] - [244, 25] + line: (number [244, 11] - [244, 14]) + date: (date [244, 15] - [244, 25])) + (blame_entry [245, 4] - [245, 25] + line: (number [245, 11] - [245, 14]) + date: (date [245, 15] - [245, 25])) + (blame_entry [246, 4] - [246, 25] + line: (number [246, 11] - [246, 14]) + date: (date [246, 15] - [246, 25]))) + (file_entry [247, 0] - [249, 25] + file_name: (filename [247, 6] - [247, 65]) + (blame_entry [248, 4] - [248, 25] + line: (number [248, 11] - [248, 14]) + date: (date [248, 15] - [248, 25])) + (blame_entry [249, 4] - [249, 25] + line: (number [249, 11] - [249, 14]) + date: (date [249, 15] - [249, 25]))) + (file_entry [250, 0] - [251, 24] + file_name: (filename [250, 6] - [250, 75]) + (blame_entry [251, 4] - [251, 24] + line: (number [251, 11] - [251, 13]) + date: (date [251, 14] - [251, 24]))) + (file_entry [252, 0] - [253, 24] + file_name: (filename [252, 6] - [252, 63]) + (blame_entry [253, 4] - [253, 24] + line: (number [253, 11] - [253, 13]) + date: (date [253, 14] - [253, 24]))) + (file_entry [254, 0] - [255, 24] + file_name: (filename [254, 6] - [254, 84]) + (blame_entry [255, 4] - [255, 24] + line: (number [255, 11] - [255, 13]) + date: (date [255, 14] - [255, 24]))) + (file_entry [256, 0] - [257, 24] + file_name: (filename [256, 6] - [256, 61]) + (blame_entry [257, 4] - [257, 24] + line: (number [257, 11] - [257, 13]) + date: (date [257, 14] - [257, 24]))) + (file_entry [258, 0] - [260, 25] + file_name: (filename [258, 6] - [258, 75]) + (blame_entry [259, 4] - [259, 25] + line: (number [259, 11] - [259, 14]) + date: (date [259, 15] - [259, 25])) + (blame_entry [260, 4] - [260, 25] + line: (number [260, 11] - [260, 14]) + date: (date [260, 15] - [260, 25]))) + (file_entry [261, 0] - [270, 25] + file_name: (filename [261, 6] - [261, 60]) + (blame_entry [262, 4] - [262, 23] + line: (number [262, 11] - [262, 12]) + date: (date [262, 13] - [262, 23])) + (blame_entry [263, 4] - [263, 24] + line: (number [263, 11] - [263, 13]) + date: (date [263, 14] - [263, 24])) + (blame_entry [264, 4] - [264, 24] + line: (number [264, 11] - [264, 13]) + date: (date [264, 14] - [264, 24])) + (blame_entry [265, 4] - [265, 24] + line: (number [265, 11] - [265, 13]) + date: (date [265, 14] - [265, 24])) + (blame_entry [266, 4] - [266, 24] + line: (number [266, 11] - [266, 13]) + date: (date [266, 14] - [266, 24])) + (blame_entry [267, 4] - [267, 24] + line: (number [267, 11] - [267, 13]) + date: (date [267, 14] - [267, 24])) + (blame_entry [268, 4] - [268, 25] + line: (number [268, 11] - [268, 14]) + date: (date [268, 15] - [268, 25])) + (blame_entry [269, 4] - [269, 25] + line: (number [269, 11] - [269, 14]) + date: (date [269, 15] - [269, 25])) + (blame_entry [270, 4] - [270, 25] + line: (number [270, 11] - [270, 14]) + date: (date [270, 15] - [270, 25]))) + (file_entry [271, 0] - [272, 24] + file_name: (filename [271, 6] - [271, 61]) + (blame_entry [272, 4] - [272, 24] + line: (number [272, 11] - [272, 13]) + date: (date [272, 14] - [272, 24]))) + (file_entry [273, 0] - [277, 24] + file_name: (filename [273, 6] - [273, 60]) + (blame_entry [274, 4] - [274, 24] + line: (number [274, 11] - [274, 13]) + date: (date [274, 14] - [274, 24])) + (blame_entry [275, 4] - [275, 24] + line: (number [275, 11] - [275, 13]) + date: (date [275, 14] - [275, 24])) + (blame_entry [276, 4] - [276, 24] + line: (number [276, 11] - [276, 13]) + date: (date [276, 14] - [276, 24])) + (blame_entry [277, 4] - [277, 24] + line: (number [277, 11] - [277, 13]) + date: (date [277, 14] - [277, 24]))) + (file_entry [278, 0] - [279, 24] + file_name: (filename [278, 6] - [278, 79]) + (blame_entry [279, 4] - [279, 24] + line: (number [279, 11] - [279, 13]) + date: (date [279, 14] - [279, 24]))) + (file_entry [280, 0] - [282, 25] + file_name: (filename [280, 6] - [280, 80]) + (blame_entry [281, 4] - [281, 25] + line: (number [281, 11] - [281, 14]) + date: (date [281, 15] - [281, 25])) + (blame_entry [282, 4] - [282, 25] + line: (number [282, 11] - [282, 14]) + date: (date [282, 15] - [282, 25]))) + (file_entry [283, 0] - [284, 23] + file_name: (filename [283, 6] - [283, 68]) + (blame_entry [284, 4] - [284, 23] + line: (number [284, 11] - [284, 12]) + date: (date [284, 13] - [284, 23]))) + (file_entry [285, 0] - [287, 24] + file_name: (filename [285, 6] - [285, 68]) + (blame_entry [286, 4] - [286, 23] + line: (number [286, 11] - [286, 12]) + date: (date [286, 13] - [286, 23])) + (blame_entry [287, 4] - [287, 24] + line: (number [287, 11] - [287, 13]) + date: (date [287, 14] - [287, 24]))) + (file_entry [288, 0] - [290, 24] + file_name: (filename [288, 6] - [288, 74]) + (blame_entry [289, 4] - [289, 23] + line: (number [289, 11] - [289, 12]) + date: (date [289, 13] - [289, 23])) + (blame_entry [290, 4] - [290, 24] + line: (number [290, 11] - [290, 13]) + date: (date [290, 14] - [290, 24]))) + (file_entry [291, 0] - [295, 25] + file_name: (filename [291, 6] - [291, 42]) + (blame_entry [292, 4] - [292, 25] + line: (number [292, 11] - [292, 14]) + date: (date [292, 15] - [292, 25])) + (blame_entry [293, 4] - [293, 25] + line: (number [293, 11] - [293, 14]) + date: (date [293, 15] - [293, 25])) + (blame_entry [294, 4] - [294, 25] + line: (number [294, 11] - [294, 14]) + date: (date [294, 15] - [294, 25])) + (blame_entry [295, 4] - [295, 25] + line: (number [295, 11] - [295, 14]) + date: (date [295, 15] - [295, 25]))) + (file_entry [296, 0] - [297, 24] + file_name: (filename [296, 6] - [296, 53]) + (blame_entry [297, 4] - [297, 24] + line: (number [297, 11] - [297, 13]) + date: (date [297, 14] - [297, 24]))) + (file_entry [298, 0] - [303, 25] + file_name: (filename [298, 6] - [298, 49]) + (blame_entry [299, 4] - [299, 24] + line: (number [299, 11] - [299, 13]) + date: (date [299, 14] - [299, 24])) + (blame_entry [300, 4] - [300, 24] + line: (number [300, 11] - [300, 13]) + date: (date [300, 14] - [300, 24])) + (blame_entry [301, 4] - [301, 24] + line: (number [301, 11] - [301, 13]) + date: (date [301, 14] - [301, 24])) + (blame_entry [302, 4] - [302, 25] + line: (number [302, 11] - [302, 14]) + date: (date [302, 15] - [302, 25])) + (blame_entry [303, 4] - [303, 25] + line: (number [303, 11] - [303, 14]) + date: (date [303, 15] - [303, 25]))) + (file_entry [304, 0] - [307, 25] + file_name: (filename [304, 6] - [304, 60]) + (blame_entry [305, 4] - [305, 24] + line: (number [305, 11] - [305, 13]) + date: (date [305, 14] - [305, 24])) + (blame_entry [306, 4] - [306, 24] + line: (number [306, 11] - [306, 13]) + date: (date [306, 14] - [306, 24])) + (blame_entry [307, 4] - [307, 25] + line: (number [307, 11] - [307, 14]) + date: (date [307, 15] - [307, 25]))) + (file_entry [308, 0] - [309, 25] + file_name: (filename [308, 6] - [308, 58]) + (blame_entry [309, 4] - [309, 25] + line: (number [309, 11] - [309, 14]) + date: (date [309, 15] - [309, 25]))) + (file_entry [310, 0] - [313, 24] + file_name: (filename [310, 6] - [310, 63]) + (blame_entry [311, 4] - [311, 23] + line: (number [311, 11] - [311, 12]) + date: (date [311, 13] - [311, 23])) + (blame_entry [312, 4] - [312, 23] + line: (number [312, 11] - [312, 12]) + date: (date [312, 13] - [312, 23])) + (blame_entry [313, 4] - [313, 24] + line: (number [313, 11] - [313, 13]) + date: (date [313, 14] - [313, 24]))) + (file_entry [314, 0] - [318, 25] + file_name: (filename [314, 6] - [314, 45]) + (blame_entry [315, 4] - [315, 24] + line: (number [315, 11] - [315, 13]) + date: (date [315, 14] - [315, 24])) + (blame_entry [316, 4] - [316, 24] + line: (number [316, 11] - [316, 13]) + date: (date [316, 14] - [316, 24])) + (blame_entry [317, 4] - [317, 24] + line: (number [317, 11] - [317, 13]) + date: (date [317, 14] - [317, 24])) + (blame_entry [318, 4] - [318, 25] + line: (number [318, 11] - [318, 14]) + date: (date [318, 15] - [318, 25]))) + (file_entry [319, 0] - [320, 23] + file_name: (filename [319, 6] - [319, 64]) + (blame_entry [320, 4] - [320, 23] + line: (number [320, 11] - [320, 12]) + date: (date [320, 13] - [320, 23]))) + (file_entry [321, 0] - [322, 24] + file_name: (filename [321, 6] - [321, 67]) + (blame_entry [322, 4] - [322, 24] + line: (number [322, 11] - [322, 13]) + date: (date [322, 14] - [322, 24]))) + (file_entry [323, 0] - [324, 24] + file_name: (filename [323, 6] - [323, 73]) + (blame_entry [324, 4] - [324, 24] + line: (number [324, 11] - [324, 13]) + date: (date [324, 14] - [324, 24]))) + (file_entry [325, 0] - [328, 25] + file_name: (filename [325, 6] - [325, 94]) + (blame_entry [326, 4] - [326, 24] + line: (number [326, 11] - [326, 13]) + date: (date [326, 14] - [326, 24])) + (blame_entry [327, 4] - [327, 25] + line: (number [327, 11] - [327, 14]) + date: (date [327, 15] - [327, 25])) + (blame_entry [328, 4] - [328, 25] + line: (number [328, 11] - [328, 14]) + date: (date [328, 15] - [328, 25]))) + (file_entry [329, 0] - [331, 26] + file_name: (filename [329, 6] - [329, 63]) + (blame_entry [330, 4] - [330, 25] + line: (number [330, 11] - [330, 14]) + date: (date [330, 15] - [330, 25])) + (blame_entry [331, 4] - [331, 26] + line: (number [331, 11] - [331, 15]) + date: (date [331, 16] - [331, 26]))) + (file_entry [332, 0] - [336, 24] + file_name: (filename [332, 6] - [332, 43]) + (blame_entry [333, 4] - [333, 24] + line: (number [333, 11] - [333, 13]) + date: (date [333, 14] - [333, 24])) + (blame_entry [334, 4] - [334, 24] + line: (number [334, 11] - [334, 13]) + date: (date [334, 14] - [334, 24])) + (blame_entry [335, 4] - [335, 24] + line: (number [335, 11] - [335, 13]) + date: (date [335, 14] - [335, 24])) + (blame_entry [336, 4] - [336, 24] + line: (number [336, 11] - [336, 13]) + date: (date [336, 14] - [336, 24]))) + (file_entry [337, 0] - [339, 24] + file_name: (filename [337, 6] - [337, 54]) + (blame_entry [338, 4] - [338, 24] + line: (number [338, 11] - [338, 13]) + date: (date [338, 14] - [338, 24])) + (blame_entry [339, 4] - [339, 24] + line: (number [339, 11] - [339, 13]) + date: (date [339, 14] - [339, 24]))) + (file_entry [340, 0] - [343, 25] + file_name: (filename [340, 6] - [340, 110]) + (blame_entry [341, 4] - [341, 24] + line: (number [341, 11] - [341, 13]) + date: (date [341, 14] - [341, 24])) + (blame_entry [342, 4] - [342, 24] + line: (number [342, 11] - [342, 13]) + date: (date [342, 14] - [342, 24])) + (blame_entry [343, 4] - [343, 25] + line: (number [343, 11] - [343, 14]) + date: (date [343, 15] - [343, 25]))) + (file_entry [344, 0] - [346, 25] + file_name: (filename [344, 6] - [344, 80]) + (blame_entry [345, 4] - [345, 25] + line: (number [345, 11] - [345, 14]) + date: (date [345, 15] - [345, 25])) + (blame_entry [346, 4] - [346, 25] + line: (number [346, 11] - [346, 14]) + date: (date [346, 15] - [346, 25]))) + (file_entry [347, 0] - [348, 24] + file_name: (filename [347, 6] - [347, 51]) + (blame_entry [348, 4] - [348, 24] + line: (number [348, 11] - [348, 13]) + date: (date [348, 14] - [348, 24]))) + (file_entry [349, 0] - [350, 24] + file_name: (filename [349, 6] - [349, 48]) + (blame_entry [350, 4] - [350, 24] + line: (number [350, 11] - [350, 13]) + date: (date [350, 14] - [350, 24]))) + (file_entry [351, 0] - [357, 25] + file_name: (filename [351, 6] - [351, 78]) + (blame_entry [352, 4] - [352, 24] + line: (number [352, 11] - [352, 13]) + date: (date [352, 14] - [352, 24])) + (blame_entry [353, 4] - [353, 24] + line: (number [353, 11] - [353, 13]) + date: (date [353, 14] - [353, 24])) + (blame_entry [354, 4] - [354, 24] + line: (number [354, 11] - [354, 13]) + date: (date [354, 14] - [354, 24])) + (blame_entry [355, 4] - [355, 25] + line: (number [355, 11] - [355, 14]) + date: (date [355, 15] - [355, 25])) + (blame_entry [356, 4] - [356, 25] + line: (number [356, 11] - [356, 14]) + date: (date [356, 15] - [356, 25])) + (blame_entry [357, 4] - [357, 25] + line: (number [357, 11] - [357, 14]) + date: (date [357, 15] - [357, 25]))) + (file_entry [358, 0] - [359, 24] + file_name: (filename [358, 6] - [358, 81]) + (blame_entry [359, 4] - [359, 24] + line: (number [359, 11] - [359, 13]) + date: (date [359, 14] - [359, 24]))) + (file_entry [360, 0] - [361, 23] + file_name: (filename [360, 6] - [360, 71]) + (blame_entry [361, 4] - [361, 23] + line: (number [361, 11] - [361, 12]) + date: (date [361, 13] - [361, 23]))) + (file_entry [362, 0] - [363, 24] + file_name: (filename [362, 6] - [362, 81]) + (blame_entry [363, 4] - [363, 24] + line: (number [363, 11] - [363, 13]) + date: (date [363, 14] - [363, 24]))) + (file_entry [364, 0] - [367, 25] + file_name: (filename [364, 6] - [364, 67]) + (blame_entry [365, 4] - [365, 24] + line: (number [365, 11] - [365, 13]) + date: (date [365, 14] - [365, 24])) + (blame_entry [366, 4] - [366, 25] + line: (number [366, 11] - [366, 14]) + date: (date [366, 15] - [366, 25])) + (blame_entry [367, 4] - [367, 25] + line: (number [367, 11] - [367, 14]) + date: (date [367, 15] - [367, 25]))) + (file_entry [368, 0] - [369, 24] + file_name: (filename [368, 6] - [368, 43]) + (blame_entry [369, 4] - [369, 24] + line: (number [369, 11] - [369, 13]) + date: (date [369, 14] - [369, 24]))) + (file_entry [370, 0] - [371, 23] + file_name: (filename [370, 6] - [370, 68]) + (blame_entry [371, 4] - [371, 23] + line: (number [371, 11] - [371, 12]) + date: (date [371, 13] - [371, 23]))) + (file_entry [372, 0] - [378, 24] + file_name: (filename [372, 6] - [372, 47]) + (blame_entry [373, 4] - [373, 23] + line: (number [373, 11] - [373, 12]) + date: (date [373, 13] - [373, 23])) + (blame_entry [374, 4] - [374, 23] + line: (number [374, 11] - [374, 12]) + date: (date [374, 13] - [374, 23])) + (blame_entry [375, 4] - [375, 24] + line: (number [375, 11] - [375, 13]) + date: (date [375, 14] - [375, 24])) + (blame_entry [376, 4] - [376, 24] + line: (number [376, 11] - [376, 13]) + date: (date [376, 14] - [376, 24])) + (blame_entry [377, 4] - [377, 24] + line: (number [377, 11] - [377, 13]) + date: (date [377, 14] - [377, 24])) + (blame_entry [378, 4] - [378, 24] + line: (number [378, 11] - [378, 13]) + date: (date [378, 14] - [378, 24]))) + (file_entry [379, 0] - [386, 25] + file_name: (filename [379, 6] - [379, 55]) + (blame_entry [380, 4] - [380, 25] + line: (number [380, 11] - [380, 14]) + date: (date [380, 15] - [380, 25])) + (blame_entry [381, 4] - [381, 25] + line: (number [381, 11] - [381, 14]) + date: (date [381, 15] - [381, 25])) + (blame_entry [382, 4] - [382, 25] + line: (number [382, 11] - [382, 14]) + date: (date [382, 15] - [382, 25])) + (blame_entry [383, 4] - [383, 25] + line: (number [383, 11] - [383, 14]) + date: (date [383, 15] - [383, 25])) + (blame_entry [384, 4] - [384, 25] + line: (number [384, 11] - [384, 14]) + date: (date [384, 15] - [384, 25])) + (blame_entry [385, 4] - [385, 25] + line: (number [385, 11] - [385, 14]) + date: (date [385, 15] - [385, 25])) + (blame_entry [386, 4] - [386, 25] + line: (number [386, 11] - [386, 14]) + date: (date [386, 15] - [386, 25]))) + (file_entry [387, 0] - [389, 24] + file_name: (filename [387, 6] - [387, 54]) + (blame_entry [388, 4] - [388, 24] + line: (number [388, 11] - [388, 13]) + date: (date [388, 14] - [388, 24])) + (blame_entry [389, 4] - [389, 24] + line: (number [389, 11] - [389, 13]) + date: (date [389, 14] - [389, 24]))) + (file_entry [390, 0] - [391, 25] + file_name: (filename [390, 6] - [390, 51]) + (blame_entry [391, 4] - [391, 25] + line: (number [391, 11] - [391, 14]) + date: (date [391, 15] - [391, 25]))) + (file_entry [392, 0] - [395, 25] + file_name: (filename [392, 6] - [392, 65]) + (blame_entry [393, 4] - [393, 25] + line: (number [393, 11] - [393, 14]) + date: (date [393, 15] - [393, 25])) + (blame_entry [394, 4] - [394, 25] + line: (number [394, 11] - [394, 14]) + date: (date [394, 15] - [394, 25])) + (blame_entry [395, 4] - [395, 25] + line: (number [395, 11] - [395, 14]) + date: (date [395, 15] - [395, 25]))) + (file_entry [396, 0] - [398, 25] + file_name: (filename [396, 6] - [396, 51]) + (blame_entry [397, 4] - [397, 25] + line: (number [397, 11] - [397, 14]) + date: (date [397, 15] - [397, 25])) + (blame_entry [398, 4] - [398, 25] + line: (number [398, 11] - [398, 14]) + date: (date [398, 15] - [398, 25]))) + (file_entry [399, 0] - [404, 25] + file_name: (filename [399, 6] - [399, 60]) + (blame_entry [400, 4] - [400, 24] + line: (number [400, 11] - [400, 13]) + date: (date [400, 14] - [400, 24])) + (blame_entry [401, 4] - [401, 24] + line: (number [401, 11] - [401, 13]) + date: (date [401, 14] - [401, 24])) + (blame_entry [402, 4] - [402, 25] + line: (number [402, 11] - [402, 14]) + date: (date [402, 15] - [402, 25])) + (blame_entry [403, 4] - [403, 25] + line: (number [403, 11] - [403, 14]) + date: (date [403, 15] - [403, 25])) + (blame_entry [404, 4] - [404, 25] + line: (number [404, 11] - [404, 14]) + date: (date [404, 15] - [404, 25]))) + (file_entry [405, 0] - [407, 24] + file_name: (filename [405, 6] - [405, 67]) + (blame_entry [406, 4] - [406, 23] + line: (number [406, 11] - [406, 12]) + date: (date [406, 13] - [406, 23])) + (blame_entry [407, 4] - [407, 24] + line: (number [407, 11] - [407, 13]) + date: (date [407, 14] - [407, 24]))) + (file_entry [408, 0] - [409, 23] + file_name: (filename [408, 6] - [408, 72]) + (blame_entry [409, 4] - [409, 23] + line: (number [409, 11] - [409, 12]) + date: (date [409, 13] - [409, 23]))) + (file_entry [410, 0] - [413, 24] + file_name: (filename [410, 6] - [410, 57]) + (blame_entry [411, 4] - [411, 23] + line: (number [411, 11] - [411, 12]) + date: (date [411, 13] - [411, 23])) + (blame_entry [412, 4] - [412, 24] + line: (number [412, 11] - [412, 13]) + date: (date [412, 14] - [412, 24])) + (blame_entry [413, 4] - [413, 24] + line: (number [413, 11] - [413, 13]) + date: (date [413, 14] - [413, 24]))) + (file_entry [414, 0] - [418, 25] + file_name: (filename [414, 6] - [414, 87]) + (blame_entry [415, 4] - [415, 25] + line: (number [415, 11] - [415, 14]) + date: (date [415, 15] - [415, 25])) + (blame_entry [416, 4] - [416, 25] + line: (number [416, 11] - [416, 14]) + date: (date [416, 15] - [416, 25])) + (blame_entry [417, 4] - [417, 25] + line: (number [417, 11] - [417, 14]) + date: (date [417, 15] - [417, 25])) + (blame_entry [418, 4] - [418, 25] + line: (number [418, 11] - [418, 14]) + date: (date [418, 15] - [418, 25]))) + (file_entry [419, 0] - [423, 25] + file_name: (filename [419, 6] - [419, 68]) + (blame_entry [420, 4] - [420, 24] + line: (number [420, 11] - [420, 13]) + date: (date [420, 14] - [420, 24])) + (blame_entry [421, 4] - [421, 25] + line: (number [421, 11] - [421, 14]) + date: (date [421, 15] - [421, 25])) + (blame_entry [422, 4] - [422, 25] + line: (number [422, 11] - [422, 14]) + date: (date [422, 15] - [422, 25])) + (blame_entry [423, 4] - [423, 25] + line: (number [423, 11] - [423, 14]) + date: (date [423, 15] - [423, 25]))) + (file_entry [424, 0] - [426, 24] + file_name: (filename [424, 6] - [424, 65]) + (blame_entry [425, 4] - [425, 24] + line: (number [425, 11] - [425, 13]) + date: (date [425, 14] - [425, 24])) + (blame_entry [426, 4] - [426, 24] + line: (number [426, 11] - [426, 13]) + date: (date [426, 14] - [426, 24]))) + (file_entry [427, 0] - [428, 24] + file_name: (filename [427, 6] - [427, 89]) + (blame_entry [428, 4] - [428, 24] + line: (number [428, 11] - [428, 13]) + date: (date [428, 14] - [428, 24]))) + (file_entry [429, 0] - [430, 23] + file_name: (filename [429, 6] - [429, 71]) + (blame_entry [430, 4] - [430, 23] + line: (number [430, 11] - [430, 12]) + date: (date [430, 13] - [430, 23]))) + (file_entry [431, 0] - [435, 25] + file_name: (filename [431, 6] - [431, 70]) + (blame_entry [432, 4] - [432, 24] + line: (number [432, 11] - [432, 13]) + date: (date [432, 14] - [432, 24])) + (blame_entry [433, 4] - [433, 25] + line: (number [433, 11] - [433, 14]) + date: (date [433, 15] - [433, 25])) + (blame_entry [434, 4] - [434, 25] + line: (number [434, 11] - [434, 14]) + date: (date [434, 15] - [434, 25])) + (blame_entry [435, 4] - [435, 25] + line: (number [435, 11] - [435, 14]) + date: (date [435, 15] - [435, 25]))) + (file_entry [436, 0] - [437, 23] + file_name: (filename [436, 6] - [436, 84]) + (blame_entry [437, 4] - [437, 23] + line: (number [437, 11] - [437, 12]) + date: (date [437, 13] - [437, 23]))) + (file_entry [438, 0] - [439, 24] + file_name: (filename [438, 6] - [438, 87]) + (blame_entry [439, 4] - [439, 24] + line: (number [439, 11] - [439, 13]) + date: (date [439, 14] - [439, 24]))) + (file_entry [440, 0] - [448, 25] + file_name: (filename [440, 6] - [440, 66]) + (blame_entry [441, 4] - [441, 23] + line: (number [441, 11] - [441, 12]) + date: (date [441, 13] - [441, 23])) + (blame_entry [442, 4] - [442, 24] + line: (number [442, 11] - [442, 13]) + date: (date [442, 14] - [442, 24])) + (blame_entry [443, 4] - [443, 24] + line: (number [443, 11] - [443, 13]) + date: (date [443, 14] - [443, 24])) + (blame_entry [444, 4] - [444, 24] + line: (number [444, 11] - [444, 13]) + date: (date [444, 14] - [444, 24])) + (blame_entry [445, 4] - [445, 25] + line: (number [445, 11] - [445, 14]) + date: (date [445, 15] - [445, 25])) + (blame_entry [446, 4] - [446, 25] + line: (number [446, 11] - [446, 14]) + date: (date [446, 15] - [446, 25])) + (blame_entry [447, 4] - [447, 25] + line: (number [447, 11] - [447, 14]) + date: (date [447, 15] - [447, 25])) + (blame_entry [448, 4] - [448, 25] + line: (number [448, 11] - [448, 14]) + date: (date [448, 15] - [448, 25]))) + (file_entry [449, 0] - [453, 25] + file_name: (filename [449, 6] - [449, 70]) + (blame_entry [450, 4] - [450, 24] + line: (number [450, 11] - [450, 13]) + date: (date [450, 14] - [450, 24])) + (blame_entry [451, 4] - [451, 25] + line: (number [451, 11] - [451, 14]) + date: (date [451, 15] - [451, 25])) + (blame_entry [452, 4] - [452, 25] + line: (number [452, 11] - [452, 14]) + date: (date [452, 15] - [452, 25])) + (blame_entry [453, 4] - [453, 25] + line: (number [453, 11] - [453, 14]) + date: (date [453, 15] - [453, 25]))) + (file_entry [454, 0] - [458, 25] + file_name: (filename [454, 6] - [454, 68]) + (blame_entry [455, 4] - [455, 24] + line: (number [455, 11] - [455, 13]) + date: (date [455, 14] - [455, 24])) + (blame_entry [456, 4] - [456, 25] + line: (number [456, 11] - [456, 14]) + date: (date [456, 15] - [456, 25])) + (blame_entry [457, 4] - [457, 25] + line: (number [457, 11] - [457, 14]) + date: (date [457, 15] - [457, 25])) + (blame_entry [458, 4] - [458, 25] + line: (number [458, 11] - [458, 14]) + date: (date [458, 15] - [458, 25]))) + (file_entry [459, 0] - [461, 24] + file_name: (filename [459, 6] - [459, 42]) + (blame_entry [460, 4] - [460, 24] + line: (number [460, 11] - [460, 13]) + date: (date [460, 14] - [460, 24])) + (blame_entry [461, 4] - [461, 24] + line: (number [461, 11] - [461, 13]) + date: (date [461, 14] - [461, 24]))) + (file_entry [462, 0] - [463, 24] + file_name: (filename [462, 6] - [462, 34]) + (blame_entry [463, 4] - [463, 24] + line: (number [463, 11] - [463, 13]) + date: (date [463, 14] - [463, 24]))) + (file_entry [464, 0] - [470, 25] + file_name: (filename [464, 6] - [464, 59]) + (blame_entry [465, 4] - [465, 24] + line: (number [465, 11] - [465, 13]) + date: (date [465, 14] - [465, 24])) + (blame_entry [466, 4] - [466, 24] + line: (number [466, 11] - [466, 13]) + date: (date [466, 14] - [466, 24])) + (blame_entry [467, 4] - [467, 24] + line: (number [467, 11] - [467, 13]) + date: (date [467, 14] - [467, 24])) + (blame_entry [468, 4] - [468, 25] + line: (number [468, 11] - [468, 14]) + date: (date [468, 15] - [468, 25])) + (blame_entry [469, 4] - [469, 25] + line: (number [469, 11] - [469, 14]) + date: (date [469, 15] - [469, 25])) + (blame_entry [470, 4] - [470, 25] + line: (number [470, 11] - [470, 14]) + date: (date [470, 15] - [470, 25]))) + (file_entry [471, 0] - [473, 24] + file_name: (filename [471, 6] - [471, 90]) + (blame_entry [472, 4] - [472, 24] + line: (number [472, 11] - [472, 13]) + date: (date [472, 14] - [472, 24])) + (blame_entry [473, 4] - [473, 24] + line: (number [473, 11] - [473, 13]) + date: (date [473, 14] - [473, 24]))) + (file_entry [474, 0] - [475, 24] + file_name: (filename [474, 6] - [474, 72]) + (blame_entry [475, 4] - [475, 24] + line: (number [475, 11] - [475, 13]) + date: (date [475, 14] - [475, 24]))) + (file_entry [476, 0] - [477, 23] + file_name: (filename [476, 6] - [476, 80]) + (blame_entry [477, 4] - [477, 23] + line: (number [477, 11] - [477, 12]) + date: (date [477, 13] - [477, 23]))) + (file_entry [478, 0] - [479, 24] + file_name: (filename [478, 6] - [478, 75]) + (blame_entry [479, 4] - [479, 24] + line: (number [479, 11] - [479, 13]) + date: (date [479, 14] - [479, 24]))) + (file_entry [480, 0] - [481, 24] + file_name: (filename [480, 6] - [480, 67]) + (blame_entry [481, 4] - [481, 24] + line: (number [481, 11] - [481, 13]) + date: (date [481, 14] - [481, 24]))) + (file_entry [482, 0] - [483, 24] + file_name: (filename [482, 6] - [482, 77]) + (blame_entry [483, 4] - [483, 24] + line: (number [483, 11] - [483, 13]) + date: (date [483, 14] - [483, 24]))) + (file_entry [484, 0] - [485, 25] + file_name: (filename [484, 6] - [484, 62]) + (blame_entry [485, 4] - [485, 25] + line: (number [485, 11] - [485, 14]) + date: (date [485, 15] - [485, 25]))) + (file_entry [486, 0] - [488, 25] + file_name: (filename [486, 6] - [486, 49]) + (blame_entry [487, 4] - [487, 24] + line: (number [487, 11] - [487, 13]) + date: (date [487, 14] - [487, 24])) + (blame_entry [488, 4] - [488, 25] + line: (number [488, 11] - [488, 14]) + date: (date [488, 15] - [488, 25]))) + (file_entry [489, 0] - [491, 24] + file_name: (filename [489, 6] - [489, 101]) + (blame_entry [490, 4] - [490, 23] + line: (number [490, 11] - [490, 12]) + date: (date [490, 13] - [490, 23])) + (blame_entry [491, 4] - [491, 24] + line: (number [491, 11] - [491, 13]) + date: (date [491, 14] - [491, 24]))) + (file_entry [492, 0] - [493, 24] + file_name: (filename [492, 6] - [492, 70]) + (blame_entry [493, 4] - [493, 24] + line: (number [493, 11] - [493, 13]) + date: (date [493, 14] - [493, 24]))) + (file_entry [494, 0] - [498, 25] + file_name: (filename [494, 6] - [494, 92]) + (blame_entry [495, 4] - [495, 25] + line: (number [495, 11] - [495, 14]) + date: (date [495, 15] - [495, 25])) + (blame_entry [496, 4] - [496, 25] + line: (number [496, 11] - [496, 14]) + date: (date [496, 15] - [496, 25])) + (blame_entry [497, 4] - [497, 25] + line: (number [497, 11] - [497, 14]) + date: (date [497, 15] - [497, 25])) + (blame_entry [498, 4] - [498, 25] + line: (number [498, 11] - [498, 14]) + date: (date [498, 15] - [498, 25]))) + (file_entry [499, 0] - [507, 24] + file_name: (filename [499, 6] - [499, 58]) + (blame_entry [500, 4] - [500, 24] + line: (number [500, 11] - [500, 13]) + date: (date [500, 14] - [500, 24])) + (blame_entry [501, 4] - [501, 24] + line: (number [501, 11] - [501, 13]) + date: (date [501, 14] - [501, 24])) + (blame_entry [502, 4] - [502, 24] + line: (number [502, 11] - [502, 13]) + date: (date [502, 14] - [502, 24])) + (blame_entry [503, 4] - [503, 24] + line: (number [503, 11] - [503, 13]) + date: (date [503, 14] - [503, 24])) + (blame_entry [504, 4] - [504, 24] + line: (number [504, 11] - [504, 13]) + date: (date [504, 14] - [504, 24])) + (blame_entry [505, 4] - [505, 24] + line: (number [505, 11] - [505, 13]) + date: (date [505, 14] - [505, 24])) + (blame_entry [506, 4] - [506, 24] + line: (number [506, 11] - [506, 13]) + date: (date [506, 14] - [506, 24])) + (blame_entry [507, 4] - [507, 24] + line: (number [507, 11] - [507, 13]) + date: (date [507, 14] - [507, 24]))) + (file_entry [508, 0] - [512, 25] + file_name: (filename [508, 6] - [508, 92]) + (blame_entry [509, 4] - [509, 25] + line: (number [509, 11] - [509, 14]) + date: (date [509, 15] - [509, 25])) + (blame_entry [510, 4] - [510, 25] + line: (number [510, 11] - [510, 14]) + date: (date [510, 15] - [510, 25])) + (blame_entry [511, 4] - [511, 25] + line: (number [511, 11] - [511, 14]) + date: (date [511, 15] - [511, 25])) + (blame_entry [512, 4] - [512, 25] + line: (number [512, 11] - [512, 14]) + date: (date [512, 15] - [512, 25]))) + (file_entry [513, 0] - [515, 24] + file_name: (filename [513, 6] - [513, 77]) + (blame_entry [514, 4] - [514, 23] + line: (number [514, 11] - [514, 12]) + date: (date [514, 13] - [514, 23])) + (blame_entry [515, 4] - [515, 24] + line: (number [515, 11] - [515, 13]) + date: (date [515, 14] - [515, 24]))) + (file_entry [516, 0] - [520, 25] + file_name: (filename [516, 6] - [516, 70]) + (blame_entry [517, 4] - [517, 24] + line: (number [517, 11] - [517, 13]) + date: (date [517, 14] - [517, 24])) + (blame_entry [518, 4] - [518, 25] + line: (number [518, 11] - [518, 14]) + date: (date [518, 15] - [518, 25])) + (blame_entry [519, 4] - [519, 25] + line: (number [519, 11] - [519, 14]) + date: (date [519, 15] - [519, 25])) + (blame_entry [520, 4] - [520, 25] + line: (number [520, 11] - [520, 14]) + date: (date [520, 15] - [520, 25]))) + (file_entry [521, 0] - [524, 25] + file_name: (filename [521, 6] - [521, 46]) + (blame_entry [522, 4] - [522, 25] + line: (number [522, 11] - [522, 14]) + date: (date [522, 15] - [522, 25])) + (blame_entry [523, 4] - [523, 25] + line: (number [523, 11] - [523, 14]) + date: (date [523, 15] - [523, 25])) + (blame_entry [524, 4] - [524, 25] + line: (number [524, 11] - [524, 14]) + date: (date [524, 15] - [524, 25]))) + (file_entry [525, 0] - [526, 24] + file_name: (filename [525, 6] - [525, 52]) + (blame_entry [526, 4] - [526, 24] + line: (number [526, 11] - [526, 13]) + date: (date [526, 14] - [526, 24]))) + (file_entry [527, 0] - [532, 25] + file_name: (filename [527, 6] - [527, 66]) + (blame_entry [528, 4] - [528, 24] + line: (number [528, 11] - [528, 13]) + date: (date [528, 14] - [528, 24])) + (blame_entry [529, 4] - [529, 24] + line: (number [529, 11] - [529, 13]) + date: (date [529, 14] - [529, 24])) + (blame_entry [530, 4] - [530, 25] + line: (number [530, 11] - [530, 14]) + date: (date [530, 15] - [530, 25])) + (blame_entry [531, 4] - [531, 25] + line: (number [531, 11] - [531, 14]) + date: (date [531, 15] - [531, 25])) + (blame_entry [532, 4] - [532, 25] + line: (number [532, 11] - [532, 14]) + date: (date [532, 15] - [532, 25]))) + (file_entry [533, 0] - [540, 25] + file_name: (filename [533, 6] - [533, 77]) + (blame_entry [534, 4] - [534, 25] + line: (number [534, 11] - [534, 14]) + date: (date [534, 15] - [534, 25])) + (blame_entry [535, 4] - [535, 25] + line: (number [535, 11] - [535, 14]) + date: (date [535, 15] - [535, 25])) + (blame_entry [536, 4] - [536, 25] + line: (number [536, 11] - [536, 14]) + date: (date [536, 15] - [536, 25])) + (blame_entry [537, 4] - [537, 25] + line: (number [537, 11] - [537, 14]) + date: (date [537, 15] - [537, 25])) + (blame_entry [538, 4] - [538, 25] + line: (number [538, 11] - [538, 14]) + date: (date [538, 15] - [538, 25])) + (blame_entry [539, 4] - [539, 25] + line: (number [539, 11] - [539, 14]) + date: (date [539, 15] - [539, 25])) + (blame_entry [540, 4] - [540, 25] + line: (number [540, 11] - [540, 14]) + date: (date [540, 15] - [540, 25]))) + (file_entry [541, 0] - [546, 25] + file_name: (filename [541, 6] - [541, 45]) + (blame_entry [542, 4] - [542, 24] + line: (number [542, 11] - [542, 13]) + date: (date [542, 14] - [542, 24])) + (blame_entry [543, 4] - [543, 25] + line: (number [543, 11] - [543, 14]) + date: (date [543, 15] - [543, 25])) + (blame_entry [544, 4] - [544, 25] + line: (number [544, 11] - [544, 14]) + date: (date [544, 15] - [544, 25])) + (blame_entry [545, 4] - [545, 25] + line: (number [545, 11] - [545, 14]) + date: (date [545, 15] - [545, 25])) + (blame_entry [546, 4] - [546, 25] + line: (number [546, 11] - [546, 14]) + date: (date [546, 15] - [546, 25]))) + (file_entry [547, 0] - [549, 24] + file_name: (filename [547, 6] - [547, 68]) + (blame_entry [548, 4] - [548, 23] + line: (number [548, 11] - [548, 12]) + date: (date [548, 13] - [548, 23])) + (blame_entry [549, 4] - [549, 24] + line: (number [549, 11] - [549, 13]) + date: (date [549, 14] - [549, 24]))) + (file_entry [550, 0] - [551, 25] + file_name: (filename [550, 6] - [550, 82]) + (blame_entry [551, 4] - [551, 25] + line: (number [551, 11] - [551, 14]) + date: (date [551, 15] - [551, 25]))) + (file_entry [552, 0] - [559, 25] + file_name: (filename [552, 6] - [552, 51]) + (blame_entry [553, 4] - [553, 24] + line: (number [553, 11] - [553, 13]) + date: (date [553, 14] - [553, 24])) + (blame_entry [554, 4] - [554, 25] + line: (number [554, 11] - [554, 14]) + date: (date [554, 15] - [554, 25])) + (blame_entry [555, 4] - [555, 25] + line: (number [555, 11] - [555, 14]) + date: (date [555, 15] - [555, 25])) + (blame_entry [556, 4] - [556, 25] + line: (number [556, 11] - [556, 14]) + date: (date [556, 15] - [556, 25])) + (blame_entry [557, 4] - [557, 25] + line: (number [557, 11] - [557, 14]) + date: (date [557, 15] - [557, 25])) + (blame_entry [558, 4] - [558, 25] + line: (number [558, 11] - [558, 14]) + date: (date [558, 15] - [558, 25])) + (blame_entry [559, 4] - [559, 25] + line: (number [559, 11] - [559, 14]) + date: (date [559, 15] - [559, 25]))) + (file_entry [560, 0] - [561, 24] + file_name: (filename [560, 6] - [560, 53]) + (blame_entry [561, 4] - [561, 24] + line: (number [561, 11] - [561, 13]) + date: (date [561, 14] - [561, 24]))) + (file_entry [562, 0] - [566, 25] + file_name: (filename [562, 6] - [562, 91]) + (blame_entry [563, 4] - [563, 24] + line: (number [563, 11] - [563, 13]) + date: (date [563, 14] - [563, 24])) + (blame_entry [564, 4] - [564, 25] + line: (number [564, 11] - [564, 14]) + date: (date [564, 15] - [564, 25])) + (blame_entry [565, 4] - [565, 25] + line: (number [565, 11] - [565, 14]) + date: (date [565, 15] - [565, 25])) + (blame_entry [566, 4] - [566, 25] + line: (number [566, 11] - [566, 14]) + date: (date [566, 15] - [566, 25]))) + (file_entry [567, 0] - [570, 23] + file_name: (filename [567, 6] - [567, 54]) + (blame_entry [568, 4] - [568, 23] + line: (number [568, 11] - [568, 12]) + date: (date [568, 13] - [568, 23])) + (blame_entry [569, 4] - [569, 23] + line: (number [569, 11] - [569, 12]) + date: (date [569, 13] - [569, 23])) + (blame_entry [570, 4] - [570, 23] + line: (number [570, 11] - [570, 12]) + date: (date [570, 13] - [570, 23]))) + (file_entry [571, 0] - [575, 25] + file_name: (filename [571, 6] - [571, 92]) + (blame_entry [572, 4] - [572, 25] + line: (number [572, 11] - [572, 14]) + date: (date [572, 15] - [572, 25])) + (blame_entry [573, 4] - [573, 25] + line: (number [573, 11] - [573, 14]) + date: (date [573, 15] - [573, 25])) + (blame_entry [574, 4] - [574, 25] + line: (number [574, 11] - [574, 14]) + date: (date [574, 15] - [574, 25])) + (blame_entry [575, 4] - [575, 25] + line: (number [575, 11] - [575, 14]) + date: (date [575, 15] - [575, 25]))) + (file_entry [576, 0] - [589, 25] + file_name: (filename [576, 6] - [576, 40]) + (blame_entry [577, 4] - [577, 24] + line: (number [577, 11] - [577, 13]) + date: (date [577, 14] - [577, 24])) + (blame_entry [578, 4] - [578, 24] + line: (number [578, 11] - [578, 13]) + date: (date [578, 14] - [578, 24])) + (blame_entry [579, 4] - [579, 25] + line: (number [579, 11] - [579, 14]) + date: (date [579, 15] - [579, 25])) + (blame_entry [580, 4] - [580, 25] + line: (number [580, 11] - [580, 14]) + date: (date [580, 15] - [580, 25])) + (blame_entry [581, 4] - [581, 25] + line: (number [581, 11] - [581, 14]) + date: (date [581, 15] - [581, 25])) + (blame_entry [582, 4] - [582, 25] + line: (number [582, 11] - [582, 14]) + date: (date [582, 15] - [582, 25])) + (blame_entry [583, 4] - [583, 25] + line: (number [583, 11] - [583, 14]) + date: (date [583, 15] - [583, 25])) + (blame_entry [584, 4] - [584, 25] + line: (number [584, 11] - [584, 14]) + date: (date [584, 15] - [584, 25])) + (blame_entry [585, 4] - [585, 25] + line: (number [585, 11] - [585, 14]) + date: (date [585, 15] - [585, 25])) + (blame_entry [586, 4] - [586, 25] + line: (number [586, 11] - [586, 14]) + date: (date [586, 15] - [586, 25])) + (blame_entry [587, 4] - [587, 25] + line: (number [587, 11] - [587, 14]) + date: (date [587, 15] - [587, 25])) + (blame_entry [588, 4] - [588, 25] + line: (number [588, 11] - [588, 14]) + date: (date [588, 15] - [588, 25])) + (blame_entry [589, 4] - [589, 25] + line: (number [589, 11] - [589, 14]) + date: (date [589, 15] - [589, 25]))) + (file_entry [590, 0] - [593, 24] + file_name: (filename [590, 6] - [590, 80]) + (blame_entry [591, 4] - [591, 24] + line: (number [591, 11] - [591, 13]) + date: (date [591, 14] - [591, 24])) + (blame_entry [592, 4] - [592, 24] + line: (number [592, 11] - [592, 13]) + date: (date [592, 14] - [592, 24])) + (blame_entry [593, 4] - [593, 24] + line: (number [593, 11] - [593, 13]) + date: (date [593, 14] - [593, 24]))) + (file_entry [594, 0] - [596, 24] + file_name: (filename [594, 6] - [594, 56]) + (blame_entry [595, 4] - [595, 23] + line: (number [595, 11] - [595, 12]) + date: (date [595, 13] - [595, 23])) + (blame_entry [596, 4] - [596, 24] + line: (number [596, 11] - [596, 13]) + date: (date [596, 14] - [596, 24]))) + (file_entry [597, 0] - [598, 24] + file_name: (filename [597, 6] - [597, 50]) + (blame_entry [598, 4] - [598, 24] + line: (number [598, 11] - [598, 13]) + date: (date [598, 14] - [598, 24]))) + (file_entry [599, 0] - [600, 24] + file_name: (filename [599, 6] - [599, 82]) + (blame_entry [600, 4] - [600, 24] + line: (number [600, 11] - [600, 13]) + date: (date [600, 14] - [600, 24]))) + (file_entry [601, 0] - [602, 24] + file_name: (filename [601, 6] - [601, 73]) + (blame_entry [602, 4] - [602, 24] + line: (number [602, 11] - [602, 13]) + date: (date [602, 14] - [602, 24]))) + (file_entry [603, 0] - [621, 25] + file_name: (filename [603, 6] - [603, 59]) + (blame_entry [604, 4] - [604, 24] + line: (number [604, 11] - [604, 13]) + date: (date [604, 14] - [604, 24])) + (blame_entry [605, 4] - [605, 25] + line: (number [605, 11] - [605, 14]) + date: (date [605, 15] - [605, 25])) + (blame_entry [606, 4] - [606, 25] + line: (number [606, 11] - [606, 14]) + date: (date [606, 15] - [606, 25])) + (blame_entry [607, 4] - [607, 25] + line: (number [607, 11] - [607, 14]) + date: (date [607, 15] - [607, 25])) + (blame_entry [608, 4] - [608, 25] + line: (number [608, 11] - [608, 14]) + date: (date [608, 15] - [608, 25])) + (blame_entry [609, 4] - [609, 25] + line: (number [609, 11] - [609, 14]) + date: (date [609, 15] - [609, 25])) + (blame_entry [610, 4] - [610, 25] + line: (number [610, 11] - [610, 14]) + date: (date [610, 15] - [610, 25])) + (blame_entry [611, 4] - [611, 25] + line: (number [611, 11] - [611, 14]) + date: (date [611, 15] - [611, 25])) + (blame_entry [612, 4] - [612, 25] + line: (number [612, 11] - [612, 14]) + date: (date [612, 15] - [612, 25])) + (blame_entry [613, 4] - [613, 25] + line: (number [613, 11] - [613, 14]) + date: (date [613, 15] - [613, 25])) + (blame_entry [614, 4] - [614, 25] + line: (number [614, 11] - [614, 14]) + date: (date [614, 15] - [614, 25])) + (blame_entry [615, 4] - [615, 25] + line: (number [615, 11] - [615, 14]) + date: (date [615, 15] - [615, 25])) + (blame_entry [616, 4] - [616, 25] + line: (number [616, 11] - [616, 14]) + date: (date [616, 15] - [616, 25])) + (blame_entry [617, 4] - [617, 25] + line: (number [617, 11] - [617, 14]) + date: (date [617, 15] - [617, 25])) + (blame_entry [618, 4] - [618, 25] + line: (number [618, 11] - [618, 14]) + date: (date [618, 15] - [618, 25])) + (blame_entry [619, 4] - [619, 25] + line: (number [619, 11] - [619, 14]) + date: (date [619, 15] - [619, 25])) + (blame_entry [620, 4] - [620, 25] + line: (number [620, 11] - [620, 14]) + date: (date [620, 15] - [620, 25])) + (blame_entry [621, 4] - [621, 25] + line: (number [621, 11] - [621, 14]) + date: (date [621, 15] - [621, 25]))) + (file_entry [622, 0] - [623, 24] + file_name: (filename [622, 6] - [622, 50]) + (blame_entry [623, 4] - [623, 24] + line: (number [623, 11] - [623, 13]) + date: (date [623, 14] - [623, 24]))) + (file_entry [624, 0] - [625, 25] + file_name: (filename [624, 6] - [624, 59]) + (blame_entry [625, 4] - [625, 25] + line: (number [625, 11] - [625, 14]) + date: (date [625, 15] - [625, 25]))) + (file_entry [626, 0] - [628, 25] + file_name: (filename [626, 6] - [626, 76]) + (blame_entry [627, 4] - [627, 24] + line: (number [627, 11] - [627, 13]) + date: (date [627, 14] - [627, 24])) + (blame_entry [628, 4] - [628, 25] + line: (number [628, 11] - [628, 14]) + date: (date [628, 15] - [628, 25]))) + (file_entry [629, 0] - [631, 24] + file_name: (filename [629, 6] - [629, 68]) + (blame_entry [630, 4] - [630, 23] + line: (number [630, 11] - [630, 12]) + date: (date [630, 13] - [630, 23])) + (blame_entry [631, 4] - [631, 24] + line: (number [631, 11] - [631, 13]) + date: (date [631, 14] - [631, 24]))) + (file_entry [632, 0] - [633, 24] + file_name: (filename [632, 6] - [632, 69]) + (blame_entry [633, 4] - [633, 24] + line: (number [633, 11] - [633, 13]) + date: (date [633, 14] - [633, 24]))) + (file_entry [634, 0] - [635, 24] + file_name: (filename [634, 6] - [634, 82]) + (blame_entry [635, 4] - [635, 24] + line: (number [635, 11] - [635, 13]) + date: (date [635, 14] - [635, 24]))) + (file_entry [636, 0] - [639, 25] + file_name: (filename [636, 6] - [636, 62]) + (blame_entry [637, 4] - [637, 25] + line: (number [637, 11] - [637, 14]) + date: (date [637, 15] - [637, 25])) + (blame_entry [638, 4] - [638, 25] + line: (number [638, 11] - [638, 14]) + date: (date [638, 15] - [638, 25])) + (blame_entry [639, 4] - [639, 25] + line: (number [639, 11] - [639, 14]) + date: (date [639, 15] - [639, 25]))) + (file_entry [640, 0] - [641, 24] + file_name: (filename [640, 6] - [640, 82]) + (blame_entry [641, 4] - [641, 24] + line: (number [641, 11] - [641, 13]) + date: (date [641, 14] - [641, 24]))) + (file_entry [642, 0] - [644, 24] + file_name: (filename [642, 6] - [642, 62]) + (blame_entry [643, 4] - [643, 24] + line: (number [643, 11] - [643, 13]) + date: (date [643, 14] - [643, 24])) + (blame_entry [644, 4] - [644, 24] + line: (number [644, 11] - [644, 13]) + date: (date [644, 14] - [644, 24]))) + (file_entry [645, 0] - [650, 24] + file_name: (filename [645, 6] - [645, 54]) + (blame_entry [646, 4] - [646, 23] + line: (number [646, 11] - [646, 12]) + date: (date [646, 13] - [646, 23])) + (blame_entry [647, 4] - [647, 24] + line: (number [647, 11] - [647, 13]) + date: (date [647, 14] - [647, 24])) + (blame_entry [648, 4] - [648, 24] + line: (number [648, 11] - [648, 13]) + date: (date [648, 14] - [648, 24])) + (blame_entry [649, 4] - [649, 24] + line: (number [649, 11] - [649, 13]) + date: (date [649, 14] - [649, 24])) + (blame_entry [650, 4] - [650, 24] + line: (number [650, 11] - [650, 13]) + date: (date [650, 14] - [650, 24]))) + (file_entry [651, 0] - [656, 26] + file_name: (filename [651, 6] - [651, 91]) + (blame_entry [652, 4] - [652, 25] + line: (number [652, 11] - [652, 14]) + date: (date [652, 15] - [652, 25])) + (blame_entry [653, 4] - [653, 25] + line: (number [653, 11] - [653, 14]) + date: (date [653, 15] - [653, 25])) + (blame_entry [654, 4] - [654, 26] + line: (number [654, 11] - [654, 15]) + date: (date [654, 16] - [654, 26])) + (blame_entry [655, 4] - [655, 26] + line: (number [655, 11] - [655, 15]) + date: (date [655, 16] - [655, 26])) + (blame_entry [656, 4] - [656, 26] + line: (number [656, 11] - [656, 15]) + date: (date [656, 16] - [656, 26]))) + (file_entry [657, 0] - [661, 25] + file_name: (filename [657, 6] - [657, 93]) + (blame_entry [658, 4] - [658, 25] + line: (number [658, 11] - [658, 14]) + date: (date [658, 15] - [658, 25])) + (blame_entry [659, 4] - [659, 25] + line: (number [659, 11] - [659, 14]) + date: (date [659, 15] - [659, 25])) + (blame_entry [660, 4] - [660, 25] + line: (number [660, 11] - [660, 14]) + date: (date [660, 15] - [660, 25])) + (blame_entry [661, 4] - [661, 25] + line: (number [661, 11] - [661, 14]) + date: (date [661, 15] - [661, 25]))) + (file_entry [662, 0] - [664, 25] + file_name: (filename [662, 6] - [662, 70]) + (blame_entry [663, 4] - [663, 25] + line: (number [663, 11] - [663, 14]) + date: (date [663, 15] - [663, 25])) + (blame_entry [664, 4] - [664, 25] + line: (number [664, 11] - [664, 14]) + date: (date [664, 15] - [664, 25]))) + (file_entry [665, 0] - [669, 25] + file_name: (filename [665, 6] - [665, 61]) + (blame_entry [666, 4] - [666, 24] + line: (number [666, 11] - [666, 13]) + date: (date [666, 14] - [666, 24])) + (blame_entry [667, 4] - [667, 25] + line: (number [667, 11] - [667, 14]) + date: (date [667, 15] - [667, 25])) + (blame_entry [668, 4] - [668, 25] + line: (number [668, 11] - [668, 14]) + date: (date [668, 15] - [668, 25])) + (blame_entry [669, 4] - [669, 25] + line: (number [669, 11] - [669, 14]) + date: (date [669, 15] - [669, 25]))) + (file_entry [670, 0] - [673, 24] + file_name: (filename [670, 6] - [670, 87]) + (blame_entry [671, 4] - [671, 24] + line: (number [671, 11] - [671, 13]) + date: (date [671, 14] - [671, 24])) + (blame_entry [672, 4] - [672, 24] + line: (number [672, 11] - [672, 13]) + date: (date [672, 14] - [672, 24])) + (blame_entry [673, 4] - [673, 24] + line: (number [673, 11] - [673, 13]) + date: (date [673, 14] - [673, 24]))) + (file_entry [674, 0] - [676, 24] + file_name: (filename [674, 6] - [674, 57]) + (blame_entry [675, 4] - [675, 24] + line: (number [675, 11] - [675, 13]) + date: (date [675, 14] - [675, 24])) + (blame_entry [676, 4] - [676, 24] + line: (number [676, 11] - [676, 13]) + date: (date [676, 14] - [676, 24]))) + (file_entry [677, 0] - [678, 24] + file_name: (filename [677, 6] - [677, 65]) + (blame_entry [678, 4] - [678, 24] + line: (number [678, 11] - [678, 13]) + date: (date [678, 14] - [678, 24]))) + (file_entry [679, 0] - [683, 25] + file_name: (filename [679, 6] - [679, 93]) + (blame_entry [680, 4] - [680, 25] + line: (number [680, 11] - [680, 14]) + date: (date [680, 15] - [680, 25])) + (blame_entry [681, 4] - [681, 25] + line: (number [681, 11] - [681, 14]) + date: (date [681, 15] - [681, 25])) + (blame_entry [682, 4] - [682, 25] + line: (number [682, 11] - [682, 14]) + date: (date [682, 15] - [682, 25])) + (blame_entry [683, 4] - [683, 25] + line: (number [683, 11] - [683, 14]) + date: (date [683, 15] - [683, 25]))) + (file_entry [684, 0] - [685, 24] + file_name: (filename [684, 6] - [684, 65]) + (blame_entry [685, 4] - [685, 24] + line: (number [685, 11] - [685, 13]) + date: (date [685, 14] - [685, 24]))) + (file_entry [686, 0] - [688, 25] + file_name: (filename [686, 6] - [686, 70]) + (blame_entry [687, 4] - [687, 25] + line: (number [687, 11] - [687, 14]) + date: (date [687, 15] - [687, 25])) + (blame_entry [688, 4] - [688, 25] + line: (number [688, 11] - [688, 14]) + date: (date [688, 15] - [688, 25]))) + (file_entry [689, 0] - [691, 24] + file_name: (filename [689, 6] - [689, 60]) + (blame_entry [690, 4] - [690, 24] + line: (number [690, 11] - [690, 13]) + date: (date [690, 14] - [690, 24])) + (blame_entry [691, 4] - [691, 24] + line: (number [691, 11] - [691, 13]) + date: (date [691, 14] - [691, 24]))) + (file_entry [692, 0] - [696, 25] + file_name: (filename [692, 6] - [692, 75]) + (blame_entry [693, 4] - [693, 24] + line: (number [693, 11] - [693, 13]) + date: (date [693, 14] - [693, 24])) + (blame_entry [694, 4] - [694, 25] + line: (number [694, 11] - [694, 14]) + date: (date [694, 15] - [694, 25])) + (blame_entry [695, 4] - [695, 25] + line: (number [695, 11] - [695, 14]) + date: (date [695, 15] - [695, 25])) + (blame_entry [696, 4] - [696, 25] + line: (number [696, 11] - [696, 14]) + date: (date [696, 15] - [696, 25]))) + (file_entry [697, 0] - [698, 24] + file_name: (filename [697, 6] - [697, 86]) + (blame_entry [698, 4] - [698, 24] + line: (number [698, 11] - [698, 13]) + date: (date [698, 14] - [698, 24]))) + (file_entry [699, 0] - [700, 24] + file_name: (filename [699, 6] - [699, 82]) + (blame_entry [700, 4] - [700, 24] + line: (number [700, 11] - [700, 13]) + date: (date [700, 14] - [700, 24]))) + (file_entry [701, 0] - [702, 25] + file_name: (filename [701, 6] - [701, 61]) + (blame_entry [702, 4] - [702, 25] + line: (number [702, 11] - [702, 14]) + date: (date [702, 15] - [702, 25]))) + (file_entry [703, 0] - [705, 24] + file_name: (filename [703, 6] - [703, 75]) + (blame_entry [704, 4] - [704, 23] + line: (number [704, 11] - [704, 12]) + date: (date [704, 13] - [704, 23])) + (blame_entry [705, 4] - [705, 24] + line: (number [705, 11] - [705, 13]) + date: (date [705, 14] - [705, 24]))) + (file_entry [706, 0] - [718, 25] + file_name: (filename [706, 6] - [706, 61]) + (blame_entry [707, 4] - [707, 24] + line: (number [707, 11] - [707, 13]) + date: (date [707, 14] - [707, 24])) + (blame_entry [708, 4] - [708, 24] + line: (number [708, 11] - [708, 13]) + date: (date [708, 14] - [708, 24])) + (blame_entry [709, 4] - [709, 25] + line: (number [709, 11] - [709, 14]) + date: (date [709, 15] - [709, 25])) + (blame_entry [710, 4] - [710, 25] + line: (number [710, 11] - [710, 14]) + date: (date [710, 15] - [710, 25])) + (blame_entry [711, 4] - [711, 25] + line: (number [711, 11] - [711, 14]) + date: (date [711, 15] - [711, 25])) + (blame_entry [712, 4] - [712, 25] + line: (number [712, 11] - [712, 14]) + date: (date [712, 15] - [712, 25])) + (blame_entry [713, 4] - [713, 25] + line: (number [713, 11] - [713, 14]) + date: (date [713, 15] - [713, 25])) + (blame_entry [714, 4] - [714, 25] + line: (number [714, 11] - [714, 14]) + date: (date [714, 15] - [714, 25])) + (blame_entry [715, 4] - [715, 25] + line: (number [715, 11] - [715, 14]) + date: (date [715, 15] - [715, 25])) + (blame_entry [716, 4] - [716, 25] + line: (number [716, 11] - [716, 14]) + date: (date [716, 15] - [716, 25])) + (blame_entry [717, 4] - [717, 25] + line: (number [717, 11] - [717, 14]) + date: (date [717, 15] - [717, 25])) + (blame_entry [718, 4] - [718, 25] + line: (number [718, 11] - [718, 14]) + date: (date [718, 15] - [718, 25]))) + (file_entry [719, 0] - [723, 25] + file_name: (filename [719, 6] - [719, 103]) + (blame_entry [720, 4] - [720, 25] + line: (number [720, 11] - [720, 14]) + date: (date [720, 15] - [720, 25])) + (blame_entry [721, 4] - [721, 25] + line: (number [721, 11] - [721, 14]) + date: (date [721, 15] - [721, 25])) + (blame_entry [722, 4] - [722, 25] + line: (number [722, 11] - [722, 14]) + date: (date [722, 15] - [722, 25])) + (blame_entry [723, 4] - [723, 25] + line: (number [723, 11] - [723, 14]) + date: (date [723, 15] - [723, 25]))) + (file_entry [724, 0] - [726, 25] + file_name: (filename [724, 6] - [724, 76]) + (blame_entry [725, 4] - [725, 24] + line: (number [725, 11] - [725, 13]) + date: (date [725, 14] - [725, 24])) + (blame_entry [726, 4] - [726, 25] + line: (number [726, 11] - [726, 14]) + date: (date [726, 15] - [726, 25]))) + (file_entry [727, 0] - [728, 24] + file_name: (filename [727, 6] - [727, 78]) + (blame_entry [728, 4] - [728, 24] + line: (number [728, 11] - [728, 13]) + date: (date [728, 14] - [728, 24]))) + (file_entry [729, 0] - [730, 25] + file_name: (filename [729, 6] - [729, 47]) + (blame_entry [730, 4] - [730, 25] + line: (number [730, 11] - [730, 14]) + date: (date [730, 15] - [730, 25]))) + (file_entry [731, 0] - [735, 25] + file_name: (filename [731, 6] - [731, 93]) + (blame_entry [732, 4] - [732, 25] + line: (number [732, 11] - [732, 14]) + date: (date [732, 15] - [732, 25])) + (blame_entry [733, 4] - [733, 25] + line: (number [733, 11] - [733, 14]) + date: (date [733, 15] - [733, 25])) + (blame_entry [734, 4] - [734, 25] + line: (number [734, 11] - [734, 14]) + date: (date [734, 15] - [734, 25])) + (blame_entry [735, 4] - [735, 25] + line: (number [735, 11] - [735, 14]) + date: (date [735, 15] - [735, 25]))) + (file_entry [736, 0] - [740, 24] + file_name: (filename [736, 6] - [736, 55]) + (blame_entry [737, 4] - [737, 24] + line: (number [737, 11] - [737, 13]) + date: (date [737, 14] - [737, 24])) + (blame_entry [738, 4] - [738, 24] + line: (number [738, 11] - [738, 13]) + date: (date [738, 14] - [738, 24])) + (blame_entry [739, 4] - [739, 24] + line: (number [739, 11] - [739, 13]) + date: (date [739, 14] - [739, 24])) + (blame_entry [740, 4] - [740, 24] + line: (number [740, 11] - [740, 13]) + date: (date [740, 14] - [740, 24]))) + (file_entry [741, 0] - [744, 24] + file_name: (filename [741, 6] - [741, 61]) + (blame_entry [742, 4] - [742, 24] + line: (number [742, 11] - [742, 13]) + date: (date [742, 14] - [742, 24])) + (blame_entry [743, 4] - [743, 24] + line: (number [743, 11] - [743, 13]) + date: (date [743, 14] - [743, 24])) + (blame_entry [744, 4] - [744, 24] + line: (number [744, 11] - [744, 13]) + date: (date [744, 14] - [744, 24]))) + (file_entry [745, 0] - [746, 25] + file_name: (filename [745, 6] - [745, 64]) + (blame_entry [746, 4] - [746, 25] + line: (number [746, 11] - [746, 14]) + date: (date [746, 15] - [746, 25]))) + (file_entry [747, 0] - [762, 25] + file_name: (filename [747, 6] - [747, 64]) + (blame_entry [748, 4] - [748, 24] + line: (number [748, 11] - [748, 13]) + date: (date [748, 14] - [748, 24])) + (blame_entry [749, 4] - [749, 24] + line: (number [749, 11] - [749, 13]) + date: (date [749, 14] - [749, 24])) + (blame_entry [750, 4] - [750, 25] + line: (number [750, 11] - [750, 14]) + date: (date [750, 15] - [750, 25])) + (blame_entry [751, 4] - [751, 25] + line: (number [751, 11] - [751, 14]) + date: (date [751, 15] - [751, 25])) + (blame_entry [752, 4] - [752, 25] + line: (number [752, 11] - [752, 14]) + date: (date [752, 15] - [752, 25])) + (blame_entry [753, 4] - [753, 25] + line: (number [753, 11] - [753, 14]) + date: (date [753, 15] - [753, 25])) + (blame_entry [754, 4] - [754, 25] + line: (number [754, 11] - [754, 14]) + date: (date [754, 15] - [754, 25])) + (blame_entry [755, 4] - [755, 25] + line: (number [755, 11] - [755, 14]) + date: (date [755, 15] - [755, 25])) + (blame_entry [756, 4] - [756, 25] + line: (number [756, 11] - [756, 14]) + date: (date [756, 15] - [756, 25])) + (blame_entry [757, 4] - [757, 25] + line: (number [757, 11] - [757, 14]) + date: (date [757, 15] - [757, 25])) + (blame_entry [758, 4] - [758, 25] + line: (number [758, 11] - [758, 14]) + date: (date [758, 15] - [758, 25])) + (blame_entry [759, 4] - [759, 25] + line: (number [759, 11] - [759, 14]) + date: (date [759, 15] - [759, 25])) + (blame_entry [760, 4] - [760, 25] + line: (number [760, 11] - [760, 14]) + date: (date [760, 15] - [760, 25])) + (blame_entry [761, 4] - [761, 25] + line: (number [761, 11] - [761, 14]) + date: (date [761, 15] - [761, 25])) + (blame_entry [762, 4] - [762, 25] + line: (number [762, 11] - [762, 14]) + date: (date [762, 15] - [762, 25]))) + (file_entry [763, 0] - [766, 24] + file_name: (filename [763, 6] - [763, 53]) + (blame_entry [764, 4] - [764, 24] + line: (number [764, 11] - [764, 13]) + date: (date [764, 14] - [764, 24])) + (blame_entry [765, 4] - [765, 24] + line: (number [765, 11] - [765, 13]) + date: (date [765, 14] - [765, 24])) + (blame_entry [766, 4] - [766, 24] + line: (number [766, 11] - [766, 13]) + date: (date [766, 14] - [766, 24]))) + (file_entry [767, 0] - [769, 24] + file_name: (filename [767, 6] - [767, 99]) + (blame_entry [768, 4] - [768, 23] + line: (number [768, 11] - [768, 12]) + date: (date [768, 13] - [768, 23])) + (blame_entry [769, 4] - [769, 24] + line: (number [769, 11] - [769, 13]) + date: (date [769, 14] - [769, 24]))) + (file_entry [770, 0] - [776, 25] + file_name: (filename [770, 6] - [770, 56]) + (blame_entry [771, 4] - [771, 24] + line: (number [771, 11] - [771, 13]) + date: (date [771, 14] - [771, 24])) + (blame_entry [772, 4] - [772, 24] + line: (number [772, 11] - [772, 13]) + date: (date [772, 14] - [772, 24])) + (blame_entry [773, 4] - [773, 24] + line: (number [773, 11] - [773, 13]) + date: (date [773, 14] - [773, 24])) + (blame_entry [774, 4] - [774, 24] + line: (number [774, 11] - [774, 13]) + date: (date [774, 14] - [774, 24])) + (blame_entry [775, 4] - [775, 24] + line: (number [775, 11] - [775, 13]) + date: (date [775, 14] - [775, 24])) + (blame_entry [776, 4] - [776, 25] + line: (number [776, 11] - [776, 14]) + date: (date [776, 15] - [776, 25]))) + (file_entry [777, 0] - [808, 26] + file_name: (filename [777, 6] - [777, 58]) + (blame_entry [778, 4] - [778, 25] + line: (number [778, 11] - [778, 14]) + date: (date [778, 15] - [778, 25])) + (blame_entry [779, 4] - [779, 25] + line: (number [779, 11] - [779, 14]) + date: (date [779, 15] - [779, 25])) + (blame_entry [780, 4] - [780, 25] + line: (number [780, 11] - [780, 14]) + date: (date [780, 15] - [780, 25])) + (blame_entry [781, 4] - [781, 25] + line: (number [781, 11] - [781, 14]) + date: (date [781, 15] - [781, 25])) + (blame_entry [782, 4] - [782, 25] + line: (number [782, 11] - [782, 14]) + date: (date [782, 15] - [782, 25])) + (blame_entry [783, 4] - [783, 25] + line: (number [783, 11] - [783, 14]) + date: (date [783, 15] - [783, 25])) + (blame_entry [784, 4] - [784, 25] + line: (number [784, 11] - [784, 14]) + date: (date [784, 15] - [784, 25])) + (blame_entry [785, 4] - [785, 25] + line: (number [785, 11] - [785, 14]) + date: (date [785, 15] - [785, 25])) + (blame_entry [786, 4] - [786, 25] + line: (number [786, 11] - [786, 14]) + date: (date [786, 15] - [786, 25])) + (blame_entry [787, 4] - [787, 25] + line: (number [787, 11] - [787, 14]) + date: (date [787, 15] - [787, 25])) + (blame_entry [788, 4] - [788, 25] + line: (number [788, 11] - [788, 14]) + date: (date [788, 15] - [788, 25])) + (blame_entry [789, 4] - [789, 25] + line: (number [789, 11] - [789, 14]) + date: (date [789, 15] - [789, 25])) + (blame_entry [790, 4] - [790, 25] + line: (number [790, 11] - [790, 14]) + date: (date [790, 15] - [790, 25])) + (blame_entry [791, 4] - [791, 25] + line: (number [791, 11] - [791, 14]) + date: (date [791, 15] - [791, 25])) + (blame_entry [792, 4] - [792, 25] + line: (number [792, 11] - [792, 14]) + date: (date [792, 15] - [792, 25])) + (blame_entry [793, 4] - [793, 25] + line: (number [793, 11] - [793, 14]) + date: (date [793, 15] - [793, 25])) + (blame_entry [794, 4] - [794, 25] + line: (number [794, 11] - [794, 14]) + date: (date [794, 15] - [794, 25])) + (blame_entry [795, 4] - [795, 25] + line: (number [795, 11] - [795, 14]) + date: (date [795, 15] - [795, 25])) + (blame_entry [796, 4] - [796, 25] + line: (number [796, 11] - [796, 14]) + date: (date [796, 15] - [796, 25])) + (blame_entry [797, 4] - [797, 25] + line: (number [797, 11] - [797, 14]) + date: (date [797, 15] - [797, 25])) + (blame_entry [798, 4] - [798, 25] + line: (number [798, 11] - [798, 14]) + date: (date [798, 15] - [798, 25])) + (blame_entry [799, 4] - [799, 25] + line: (number [799, 11] - [799, 14]) + date: (date [799, 15] - [799, 25])) + (blame_entry [800, 4] - [800, 25] + line: (number [800, 11] - [800, 14]) + date: (date [800, 15] - [800, 25])) + (blame_entry [801, 4] - [801, 25] + line: (number [801, 11] - [801, 14]) + date: (date [801, 15] - [801, 25])) + (blame_entry [802, 4] - [802, 25] + line: (number [802, 11] - [802, 14]) + date: (date [802, 15] - [802, 25])) + (blame_entry [803, 4] - [803, 25] + line: (number [803, 11] - [803, 14]) + date: (date [803, 15] - [803, 25])) + (blame_entry [804, 4] - [804, 26] + line: (number [804, 11] - [804, 15]) + date: (date [804, 16] - [804, 26])) + (blame_entry [805, 4] - [805, 26] + line: (number [805, 11] - [805, 15]) + date: (date [805, 16] - [805, 26])) + (blame_entry [806, 4] - [806, 26] + line: (number [806, 11] - [806, 15]) + date: (date [806, 16] - [806, 26])) + (blame_entry [807, 4] - [807, 26] + line: (number [807, 11] - [807, 15]) + date: (date [807, 16] - [807, 26])) + (blame_entry [808, 4] - [808, 26] + line: (number [808, 11] - [808, 15]) + date: (date [808, 16] - [808, 26]))) + (file_entry [809, 0] - [810, 24] + file_name: (filename [809, 6] - [809, 74]) + (blame_entry [810, 4] - [810, 24] + line: (number [810, 11] - [810, 13]) + date: (date [810, 14] - [810, 24]))) + (file_entry [811, 0] - [812, 24] + file_name: (filename [811, 6] - [811, 68]) + (blame_entry [812, 4] - [812, 24] + line: (number [812, 11] - [812, 13]) + date: (date [812, 14] - [812, 24]))) + (file_entry [813, 0] - [814, 25] + file_name: (filename [813, 6] - [813, 63]) + (blame_entry [814, 4] - [814, 25] + line: (number [814, 11] - [814, 14]) + date: (date [814, 15] - [814, 25]))) + (file_entry [815, 0] - [816, 24] + file_name: (filename [815, 6] - [815, 56]) + (blame_entry [816, 4] - [816, 24] + line: (number [816, 11] - [816, 13]) + date: (date [816, 14] - [816, 24]))) + (file_entry [817, 0] - [821, 25] + file_name: (filename [817, 6] - [817, 92]) + (blame_entry [818, 4] - [818, 25] + line: (number [818, 11] - [818, 14]) + date: (date [818, 15] - [818, 25])) + (blame_entry [819, 4] - [819, 25] + line: (number [819, 11] - [819, 14]) + date: (date [819, 15] - [819, 25])) + (blame_entry [820, 4] - [820, 25] + line: (number [820, 11] - [820, 14]) + date: (date [820, 15] - [820, 25])) + (blame_entry [821, 4] - [821, 25] + line: (number [821, 11] - [821, 14]) + date: (date [821, 15] - [821, 25]))) + (file_entry [822, 0] - [824, 24] + file_name: (filename [822, 6] - [822, 83]) + (blame_entry [823, 4] - [823, 24] + line: (number [823, 11] - [823, 13]) + date: (date [823, 14] - [823, 24])) + (blame_entry [824, 4] - [824, 24] + line: (number [824, 11] - [824, 13]) + date: (date [824, 14] - [824, 24]))) + (file_entry [825, 0] - [829, 25] + file_name: (filename [825, 6] - [825, 103]) + (blame_entry [826, 4] - [826, 25] + line: (number [826, 11] - [826, 14]) + date: (date [826, 15] - [826, 25])) + (blame_entry [827, 4] - [827, 25] + line: (number [827, 11] - [827, 14]) + date: (date [827, 15] - [827, 25])) + (blame_entry [828, 4] - [828, 25] + line: (number [828, 11] - [828, 14]) + date: (date [828, 15] - [828, 25])) + (blame_entry [829, 4] - [829, 25] + line: (number [829, 11] - [829, 14]) + date: (date [829, 15] - [829, 25]))) + (file_entry [830, 0] - [834, 25] + file_name: (filename [830, 6] - [830, 80]) + (blame_entry [831, 4] - [831, 25] + line: (number [831, 11] - [831, 14]) + date: (date [831, 15] - [831, 25])) + (blame_entry [832, 4] - [832, 25] + line: (number [832, 11] - [832, 14]) + date: (date [832, 15] - [832, 25])) + (blame_entry [833, 4] - [833, 25] + line: (number [833, 11] - [833, 14]) + date: (date [833, 15] - [833, 25])) + (blame_entry [834, 4] - [834, 25] + line: (number [834, 11] - [834, 14]) + date: (date [834, 15] - [834, 25]))) + (file_entry [835, 0] - [836, 23] + file_name: (filename [835, 6] - [835, 65]) + (blame_entry [836, 4] - [836, 23] + line: (number [836, 11] - [836, 12]) + date: (date [836, 13] - [836, 23]))) + (file_entry [837, 0] - [842, 26] + file_name: (filename [837, 6] - [837, 93]) + (blame_entry [838, 4] - [838, 25] + line: (number [838, 11] - [838, 14]) + date: (date [838, 15] - [838, 25])) + (blame_entry [839, 4] - [839, 25] + line: (number [839, 11] - [839, 14]) + date: (date [839, 15] - [839, 25])) + (blame_entry [840, 4] - [840, 26] + line: (number [840, 11] - [840, 15]) + date: (date [840, 16] - [840, 26])) + (blame_entry [841, 4] - [841, 26] + line: (number [841, 11] - [841, 15]) + date: (date [841, 16] - [841, 26])) + (blame_entry [842, 4] - [842, 26] + line: (number [842, 11] - [842, 15]) + date: (date [842, 16] - [842, 26]))) + (file_entry [843, 0] - [844, 24] + file_name: (filename [843, 6] - [843, 70]) + (blame_entry [844, 4] - [844, 24] + line: (number [844, 11] - [844, 13]) + date: (date [844, 14] - [844, 24]))) + (file_entry [845, 0] - [850, 24] + file_name: (filename [845, 6] - [845, 47]) + (blame_entry [846, 4] - [846, 24] + line: (number [846, 11] - [846, 13]) + date: (date [846, 14] - [846, 24])) + (blame_entry [847, 4] - [847, 24] + line: (number [847, 11] - [847, 13]) + date: (date [847, 14] - [847, 24])) + (blame_entry [848, 4] - [848, 24] + line: (number [848, 11] - [848, 13]) + date: (date [848, 14] - [848, 24])) + (blame_entry [849, 4] - [849, 24] + line: (number [849, 11] - [849, 13]) + date: (date [849, 14] - [849, 24])) + (blame_entry [850, 4] - [850, 24] + line: (number [850, 11] - [850, 13]) + date: (date [850, 14] - [850, 24]))) + (file_entry [851, 0] - [853, 25] + file_name: (filename [851, 6] - [851, 71]) + (blame_entry [852, 4] - [852, 25] + line: (number [852, 11] - [852, 14]) + date: (date [852, 15] - [852, 25])) + (blame_entry [853, 4] - [853, 25] + line: (number [853, 11] - [853, 14]) + date: (date [853, 15] - [853, 25]))) + (file_entry [854, 0] - [867, 25] + file_name: (filename [854, 6] - [854, 45]) + (blame_entry [855, 4] - [855, 24] + line: (number [855, 11] - [855, 13]) + date: (date [855, 14] - [855, 24])) + (blame_entry [856, 4] - [856, 24] + line: (number [856, 11] - [856, 13]) + date: (date [856, 14] - [856, 24])) + (blame_entry [857, 4] - [857, 25] + line: (number [857, 11] - [857, 14]) + date: (date [857, 15] - [857, 25])) + (blame_entry [858, 4] - [858, 25] + line: (number [858, 11] - [858, 14]) + date: (date [858, 15] - [858, 25])) + (blame_entry [859, 4] - [859, 25] + line: (number [859, 11] - [859, 14]) + date: (date [859, 15] - [859, 25])) + (blame_entry [860, 4] - [860, 25] + line: (number [860, 11] - [860, 14]) + date: (date [860, 15] - [860, 25])) + (blame_entry [861, 4] - [861, 25] + line: (number [861, 11] - [861, 14]) + date: (date [861, 15] - [861, 25])) + (blame_entry [862, 4] - [862, 25] + line: (number [862, 11] - [862, 14]) + date: (date [862, 15] - [862, 25])) + (blame_entry [863, 4] - [863, 25] + line: (number [863, 11] - [863, 14]) + date: (date [863, 15] - [863, 25])) + (blame_entry [864, 4] - [864, 25] + line: (number [864, 11] - [864, 14]) + date: (date [864, 15] - [864, 25])) + (blame_entry [865, 4] - [865, 25] + line: (number [865, 11] - [865, 14]) + date: (date [865, 15] - [865, 25])) + (blame_entry [866, 4] - [866, 25] + line: (number [866, 11] - [866, 14]) + date: (date [866, 15] - [866, 25])) + (blame_entry [867, 4] - [867, 25] + line: (number [867, 11] - [867, 14]) + date: (date [867, 15] - [867, 25]))) + (file_entry [868, 0] - [870, 24] + file_name: (filename [868, 6] - [868, 47]) + (blame_entry [869, 4] - [869, 24] + line: (number [869, 11] - [869, 13]) + date: (date [869, 14] - [869, 24])) + (blame_entry [870, 4] - [870, 24] + line: (number [870, 11] - [870, 13]) + date: (date [870, 14] - [870, 24]))) + (file_entry [871, 0] - [872, 24] + file_name: (filename [871, 6] - [871, 62]) + (blame_entry [872, 4] - [872, 24] + line: (number [872, 11] - [872, 13]) + date: (date [872, 14] - [872, 24]))) + (file_entry [873, 0] - [874, 24] + file_name: (filename [873, 6] - [873, 71]) + (blame_entry [874, 4] - [874, 24] + line: (number [874, 11] - [874, 13]) + date: (date [874, 14] - [874, 24]))) + (file_entry [875, 0] - [880, 25] + file_name: (filename [875, 6] - [875, 59]) + (blame_entry [876, 4] - [876, 25] + line: (number [876, 11] - [876, 14]) + date: (date [876, 15] - [876, 25])) + (blame_entry [877, 4] - [877, 25] + line: (number [877, 11] - [877, 14]) + date: (date [877, 15] - [877, 25])) + (blame_entry [878, 4] - [878, 25] + line: (number [878, 11] - [878, 14]) + date: (date [878, 15] - [878, 25])) + (blame_entry [879, 4] - [879, 25] + line: (number [879, 11] - [879, 14]) + date: (date [879, 15] - [879, 25])) + (blame_entry [880, 4] - [880, 25] + line: (number [880, 11] - [880, 14]) + date: (date [880, 15] - [880, 25]))) + (file_entry [881, 0] - [883, 24] + file_name: (filename [881, 6] - [881, 74]) + (blame_entry [882, 4] - [882, 23] + line: (number [882, 11] - [882, 12]) + date: (date [882, 13] - [882, 23])) + (blame_entry [883, 4] - [883, 24] + line: (number [883, 11] - [883, 13]) + date: (date [883, 14] - [883, 24]))) + (file_entry [884, 0] - [890, 24] + file_name: (filename [884, 6] - [884, 57]) + (blame_entry [885, 4] - [885, 23] + line: (number [885, 11] - [885, 12]) + date: (date [885, 13] - [885, 23])) + (blame_entry [886, 4] - [886, 23] + line: (number [886, 11] - [886, 12]) + date: (date [886, 13] - [886, 23])) + (blame_entry [887, 4] - [887, 24] + line: (number [887, 11] - [887, 13]) + date: (date [887, 14] - [887, 24])) + (blame_entry [888, 4] - [888, 24] + line: (number [888, 11] - [888, 13]) + date: (date [888, 14] - [888, 24])) + (blame_entry [889, 4] - [889, 24] + line: (number [889, 11] - [889, 13]) + date: (date [889, 14] - [889, 24])) + (blame_entry [890, 4] - [890, 24] + line: (number [890, 11] - [890, 13]) + date: (date [890, 14] - [890, 24]))) + (file_entry [891, 0] - [897, 25] + file_name: (filename [891, 6] - [891, 43]) + (blame_entry [892, 4] - [892, 25] + line: (number [892, 11] - [892, 14]) + date: (date [892, 15] - [892, 25])) + (blame_entry [893, 4] - [893, 25] + line: (number [893, 11] - [893, 14]) + date: (date [893, 15] - [893, 25])) + (blame_entry [894, 4] - [894, 25] + line: (number [894, 11] - [894, 14]) + date: (date [894, 15] - [894, 25])) + (blame_entry [895, 4] - [895, 25] + line: (number [895, 11] - [895, 14]) + date: (date [895, 15] - [895, 25])) + (blame_entry [896, 4] - [896, 25] + line: (number [896, 11] - [896, 14]) + date: (date [896, 15] - [896, 25])) + (blame_entry [897, 4] - [897, 25] + line: (number [897, 11] - [897, 14]) + date: (date [897, 15] - [897, 25]))) + (file_entry [898, 0] - [915, 25] + file_name: (filename [898, 6] - [898, 54]) + (blame_entry [899, 4] - [899, 25] + line: (number [899, 11] - [899, 14]) + date: (date [899, 15] - [899, 25])) + (blame_entry [900, 4] - [900, 25] + line: (number [900, 11] - [900, 14]) + date: (date [900, 15] - [900, 25])) + (blame_entry [901, 4] - [901, 25] + line: (number [901, 11] - [901, 14]) + date: (date [901, 15] - [901, 25])) + (blame_entry [902, 4] - [902, 25] + line: (number [902, 11] - [902, 14]) + date: (date [902, 15] - [902, 25])) + (blame_entry [903, 4] - [903, 25] + line: (number [903, 11] - [903, 14]) + date: (date [903, 15] - [903, 25])) + (blame_entry [904, 4] - [904, 25] + line: (number [904, 11] - [904, 14]) + date: (date [904, 15] - [904, 25])) + (blame_entry [905, 4] - [905, 25] + line: (number [905, 11] - [905, 14]) + date: (date [905, 15] - [905, 25])) + (blame_entry [906, 4] - [906, 25] + line: (number [906, 11] - [906, 14]) + date: (date [906, 15] - [906, 25])) + (blame_entry [907, 4] - [907, 25] + line: (number [907, 11] - [907, 14]) + date: (date [907, 15] - [907, 25])) + (blame_entry [908, 4] - [908, 25] + line: (number [908, 11] - [908, 14]) + date: (date [908, 15] - [908, 25])) + (blame_entry [909, 4] - [909, 25] + line: (number [909, 11] - [909, 14]) + date: (date [909, 15] - [909, 25])) + (blame_entry [910, 4] - [910, 25] + line: (number [910, 11] - [910, 14]) + date: (date [910, 15] - [910, 25])) + (blame_entry [911, 4] - [911, 25] + line: (number [911, 11] - [911, 14]) + date: (date [911, 15] - [911, 25])) + (blame_entry [912, 4] - [912, 25] + line: (number [912, 11] - [912, 14]) + date: (date [912, 15] - [912, 25])) + (blame_entry [913, 4] - [913, 25] + line: (number [913, 11] - [913, 14]) + date: (date [913, 15] - [913, 25])) + (blame_entry [914, 4] - [914, 25] + line: (number [914, 11] - [914, 14]) + date: (date [914, 15] - [914, 25])) + (blame_entry [915, 4] - [915, 25] + line: (number [915, 11] - [915, 14]) + date: (date [915, 15] - [915, 25]))) + (file_entry [916, 0] - [919, 24] + file_name: (filename [916, 6] - [916, 68]) + (blame_entry [917, 4] - [917, 23] + line: (number [917, 11] - [917, 12]) + date: (date [917, 13] - [917, 23])) + (blame_entry [918, 4] - [918, 24] + line: (number [918, 11] - [918, 13]) + date: (date [918, 14] - [918, 24])) + (blame_entry [919, 4] - [919, 24] + line: (number [919, 11] - [919, 13]) + date: (date [919, 14] - [919, 24]))) + (file_entry [920, 0] - [921, 23] + file_name: (filename [920, 6] - [920, 84]) + (blame_entry [921, 4] - [921, 23] + line: (number [921, 11] - [921, 12]) + date: (date [921, 13] - [921, 23]))) + (file_entry [922, 0] - [923, 24] + file_name: (filename [922, 6] - [922, 60]) + (blame_entry [923, 4] - [923, 24] + line: (number [923, 11] - [923, 13]) + date: (date [923, 14] - [923, 24]))) + (file_entry [924, 0] - [925, 24] + file_name: (filename [924, 6] - [924, 74]) + (blame_entry [925, 4] - [925, 24] + line: (number [925, 11] - [925, 13]) + date: (date [925, 14] - [925, 24]))) + (file_entry [926, 0] - [931, 24] + file_name: (filename [926, 6] - [926, 51]) + (blame_entry [927, 4] - [927, 23] + line: (number [927, 11] - [927, 12]) + date: (date [927, 13] - [927, 23])) + (blame_entry [928, 4] - [928, 24] + line: (number [928, 11] - [928, 13]) + date: (date [928, 14] - [928, 24])) + (blame_entry [929, 4] - [929, 24] + line: (number [929, 11] - [929, 13]) + date: (date [929, 14] - [929, 24])) + (blame_entry [930, 4] - [930, 24] + line: (number [930, 11] - [930, 13]) + date: (date [930, 14] - [930, 24])) + (blame_entry [931, 4] - [931, 24] + line: (number [931, 11] - [931, 13]) + date: (date [931, 14] - [931, 24]))) + (file_entry [932, 0] - [933, 23] + file_name: (filename [932, 6] - [932, 59]) + (blame_entry [933, 4] - [933, 23] + line: (number [933, 11] - [933, 12]) + date: (date [933, 13] - [933, 23]))) + (file_entry [934, 0] - [935, 25] + file_name: (filename [934, 6] - [934, 51]) + (blame_entry [935, 4] - [935, 25] + line: (number [935, 11] - [935, 14]) + date: (date [935, 15] - [935, 25]))) + (file_entry [936, 0] - [940, 25] + file_name: (filename [936, 6] - [936, 69]) + (blame_entry [937, 4] - [937, 24] + line: (number [937, 11] - [937, 13]) + date: (date [937, 14] - [937, 24])) + (blame_entry [938, 4] - [938, 25] + line: (number [938, 11] - [938, 14]) + date: (date [938, 15] - [938, 25])) + (blame_entry [939, 4] - [939, 25] + line: (number [939, 11] - [939, 14]) + date: (date [939, 15] - [939, 25])) + (blame_entry [940, 4] - [940, 25] + line: (number [940, 11] - [940, 14]) + date: (date [940, 15] - [940, 25]))) + (file_entry [941, 0] - [942, 23] + file_name: (filename [941, 6] - [941, 84]) + (blame_entry [942, 4] - [942, 23] + line: (number [942, 11] - [942, 12]) + date: (date [942, 13] - [942, 23]))) + (file_entry [943, 0] - [944, 26] + file_name: (filename [943, 6] - [943, 58]) + (blame_entry [944, 4] - [944, 26] + line: (number [944, 11] - [944, 15]) + date: (date [944, 16] - [944, 26]))) + (file_entry [945, 0] - [947, 25] + file_name: (filename [945, 6] - [945, 56]) + (blame_entry [946, 4] - [946, 24] + line: (number [946, 11] - [946, 13]) + date: (date [946, 14] - [946, 24])) + (blame_entry [947, 4] - [947, 25] + line: (number [947, 11] - [947, 14]) + date: (date [947, 15] - [947, 25]))) + (file_entry [948, 0] - [953, 25] + file_name: (filename [948, 6] - [948, 98]) + (blame_entry [949, 4] - [949, 24] + line: (number [949, 11] - [949, 13]) + date: (date [949, 14] - [949, 24])) + (blame_entry [950, 4] - [950, 24] + line: (number [950, 11] - [950, 13]) + date: (date [950, 14] - [950, 24])) + (blame_entry [951, 4] - [951, 25] + line: (number [951, 11] - [951, 14]) + date: (date [951, 15] - [951, 25])) + (blame_entry [952, 4] - [952, 25] + line: (number [952, 11] - [952, 14]) + date: (date [952, 15] - [952, 25])) + (blame_entry [953, 4] - [953, 25] + line: (number [953, 11] - [953, 14]) + date: (date [953, 15] - [953, 25]))) + (file_entry [954, 0] - [955, 25] + file_name: (filename [954, 6] - [954, 68]) + (blame_entry [955, 4] - [955, 25] + line: (number [955, 11] - [955, 14]) + date: (date [955, 15] - [955, 25]))) + (file_entry [956, 0] - [957, 24] + file_name: (filename [956, 6] - [956, 94]) + (blame_entry [957, 4] - [957, 24] + line: (number [957, 11] - [957, 13]) + date: (date [957, 14] - [957, 24]))) + (file_entry [958, 0] - [959, 23] + file_name: (filename [958, 6] - [958, 67]) + (blame_entry [959, 4] - [959, 23] + line: (number [959, 11] - [959, 12]) + date: (date [959, 13] - [959, 23]))) + (file_entry [960, 0] - [966, 26] + file_name: (filename [960, 6] - [960, 55]) + (blame_entry [961, 4] - [961, 26] + line: (number [961, 11] - [961, 15]) + date: (date [961, 16] - [961, 26])) + (blame_entry [962, 4] - [962, 26] + line: (number [962, 11] - [962, 15]) + date: (date [962, 16] - [962, 26])) + (blame_entry [963, 4] - [963, 26] + line: (number [963, 11] - [963, 15]) + date: (date [963, 16] - [963, 26])) + (blame_entry [964, 4] - [964, 26] + line: (number [964, 11] - [964, 15]) + date: (date [964, 16] - [964, 26])) + (blame_entry [965, 4] - [965, 26] + line: (number [965, 11] - [965, 15]) + date: (date [965, 16] - [965, 26])) + (blame_entry [966, 4] - [966, 26] + line: (number [966, 11] - [966, 15]) + date: (date [966, 16] - [966, 26]))) + (file_entry [967, 0] - [973, 24] + file_name: (filename [967, 6] - [967, 60]) + (blame_entry [968, 4] - [968, 24] + line: (number [968, 11] - [968, 13]) + date: (date [968, 14] - [968, 24])) + (blame_entry [969, 4] - [969, 24] + line: (number [969, 11] - [969, 13]) + date: (date [969, 14] - [969, 24])) + (blame_entry [970, 4] - [970, 24] + line: (number [970, 11] - [970, 13]) + date: (date [970, 14] - [970, 24])) + (blame_entry [971, 4] - [971, 24] + line: (number [971, 11] - [971, 13]) + date: (date [971, 14] - [971, 24])) + (blame_entry [972, 4] - [972, 24] + line: (number [972, 11] - [972, 13]) + date: (date [972, 14] - [972, 24])) + (blame_entry [973, 4] - [973, 24] + line: (number [973, 11] - [973, 13]) + date: (date [973, 14] - [973, 24]))) + (file_entry [974, 0] - [976, 24] + file_name: (filename [974, 6] - [974, 70]) + (blame_entry [975, 4] - [975, 24] + line: (number [975, 11] - [975, 13]) + date: (date [975, 14] - [975, 24])) + (blame_entry [976, 4] - [976, 24] + line: (number [976, 11] - [976, 13]) + date: (date [976, 14] - [976, 24]))) + (file_entry [977, 0] - [978, 23] + file_name: (filename [977, 6] - [977, 68]) + (blame_entry [978, 4] - [978, 23] + line: (number [978, 11] - [978, 12]) + date: (date [978, 13] - [978, 23]))) + (file_entry [979, 0] - [980, 25] + file_name: (filename [979, 6] - [979, 50]) + (blame_entry [980, 4] - [980, 25] + line: (number [980, 11] - [980, 14]) + date: (date [980, 15] - [980, 25]))) + (file_entry [981, 0] - [984, 25] + file_name: (filename [981, 6] - [981, 74]) + (blame_entry [982, 4] - [982, 24] + line: (number [982, 11] - [982, 13]) + date: (date [982, 14] - [982, 24])) + (blame_entry [983, 4] - [983, 24] + line: (number [983, 11] - [983, 13]) + date: (date [983, 14] - [983, 24])) + (blame_entry [984, 4] - [984, 25] + line: (number [984, 11] - [984, 14]) + date: (date [984, 15] - [984, 25]))) + (file_entry [985, 0] - [993, 25] + file_name: (filename [985, 6] - [985, 69]) + (blame_entry [986, 4] - [986, 23] + line: (number [986, 11] - [986, 12]) + date: (date [986, 13] - [986, 23])) + (blame_entry [987, 4] - [987, 24] + line: (number [987, 11] - [987, 13]) + date: (date [987, 14] - [987, 24])) + (blame_entry [988, 4] - [988, 24] + line: (number [988, 11] - [988, 13]) + date: (date [988, 14] - [988, 24])) + (blame_entry [989, 4] - [989, 24] + line: (number [989, 11] - [989, 13]) + date: (date [989, 14] - [989, 24])) + (blame_entry [990, 4] - [990, 24] + line: (number [990, 11] - [990, 13]) + date: (date [990, 14] - [990, 24])) + (blame_entry [991, 4] - [991, 24] + line: (number [991, 11] - [991, 13]) + date: (date [991, 14] - [991, 24])) + (blame_entry [992, 4] - [992, 25] + line: (number [992, 11] - [992, 14]) + date: (date [992, 15] - [992, 25])) + (blame_entry [993, 4] - [993, 25] + line: (number [993, 11] - [993, 14]) + date: (date [993, 15] - [993, 25]))) + (file_entry [994, 0] - [998, 25] + file_name: (filename [994, 6] - [994, 81]) + (blame_entry [995, 4] - [995, 24] + line: (number [995, 11] - [995, 13]) + date: (date [995, 14] - [995, 24])) + (blame_entry [996, 4] - [996, 25] + line: (number [996, 11] - [996, 14]) + date: (date [996, 15] - [996, 25])) + (blame_entry [997, 4] - [997, 25] + line: (number [997, 11] - [997, 14]) + date: (date [997, 15] - [997, 25])) + (blame_entry [998, 4] - [998, 25] + line: (number [998, 11] - [998, 14]) + date: (date [998, 15] - [998, 25]))) + (file_entry [999, 0] - [1003, 25] + file_name: (filename [999, 6] - [999, 72]) + (blame_entry [1000, 4] - [1000, 24] + line: (number [1000, 11] - [1000, 13]) + date: (date [1000, 14] - [1000, 24])) + (blame_entry [1001, 4] - [1001, 25] + line: (number [1001, 11] - [1001, 14]) + date: (date [1001, 15] - [1001, 25])) + (blame_entry [1002, 4] - [1002, 25] + line: (number [1002, 11] - [1002, 14]) + date: (date [1002, 15] - [1002, 25])) + (blame_entry [1003, 4] - [1003, 25] + line: (number [1003, 11] - [1003, 14]) + date: (date [1003, 15] - [1003, 25]))) + (file_entry [1004, 0] - [1005, 25] + file_name: (filename [1004, 6] - [1004, 67]) + (blame_entry [1005, 4] - [1005, 25] + line: (number [1005, 11] - [1005, 14]) + date: (date [1005, 15] - [1005, 25]))) + (file_entry [1006, 0] - [1007, 25] + file_name: (filename [1006, 6] - [1006, 109]) + (blame_entry [1007, 4] - [1007, 25] + line: (number [1007, 11] - [1007, 14]) + date: (date [1007, 15] - [1007, 25]))) + (file_entry [1008, 0] - [1010, 25] + file_name: (filename [1008, 6] - [1008, 73]) + (blame_entry [1009, 4] - [1009, 24] + line: (number [1009, 11] - [1009, 13]) + date: (date [1009, 14] - [1009, 24])) + (blame_entry [1010, 4] - [1010, 25] + line: (number [1010, 11] - [1010, 14]) + date: (date [1010, 15] - [1010, 25]))) + (file_entry [1011, 0] - [1015, 25] + file_name: (filename [1011, 6] - [1011, 74]) + (blame_entry [1012, 4] - [1012, 24] + line: (number [1012, 11] - [1012, 13]) + date: (date [1012, 14] - [1012, 24])) + (blame_entry [1013, 4] - [1013, 25] + line: (number [1013, 11] - [1013, 14]) + date: (date [1013, 15] - [1013, 25])) + (blame_entry [1014, 4] - [1014, 25] + line: (number [1014, 11] - [1014, 14]) + date: (date [1014, 15] - [1014, 25])) + (blame_entry [1015, 4] - [1015, 25] + line: (number [1015, 11] - [1015, 14]) + date: (date [1015, 15] - [1015, 25]))) + (file_entry [1016, 0] - [1017, 24] + file_name: (filename [1016, 6] - [1016, 51]) + (blame_entry [1017, 4] - [1017, 24] + line: (number [1017, 11] - [1017, 13]) + date: (date [1017, 14] - [1017, 24]))) + (file_entry [1018, 0] - [1019, 23] + file_name: (filename [1018, 6] - [1018, 60]) + (blame_entry [1019, 4] - [1019, 23] + line: (number [1019, 11] - [1019, 12]) + date: (date [1019, 13] - [1019, 23]))) + (file_entry [1020, 0] - [1021, 25] + file_name: (filename [1020, 6] - [1020, 54]) + (blame_entry [1021, 4] - [1021, 25] + line: (number [1021, 11] - [1021, 14]) + date: (date [1021, 15] - [1021, 25]))) + (file_entry [1022, 0] - [1027, 24] + file_name: (filename [1022, 6] - [1022, 56]) + (blame_entry [1023, 4] - [1023, 23] + line: (number [1023, 11] - [1023, 12]) + date: (date [1023, 13] - [1023, 23])) + (blame_entry [1024, 4] - [1024, 24] + line: (number [1024, 11] - [1024, 13]) + date: (date [1024, 14] - [1024, 24])) + (blame_entry [1025, 4] - [1025, 24] + line: (number [1025, 11] - [1025, 13]) + date: (date [1025, 14] - [1025, 24])) + (blame_entry [1026, 4] - [1026, 24] + line: (number [1026, 11] - [1026, 13]) + date: (date [1026, 14] - [1026, 24])) + (blame_entry [1027, 4] - [1027, 24] + line: (number [1027, 11] - [1027, 13]) + date: (date [1027, 14] - [1027, 24]))) + (file_entry [1028, 0] - [1032, 25] + file_name: (filename [1028, 6] - [1028, 70]) + (blame_entry [1029, 4] - [1029, 24] + line: (number [1029, 11] - [1029, 13]) + date: (date [1029, 14] - [1029, 24])) + (blame_entry [1030, 4] - [1030, 25] + line: (number [1030, 11] - [1030, 14]) + date: (date [1030, 15] - [1030, 25])) + (blame_entry [1031, 4] - [1031, 25] + line: (number [1031, 11] - [1031, 14]) + date: (date [1031, 15] - [1031, 25])) + (blame_entry [1032, 4] - [1032, 25] + line: (number [1032, 11] - [1032, 14]) + date: (date [1032, 15] - [1032, 25]))) + (file_entry [1033, 0] - [1047, 25] + file_name: (filename [1033, 6] - [1033, 64]) + (blame_entry [1034, 4] - [1034, 24] + line: (number [1034, 11] - [1034, 13]) + date: (date [1034, 14] - [1034, 24])) + (blame_entry [1035, 4] - [1035, 24] + line: (number [1035, 11] - [1035, 13]) + date: (date [1035, 14] - [1035, 24])) + (blame_entry [1036, 4] - [1036, 24] + line: (number [1036, 11] - [1036, 13]) + date: (date [1036, 14] - [1036, 24])) + (blame_entry [1037, 4] - [1037, 24] + line: (number [1037, 11] - [1037, 13]) + date: (date [1037, 14] - [1037, 24])) + (blame_entry [1038, 4] - [1038, 24] + line: (number [1038, 11] - [1038, 13]) + date: (date [1038, 14] - [1038, 24])) + (blame_entry [1039, 4] - [1039, 24] + line: (number [1039, 11] - [1039, 13]) + date: (date [1039, 14] - [1039, 24])) + (blame_entry [1040, 4] - [1040, 24] + line: (number [1040, 11] - [1040, 13]) + date: (date [1040, 14] - [1040, 24])) + (blame_entry [1041, 4] - [1041, 25] + line: (number [1041, 11] - [1041, 14]) + date: (date [1041, 15] - [1041, 25])) + (blame_entry [1042, 4] - [1042, 25] + line: (number [1042, 11] - [1042, 14]) + date: (date [1042, 15] - [1042, 25])) + (blame_entry [1043, 4] - [1043, 25] + line: (number [1043, 11] - [1043, 14]) + date: (date [1043, 15] - [1043, 25])) + (blame_entry [1044, 4] - [1044, 25] + line: (number [1044, 11] - [1044, 14]) + date: (date [1044, 15] - [1044, 25])) + (blame_entry [1045, 4] - [1045, 25] + line: (number [1045, 11] - [1045, 14]) + date: (date [1045, 15] - [1045, 25])) + (blame_entry [1046, 4] - [1046, 25] + line: (number [1046, 11] - [1046, 14]) + date: (date [1046, 15] - [1046, 25])) + (blame_entry [1047, 4] - [1047, 25] + line: (number [1047, 11] - [1047, 14]) + date: (date [1047, 15] - [1047, 25]))) + (file_entry [1048, 0] - [1052, 25] + file_name: (filename [1048, 6] - [1048, 90]) + (blame_entry [1049, 4] - [1049, 25] + line: (number [1049, 11] - [1049, 14]) + date: (date [1049, 15] - [1049, 25])) + (blame_entry [1050, 4] - [1050, 25] + line: (number [1050, 11] - [1050, 14]) + date: (date [1050, 15] - [1050, 25])) + (blame_entry [1051, 4] - [1051, 25] + line: (number [1051, 11] - [1051, 14]) + date: (date [1051, 15] - [1051, 25])) + (blame_entry [1052, 4] - [1052, 25] + line: (number [1052, 11] - [1052, 14]) + date: (date [1052, 15] - [1052, 25]))) + (file_entry [1053, 0] - [1057, 25] + file_name: (filename [1053, 6] - [1053, 70]) + (blame_entry [1054, 4] - [1054, 24] + line: (number [1054, 11] - [1054, 13]) + date: (date [1054, 14] - [1054, 24])) + (blame_entry [1055, 4] - [1055, 25] + line: (number [1055, 11] - [1055, 14]) + date: (date [1055, 15] - [1055, 25])) + (blame_entry [1056, 4] - [1056, 25] + line: (number [1056, 11] - [1056, 14]) + date: (date [1056, 15] - [1056, 25])) + (blame_entry [1057, 4] - [1057, 25] + line: (number [1057, 11] - [1057, 14]) + date: (date [1057, 15] - [1057, 25]))) + (file_entry [1058, 0] - [1060, 25] + file_name: (filename [1058, 6] - [1058, 85]) + (blame_entry [1059, 4] - [1059, 25] + line: (number [1059, 11] - [1059, 14]) + date: (date [1059, 15] - [1059, 25])) + (blame_entry [1060, 4] - [1060, 25] + line: (number [1060, 11] - [1060, 14]) + date: (date [1060, 15] - [1060, 25]))) + (file_entry [1061, 0] - [1064, 25] + file_name: (filename [1061, 6] - [1061, 77]) + (blame_entry [1062, 4] - [1062, 24] + line: (number [1062, 11] - [1062, 13]) + date: (date [1062, 14] - [1062, 24])) + (blame_entry [1063, 4] - [1063, 24] + line: (number [1063, 11] - [1063, 13]) + date: (date [1063, 14] - [1063, 24])) + (blame_entry [1064, 4] - [1064, 25] + line: (number [1064, 11] - [1064, 14]) + date: (date [1064, 15] - [1064, 25]))) + (file_entry [1065, 0] - [1069, 25] + file_name: (filename [1065, 6] - [1065, 81]) + (blame_entry [1066, 4] - [1066, 24] + line: (number [1066, 11] - [1066, 13]) + date: (date [1066, 14] - [1066, 24])) + (blame_entry [1067, 4] - [1067, 25] + line: (number [1067, 11] - [1067, 14]) + date: (date [1067, 15] - [1067, 25])) + (blame_entry [1068, 4] - [1068, 25] + line: (number [1068, 11] - [1068, 14]) + date: (date [1068, 15] - [1068, 25])) + (blame_entry [1069, 4] - [1069, 25] + line: (number [1069, 11] - [1069, 14]) + date: (date [1069, 15] - [1069, 25]))) + (file_entry [1070, 0] - [1071, 24] + file_name: (filename [1070, 6] - [1070, 73]) + (blame_entry [1071, 4] - [1071, 24] + line: (number [1071, 11] - [1071, 13]) + date: (date [1071, 14] - [1071, 24]))) + (file_entry [1072, 0] - [1073, 24] + file_name: (filename [1072, 6] - [1072, 49]) + (blame_entry [1073, 4] - [1073, 24] + line: (number [1073, 11] - [1073, 13]) + date: (date [1073, 14] - [1073, 24]))) + (file_entry [1074, 0] - [1076, 25] + file_name: (filename [1074, 6] - [1074, 52]) + (blame_entry [1075, 4] - [1075, 25] + line: (number [1075, 11] - [1075, 14]) + date: (date [1075, 15] - [1075, 25])) + (blame_entry [1076, 4] - [1076, 25] + line: (number [1076, 11] - [1076, 14]) + date: (date [1076, 15] - [1076, 25]))) + (file_entry [1077, 0] - [1079, 24] + file_name: (filename [1077, 6] - [1077, 57]) + (blame_entry [1078, 4] - [1078, 24] + line: (number [1078, 11] - [1078, 13]) + date: (date [1078, 14] - [1078, 24])) + (blame_entry [1079, 4] - [1079, 24] + line: (number [1079, 11] - [1079, 13]) + date: (date [1079, 14] - [1079, 24]))) + (file_entry [1080, 0] - [1081, 24] + file_name: (filename [1080, 6] - [1080, 68]) + (blame_entry [1081, 4] - [1081, 24] + line: (number [1081, 11] - [1081, 13]) + date: (date [1081, 14] - [1081, 24]))) + (file_entry [1082, 0] - [1086, 25] + file_name: (filename [1082, 6] - [1082, 74]) + (blame_entry [1083, 4] - [1083, 24] + line: (number [1083, 11] - [1083, 13]) + date: (date [1083, 14] - [1083, 24])) + (blame_entry [1084, 4] - [1084, 25] + line: (number [1084, 11] - [1084, 14]) + date: (date [1084, 15] - [1084, 25])) + (blame_entry [1085, 4] - [1085, 25] + line: (number [1085, 11] - [1085, 14]) + date: (date [1085, 15] - [1085, 25])) + (blame_entry [1086, 4] - [1086, 25] + line: (number [1086, 11] - [1086, 14]) + date: (date [1086, 15] - [1086, 25]))) + (file_entry [1087, 0] - [1091, 25] + file_name: (filename [1087, 6] - [1087, 73]) + (blame_entry [1088, 4] - [1088, 24] + line: (number [1088, 11] - [1088, 13]) + date: (date [1088, 14] - [1088, 24])) + (blame_entry [1089, 4] - [1089, 25] + line: (number [1089, 11] - [1089, 14]) + date: (date [1089, 15] - [1089, 25])) + (blame_entry [1090, 4] - [1090, 25] + line: (number [1090, 11] - [1090, 14]) + date: (date [1090, 15] - [1090, 25])) + (blame_entry [1091, 4] - [1091, 25] + line: (number [1091, 11] - [1091, 14]) + date: (date [1091, 15] - [1091, 25]))) + (file_entry [1092, 0] - [1100, 25] + file_name: (filename [1092, 6] - [1092, 69]) + (blame_entry [1093, 4] - [1093, 23] + line: (number [1093, 11] - [1093, 12]) + date: (date [1093, 13] - [1093, 23])) + (blame_entry [1094, 4] - [1094, 24] + line: (number [1094, 11] - [1094, 13]) + date: (date [1094, 14] - [1094, 24])) + (blame_entry [1095, 4] - [1095, 25] + line: (number [1095, 11] - [1095, 14]) + date: (date [1095, 15] - [1095, 25])) + (blame_entry [1096, 4] - [1096, 25] + line: (number [1096, 11] - [1096, 14]) + date: (date [1096, 15] - [1096, 25])) + (blame_entry [1097, 4] - [1097, 25] + line: (number [1097, 11] - [1097, 14]) + date: (date [1097, 15] - [1097, 25])) + (blame_entry [1098, 4] - [1098, 25] + line: (number [1098, 11] - [1098, 14]) + date: (date [1098, 15] - [1098, 25])) + (blame_entry [1099, 4] - [1099, 25] + line: (number [1099, 11] - [1099, 14]) + date: (date [1099, 15] - [1099, 25])) + (blame_entry [1100, 4] - [1100, 25] + line: (number [1100, 11] - [1100, 14]) + date: (date [1100, 15] - [1100, 25]))) + (file_entry [1101, 0] - [1102, 24] + file_name: (filename [1101, 6] - [1101, 72]) + (blame_entry [1102, 4] - [1102, 24] + line: (number [1102, 11] - [1102, 13]) + date: (date [1102, 14] - [1102, 24]))) + (file_entry [1103, 0] - [1106, 25] + file_name: (filename [1103, 6] - [1103, 45]) + (blame_entry [1104, 4] - [1104, 25] + line: (number [1104, 11] - [1104, 14]) + date: (date [1104, 15] - [1104, 25])) + (blame_entry [1105, 4] - [1105, 25] + line: (number [1105, 11] - [1105, 14]) + date: (date [1105, 15] - [1105, 25])) + (blame_entry [1106, 4] - [1106, 25] + line: (number [1106, 11] - [1106, 14]) + date: (date [1106, 15] - [1106, 25]))) + (file_entry [1107, 0] - [1111, 24] + file_name: (filename [1107, 6] - [1107, 57]) + (blame_entry [1108, 4] - [1108, 23] + line: (number [1108, 11] - [1108, 12]) + date: (date [1108, 13] - [1108, 23])) + (blame_entry [1109, 4] - [1109, 24] + line: (number [1109, 11] - [1109, 13]) + date: (date [1109, 14] - [1109, 24])) + (blame_entry [1110, 4] - [1110, 24] + line: (number [1110, 11] - [1110, 13]) + date: (date [1110, 14] - [1110, 24])) + (blame_entry [1111, 4] - [1111, 24] + line: (number [1111, 11] - [1111, 13]) + date: (date [1111, 14] - [1111, 24]))) + (file_entry [1112, 0] - [1113, 24] + file_name: (filename [1112, 6] - [1112, 72]) + (blame_entry [1113, 4] - [1113, 24] + line: (number [1113, 11] - [1113, 13]) + date: (date [1113, 14] - [1113, 24]))) + (file_entry [1114, 0] - [1115, 24] + file_name: (filename [1114, 6] - [1114, 72]) + (blame_entry [1115, 4] - [1115, 24] + line: (number [1115, 11] - [1115, 13]) + date: (date [1115, 14] - [1115, 24]))) + (file_entry [1116, 0] - [1118, 24] + file_name: (filename [1116, 6] - [1116, 96]) + (blame_entry [1117, 4] - [1117, 23] + line: (number [1117, 11] - [1117, 12]) + date: (date [1117, 13] - [1117, 23])) + (blame_entry [1118, 4] - [1118, 24] + line: (number [1118, 11] - [1118, 13]) + date: (date [1118, 14] - [1118, 24]))) + (file_entry [1119, 0] - [1120, 23] + file_name: (filename [1119, 6] - [1119, 75]) + (blame_entry [1120, 4] - [1120, 23] + line: (number [1120, 11] - [1120, 12]) + date: (date [1120, 13] - [1120, 23]))) + (file_entry [1121, 0] - [1122, 23] + file_name: (filename [1121, 6] - [1121, 54]) + (blame_entry [1122, 4] - [1122, 23] + line: (number [1122, 11] - [1122, 12]) + date: (date [1122, 13] - [1122, 23]))) + (file_entry [1123, 0] - [1124, 24] + file_name: (filename [1123, 6] - [1123, 70]) + (blame_entry [1124, 4] - [1124, 24] + line: (number [1124, 11] - [1124, 13]) + date: (date [1124, 14] - [1124, 24]))) + (file_entry [1125, 0] - [1126, 25] + file_name: (filename [1125, 6] - [1125, 71]) + (blame_entry [1126, 4] - [1126, 25] + line: (number [1126, 11] - [1126, 14]) + date: (date [1126, 15] - [1126, 25]))) + (file_entry [1127, 0] - [1131, 25] + file_name: (filename [1127, 6] - [1127, 47]) + (blame_entry [1128, 4] - [1128, 25] + line: (number [1128, 11] - [1128, 14]) + date: (date [1128, 15] - [1128, 25])) + (blame_entry [1129, 4] - [1129, 25] + line: (number [1129, 11] - [1129, 14]) + date: (date [1129, 15] - [1129, 25])) + (blame_entry [1130, 4] - [1130, 25] + line: (number [1130, 11] - [1130, 14]) + date: (date [1130, 15] - [1130, 25])) + (blame_entry [1131, 4] - [1131, 25] + line: (number [1131, 11] - [1131, 14]) + date: (date [1131, 15] - [1131, 25]))) + (file_entry [1132, 0] - [1134, 24] + file_name: (filename [1132, 6] - [1132, 58]) + (blame_entry [1133, 4] - [1133, 24] + line: (number [1133, 11] - [1133, 13]) + date: (date [1133, 14] - [1133, 24])) + (blame_entry [1134, 4] - [1134, 24] + line: (number [1134, 11] - [1134, 13]) + date: (date [1134, 14] - [1134, 24]))) + (file_entry [1135, 0] - [1136, 25] + file_name: (filename [1135, 6] - [1135, 46]) + (blame_entry [1136, 4] - [1136, 25] + line: (number [1136, 11] - [1136, 14]) + date: (date [1136, 15] - [1136, 25]))) + (file_entry [1137, 0] - [1138, 25] + file_name: (filename [1137, 6] - [1137, 89]) + (blame_entry [1138, 4] - [1138, 25] + line: (number [1138, 11] - [1138, 14]) + date: (date [1138, 15] - [1138, 25]))) + (file_entry [1139, 0] - [1141, 24] + file_name: (filename [1139, 6] - [1139, 73]) + (blame_entry [1140, 4] - [1140, 24] + line: (number [1140, 11] - [1140, 13]) + date: (date [1140, 14] - [1140, 24])) + (blame_entry [1141, 4] - [1141, 24] + line: (number [1141, 11] - [1141, 13]) + date: (date [1141, 14] - [1141, 24]))) + (file_entry [1142, 0] - [1144, 24] + file_name: (filename [1142, 6] - [1142, 57]) + (blame_entry [1143, 4] - [1143, 24] + line: (number [1143, 11] - [1143, 13]) + date: (date [1143, 14] - [1143, 24])) + (blame_entry [1144, 4] - [1144, 24] + line: (number [1144, 11] - [1144, 13]) + date: (date [1144, 14] - [1144, 24]))) + (file_entry [1145, 0] - [1154, 25] + file_name: (filename [1145, 6] - [1145, 50]) + (blame_entry [1146, 4] - [1146, 24] + line: (number [1146, 11] - [1146, 13]) + date: (date [1146, 14] - [1146, 24])) + (blame_entry [1147, 4] - [1147, 24] + line: (number [1147, 11] - [1147, 13]) + date: (date [1147, 14] - [1147, 24])) + (blame_entry [1148, 4] - [1148, 25] + line: (number [1148, 11] - [1148, 14]) + date: (date [1148, 15] - [1148, 25])) + (blame_entry [1149, 4] - [1149, 25] + line: (number [1149, 11] - [1149, 14]) + date: (date [1149, 15] - [1149, 25])) + (blame_entry [1150, 4] - [1150, 25] + line: (number [1150, 11] - [1150, 14]) + date: (date [1150, 15] - [1150, 25])) + (blame_entry [1151, 4] - [1151, 25] + line: (number [1151, 11] - [1151, 14]) + date: (date [1151, 15] - [1151, 25])) + (blame_entry [1152, 4] - [1152, 25] + line: (number [1152, 11] - [1152, 14]) + date: (date [1152, 15] - [1152, 25])) + (blame_entry [1153, 4] - [1153, 25] + line: (number [1153, 11] - [1153, 14]) + date: (date [1153, 15] - [1153, 25])) + (blame_entry [1154, 4] - [1154, 25] + line: (number [1154, 11] - [1154, 14]) + date: (date [1154, 15] - [1154, 25]))) + (file_entry [1155, 0] - [1158, 25] + file_name: (filename [1155, 6] - [1155, 101]) + (blame_entry [1156, 4] - [1156, 24] + line: (number [1156, 11] - [1156, 13]) + date: (date [1156, 14] - [1156, 24])) + (blame_entry [1157, 4] - [1157, 24] + line: (number [1157, 11] - [1157, 13]) + date: (date [1157, 14] - [1157, 24])) + (blame_entry [1158, 4] - [1158, 25] + line: (number [1158, 11] - [1158, 14]) + date: (date [1158, 15] - [1158, 25]))) + (file_entry [1159, 0] - [1162, 24] + file_name: (filename [1159, 6] - [1159, 58]) + (blame_entry [1160, 4] - [1160, 23] + line: (number [1160, 11] - [1160, 12]) + date: (date [1160, 13] - [1160, 23])) + (blame_entry [1161, 4] - [1161, 23] + line: (number [1161, 11] - [1161, 12]) + date: (date [1161, 13] - [1161, 23])) + (blame_entry [1162, 4] - [1162, 24] + line: (number [1162, 11] - [1162, 13]) + date: (date [1162, 14] - [1162, 24]))) + (file_entry [1163, 0] - [1164, 24] + file_name: (filename [1163, 6] - [1163, 91]) + (blame_entry [1164, 4] - [1164, 24] + line: (number [1164, 11] - [1164, 13]) + date: (date [1164, 14] - [1164, 24]))) + (file_entry [1165, 0] - [1167, 24] + file_name: (filename [1165, 6] - [1165, 80]) + (blame_entry [1166, 4] - [1166, 24] + line: (number [1166, 11] - [1166, 13]) + date: (date [1166, 14] - [1166, 24])) + (blame_entry [1167, 4] - [1167, 24] + line: (number [1167, 11] - [1167, 13]) + date: (date [1167, 14] - [1167, 24]))) + (file_entry [1168, 0] - [1169, 25] + file_name: (filename [1168, 6] - [1168, 68]) + (blame_entry [1169, 4] - [1169, 25] + line: (number [1169, 11] - [1169, 14]) + date: (date [1169, 15] - [1169, 25]))) + (file_entry [1170, 0] - [1172, 24] + file_name: (filename [1170, 6] - [1170, 57]) + (blame_entry [1171, 4] - [1171, 24] + line: (number [1171, 11] - [1171, 13]) + date: (date [1171, 14] - [1171, 24])) + (blame_entry [1172, 4] - [1172, 24] + line: (number [1172, 11] - [1172, 13]) + date: (date [1172, 14] - [1172, 24]))) + (file_entry [1173, 0] - [1174, 24] + file_name: (filename [1173, 6] - [1173, 69]) + (blame_entry [1174, 4] - [1174, 24] + line: (number [1174, 11] - [1174, 13]) + date: (date [1174, 14] - [1174, 24]))) + (file_entry [1175, 0] - [1184, 26] + file_name: (filename [1175, 6] - [1175, 43]) + (blame_entry [1176, 4] - [1176, 25] + line: (number [1176, 11] - [1176, 14]) + date: (date [1176, 15] - [1176, 25])) + (blame_entry [1177, 4] - [1177, 25] + line: (number [1177, 11] - [1177, 14]) + date: (date [1177, 15] - [1177, 25])) + (blame_entry [1178, 4] - [1178, 25] + line: (number [1178, 11] - [1178, 14]) + date: (date [1178, 15] - [1178, 25])) + (blame_entry [1179, 4] - [1179, 25] + line: (number [1179, 11] - [1179, 14]) + date: (date [1179, 15] - [1179, 25])) + (blame_entry [1180, 4] - [1180, 25] + line: (number [1180, 11] - [1180, 14]) + date: (date [1180, 15] - [1180, 25])) + (blame_entry [1181, 4] - [1181, 25] + line: (number [1181, 11] - [1181, 14]) + date: (date [1181, 15] - [1181, 25])) + (blame_entry [1182, 4] - [1182, 25] + line: (number [1182, 11] - [1182, 14]) + date: (date [1182, 15] - [1182, 25])) + (blame_entry [1183, 4] - [1183, 25] + line: (number [1183, 11] - [1183, 14]) + date: (date [1183, 15] - [1183, 25])) + (blame_entry [1184, 4] - [1184, 26] + line: (number [1184, 11] - [1184, 15]) + date: (date [1184, 16] - [1184, 26]))) + (file_entry [1185, 0] - [1188, 24] + file_name: (filename [1185, 6] - [1185, 70]) + (blame_entry [1186, 4] - [1186, 24] + line: (number [1186, 11] - [1186, 13]) + date: (date [1186, 14] - [1186, 24])) + (blame_entry [1187, 4] - [1187, 24] + line: (number [1187, 11] - [1187, 13]) + date: (date [1187, 14] - [1187, 24])) + (blame_entry [1188, 4] - [1188, 24] + line: (number [1188, 11] - [1188, 13]) + date: (date [1188, 14] - [1188, 24]))) + (file_entry [1189, 0] - [1190, 23] + file_name: (filename [1189, 6] - [1189, 61]) + (blame_entry [1190, 4] - [1190, 23] + line: (number [1190, 11] - [1190, 12]) + date: (date [1190, 13] - [1190, 23]))) + (file_entry [1191, 0] - [1192, 24] + file_name: (filename [1191, 6] - [1191, 51]) + (blame_entry [1192, 4] - [1192, 24] + line: (number [1192, 11] - [1192, 13]) + date: (date [1192, 14] - [1192, 24]))) + (file_entry [1193, 0] - [1195, 24] + file_name: (filename [1193, 6] - [1193, 40]) + (blame_entry [1194, 4] - [1194, 24] + line: (number [1194, 11] - [1194, 13]) + date: (date [1194, 14] - [1194, 24])) + (blame_entry [1195, 4] - [1195, 24] + line: (number [1195, 11] - [1195, 13]) + date: (date [1195, 14] - [1195, 24]))) + (file_entry [1196, 0] - [1198, 25] + file_name: (filename [1196, 6] - [1196, 62]) + (blame_entry [1197, 4] - [1197, 25] + line: (number [1197, 11] - [1197, 14]) + date: (date [1197, 15] - [1197, 25])) + (blame_entry [1198, 4] - [1198, 25] + line: (number [1198, 11] - [1198, 14]) + date: (date [1198, 15] - [1198, 25]))) + (file_entry [1199, 0] - [1200, 24] + file_name: (filename [1199, 6] - [1199, 85]) + (blame_entry [1200, 4] - [1200, 24] + line: (number [1200, 11] - [1200, 13]) + date: (date [1200, 14] - [1200, 24]))) + (file_entry [1201, 0] - [1202, 24] + file_name: (filename [1201, 6] - [1201, 76]) + (blame_entry [1202, 4] - [1202, 24] + line: (number [1202, 11] - [1202, 13]) + date: (date [1202, 14] - [1202, 24]))) + (file_entry [1203, 0] - [1204, 24] + file_name: (filename [1203, 6] - [1203, 82]) + (blame_entry [1204, 4] - [1204, 24] + line: (number [1204, 11] - [1204, 13]) + date: (date [1204, 14] - [1204, 24]))) + (file_entry [1205, 0] - [1207, 24] + file_name: (filename [1205, 6] - [1205, 65]) + (blame_entry [1206, 4] - [1206, 23] + line: (number [1206, 11] - [1206, 12]) + date: (date [1206, 13] - [1206, 23])) + (blame_entry [1207, 4] - [1207, 24] + line: (number [1207, 11] - [1207, 13]) + date: (date [1207, 14] - [1207, 24]))) + (file_entry [1208, 0] - [1209, 25] + file_name: (filename [1208, 6] - [1208, 71]) + (blame_entry [1209, 4] - [1209, 25] + line: (number [1209, 11] - [1209, 14]) + date: (date [1209, 15] - [1209, 25]))) + (file_entry [1210, 0] - [1228, 24] + file_name: (filename [1210, 6] - [1210, 60]) + (blame_entry [1211, 4] - [1211, 24] + line: (number [1211, 11] - [1211, 13]) + date: (date [1211, 14] - [1211, 24])) + (blame_entry [1212, 4] - [1212, 24] + line: (number [1212, 11] - [1212, 13]) + date: (date [1212, 14] - [1212, 24])) + (blame_entry [1213, 4] - [1213, 24] + line: (number [1213, 11] - [1213, 13]) + date: (date [1213, 14] - [1213, 24])) + (blame_entry [1214, 4] - [1214, 24] + line: (number [1214, 11] - [1214, 13]) + date: (date [1214, 14] - [1214, 24])) + (blame_entry [1215, 4] - [1215, 24] + line: (number [1215, 11] - [1215, 13]) + date: (date [1215, 14] - [1215, 24])) + (blame_entry [1216, 4] - [1216, 24] + line: (number [1216, 11] - [1216, 13]) + date: (date [1216, 14] - [1216, 24])) + (blame_entry [1217, 4] - [1217, 24] + line: (number [1217, 11] - [1217, 13]) + date: (date [1217, 14] - [1217, 24])) + (blame_entry [1218, 4] - [1218, 24] + line: (number [1218, 11] - [1218, 13]) + date: (date [1218, 14] - [1218, 24])) + (blame_entry [1219, 4] - [1219, 24] + line: (number [1219, 11] - [1219, 13]) + date: (date [1219, 14] - [1219, 24])) + (blame_entry [1220, 4] - [1220, 24] + line: (number [1220, 11] - [1220, 13]) + date: (date [1220, 14] - [1220, 24])) + (blame_entry [1221, 4] - [1221, 24] + line: (number [1221, 11] - [1221, 13]) + date: (date [1221, 14] - [1221, 24])) + (blame_entry [1222, 4] - [1222, 24] + line: (number [1222, 11] - [1222, 13]) + date: (date [1222, 14] - [1222, 24])) + (blame_entry [1223, 4] - [1223, 24] + line: (number [1223, 11] - [1223, 13]) + date: (date [1223, 14] - [1223, 24])) + (blame_entry [1224, 4] - [1224, 24] + line: (number [1224, 11] - [1224, 13]) + date: (date [1224, 14] - [1224, 24])) + (blame_entry [1225, 4] - [1225, 24] + line: (number [1225, 11] - [1225, 13]) + date: (date [1225, 14] - [1225, 24])) + (blame_entry [1226, 4] - [1226, 24] + line: (number [1226, 11] - [1226, 13]) + date: (date [1226, 14] - [1226, 24])) + (blame_entry [1227, 4] - [1227, 24] + line: (number [1227, 11] - [1227, 13]) + date: (date [1227, 14] - [1227, 24])) + (blame_entry [1228, 4] - [1228, 24] + line: (number [1228, 11] - [1228, 13]) + date: (date [1228, 14] - [1228, 24]))) + (file_entry [1229, 0] - [1230, 24] + file_name: (filename [1229, 6] - [1229, 45]) + (blame_entry [1230, 4] - [1230, 24] + line: (number [1230, 11] - [1230, 13]) + date: (date [1230, 14] - [1230, 24]))) + (file_entry [1231, 0] - [1232, 24] + file_name: (filename [1231, 6] - [1231, 64]) + (blame_entry [1232, 4] - [1232, 24] + line: (number [1232, 11] - [1232, 13]) + date: (date [1232, 14] - [1232, 24]))) + (file_entry [1233, 0] - [1234, 25] + file_name: (filename [1233, 6] - [1233, 50]) + (blame_entry [1234, 4] - [1234, 25] + line: (number [1234, 11] - [1234, 14]) + date: (date [1234, 15] - [1234, 25]))) + (file_entry [1235, 0] - [1237, 24] + file_name: (filename [1235, 6] - [1235, 68]) + (blame_entry [1236, 4] - [1236, 24] + line: (number [1236, 11] - [1236, 13]) + date: (date [1236, 14] - [1236, 24])) + (blame_entry [1237, 4] - [1237, 24] + line: (number [1237, 11] - [1237, 13]) + date: (date [1237, 14] - [1237, 24]))) + (file_entry [1238, 0] - [1243, 25] + file_name: (filename [1238, 6] - [1238, 66]) + (blame_entry [1239, 4] - [1239, 24] + line: (number [1239, 11] - [1239, 13]) + date: (date [1239, 14] - [1239, 24])) + (blame_entry [1240, 4] - [1240, 25] + line: (number [1240, 11] - [1240, 14]) + date: (date [1240, 15] - [1240, 25])) + (blame_entry [1241, 4] - [1241, 25] + line: (number [1241, 11] - [1241, 14]) + date: (date [1241, 15] - [1241, 25])) + (blame_entry [1242, 4] - [1242, 25] + line: (number [1242, 11] - [1242, 14]) + date: (date [1242, 15] - [1242, 25])) + (blame_entry [1243, 4] - [1243, 25] + line: (number [1243, 11] - [1243, 14]) + date: (date [1243, 15] - [1243, 25]))) + (file_entry [1244, 0] - [1245, 24] + file_name: (filename [1244, 6] - [1244, 72]) + (blame_entry [1245, 4] - [1245, 24] + line: (number [1245, 11] - [1245, 13]) + date: (date [1245, 14] - [1245, 24]))) + (file_entry [1246, 0] - [1248, 25] + file_name: (filename [1246, 6] - [1246, 46]) + (blame_entry [1247, 4] - [1247, 25] + line: (number [1247, 11] - [1247, 14]) + date: (date [1247, 15] - [1247, 25])) + (blame_entry [1248, 4] - [1248, 25] + line: (number [1248, 11] - [1248, 14]) + date: (date [1248, 15] - [1248, 25]))) + (file_entry [1249, 0] - [1250, 25] + file_name: (filename [1249, 6] - [1249, 49]) + (blame_entry [1250, 4] - [1250, 25] + line: (number [1250, 11] - [1250, 14]) + date: (date [1250, 15] - [1250, 25]))) + (file_entry [1251, 0] - [1252, 24] + file_name: (filename [1251, 6] - [1251, 48]) + (blame_entry [1252, 4] - [1252, 24] + line: (number [1252, 11] - [1252, 13]) + date: (date [1252, 14] - [1252, 24]))) + (file_entry [1253, 0] - [1254, 24] + file_name: (filename [1253, 6] - [1253, 79]) + (blame_entry [1254, 4] - [1254, 24] + line: (number [1254, 11] - [1254, 13]) + date: (date [1254, 14] - [1254, 24]))) + (file_entry [1255, 0] - [1256, 24] + file_name: (filename [1255, 6] - [1255, 70]) + (blame_entry [1256, 4] - [1256, 24] + line: (number [1256, 11] - [1256, 13]) + date: (date [1256, 14] - [1256, 24]))) + (file_entry [1257, 0] - [1258, 24] + file_name: (filename [1257, 6] - [1257, 64]) + (blame_entry [1258, 4] - [1258, 24] + line: (number [1258, 11] - [1258, 13]) + date: (date [1258, 14] - [1258, 24]))) + (file_entry [1259, 0] - [1261, 24] + file_name: (filename [1259, 6] - [1259, 71]) + (blame_entry [1260, 4] - [1260, 24] + line: (number [1260, 11] - [1260, 13]) + date: (date [1260, 14] - [1260, 24])) + (blame_entry [1261, 4] - [1261, 24] + line: (number [1261, 11] - [1261, 13]) + date: (date [1261, 14] - [1261, 24]))) + (file_entry [1262, 0] - [1263, 24] + file_name: (filename [1262, 6] - [1262, 84]) + (blame_entry [1263, 4] - [1263, 24] + line: (number [1263, 11] - [1263, 13]) + date: (date [1263, 14] - [1263, 24]))) + (file_entry [1264, 0] - [1265, 25] + file_name: (filename [1264, 6] - [1264, 66]) + (blame_entry [1265, 4] - [1265, 25] + line: (number [1265, 11] - [1265, 14]) + date: (date [1265, 15] - [1265, 25]))) + (file_entry [1266, 0] - [1267, 23] + file_name: (filename [1266, 6] - [1266, 84]) + (blame_entry [1267, 4] - [1267, 23] + line: (number [1267, 11] - [1267, 12]) + date: (date [1267, 13] - [1267, 23]))) + (file_entry [1268, 0] - [1273, 25] + file_name: (filename [1268, 6] - [1268, 68]) + (blame_entry [1269, 4] - [1269, 24] + line: (number [1269, 11] - [1269, 13]) + date: (date [1269, 14] - [1269, 24])) + (blame_entry [1270, 4] - [1270, 24] + line: (number [1270, 11] - [1270, 13]) + date: (date [1270, 14] - [1270, 24])) + (blame_entry [1271, 4] - [1271, 24] + line: (number [1271, 11] - [1271, 13]) + date: (date [1271, 14] - [1271, 24])) + (blame_entry [1272, 4] - [1272, 25] + line: (number [1272, 11] - [1272, 14]) + date: (date [1272, 15] - [1272, 25])) + (blame_entry [1273, 4] - [1273, 25] + line: (number [1273, 11] - [1273, 14]) + date: (date [1273, 15] - [1273, 25]))) + (file_entry [1274, 0] - [1278, 24] + file_name: (filename [1274, 6] - [1274, 67]) + (blame_entry [1275, 4] - [1275, 23] + line: (number [1275, 11] - [1275, 12]) + date: (date [1275, 13] - [1275, 23])) + (blame_entry [1276, 4] - [1276, 24] + line: (number [1276, 11] - [1276, 13]) + date: (date [1276, 14] - [1276, 24])) + (blame_entry [1277, 4] - [1277, 24] + line: (number [1277, 11] - [1277, 13]) + date: (date [1277, 14] - [1277, 24])) + (blame_entry [1278, 4] - [1278, 24] + line: (number [1278, 11] - [1278, 13]) + date: (date [1278, 14] - [1278, 24]))) + (file_entry [1279, 0] - [1283, 24] + file_name: (filename [1279, 6] - [1279, 58]) + (blame_entry [1280, 4] - [1280, 23] + line: (number [1280, 11] - [1280, 12]) + date: (date [1280, 13] - [1280, 23])) + (blame_entry [1281, 4] - [1281, 24] + line: (number [1281, 11] - [1281, 13]) + date: (date [1281, 14] - [1281, 24])) + (blame_entry [1282, 4] - [1282, 24] + line: (number [1282, 11] - [1282, 13]) + date: (date [1282, 14] - [1282, 24])) + (blame_entry [1283, 4] - [1283, 24] + line: (number [1283, 11] - [1283, 13]) + date: (date [1283, 14] - [1283, 24]))) + (file_entry [1284, 0] - [1286, 24] + file_name: (filename [1284, 6] - [1284, 72]) + (blame_entry [1285, 4] - [1285, 23] + line: (number [1285, 11] - [1285, 12]) + date: (date [1285, 13] - [1285, 23])) + (blame_entry [1286, 4] - [1286, 24] + line: (number [1286, 11] - [1286, 13]) + date: (date [1286, 14] - [1286, 24]))) + (file_entry [1287, 0] - [1291, 25] + file_name: (filename [1287, 6] - [1287, 84]) + (blame_entry [1288, 4] - [1288, 24] + line: (number [1288, 11] - [1288, 13]) + date: (date [1288, 14] - [1288, 24])) + (blame_entry [1289, 4] - [1289, 25] + line: (number [1289, 11] - [1289, 14]) + date: (date [1289, 15] - [1289, 25])) + (blame_entry [1290, 4] - [1290, 25] + line: (number [1290, 11] - [1290, 14]) + date: (date [1290, 15] - [1290, 25])) + (blame_entry [1291, 4] - [1291, 25] + line: (number [1291, 11] - [1291, 14]) + date: (date [1291, 15] - [1291, 25]))) + (file_entry [1292, 0] - [1294, 24] + file_name: (filename [1292, 6] - [1292, 64]) + (blame_entry [1293, 4] - [1293, 24] + line: (number [1293, 11] - [1293, 13]) + date: (date [1293, 14] - [1293, 24])) + (blame_entry [1294, 4] - [1294, 24] + line: (number [1294, 11] - [1294, 13]) + date: (date [1294, 14] - [1294, 24]))) + (file_entry [1295, 0] - [1296, 23] + file_name: (filename [1295, 6] - [1295, 82]) + (blame_entry [1296, 4] - [1296, 23] + line: (number [1296, 11] - [1296, 12]) + date: (date [1296, 13] - [1296, 23]))) + (file_entry [1297, 0] - [1298, 24] + file_name: (filename [1297, 6] - [1297, 68]) + (blame_entry [1298, 4] - [1298, 24] + line: (number [1298, 11] - [1298, 13]) + date: (date [1298, 14] - [1298, 24]))) + (file_entry [1299, 0] - [1301, 26] + file_name: (filename [1299, 6] - [1299, 68]) + (blame_entry [1300, 4] - [1300, 25] + line: (number [1300, 11] - [1300, 14]) + date: (date [1300, 15] - [1300, 25])) + (blame_entry [1301, 4] - [1301, 26] + line: (number [1301, 11] - [1301, 15]) + date: (date [1301, 16] - [1301, 26]))) + (file_entry [1302, 0] - [1306, 24] + file_name: (filename [1302, 6] - [1302, 66]) + (blame_entry [1303, 4] - [1303, 23] + line: (number [1303, 11] - [1303, 12]) + date: (date [1303, 13] - [1303, 23])) + (blame_entry [1304, 4] - [1304, 24] + line: (number [1304, 11] - [1304, 13]) + date: (date [1304, 14] - [1304, 24])) + (blame_entry [1305, 4] - [1305, 24] + line: (number [1305, 11] - [1305, 13]) + date: (date [1305, 14] - [1305, 24])) + (blame_entry [1306, 4] - [1306, 24] + line: (number [1306, 11] - [1306, 13]) + date: (date [1306, 14] - [1306, 24]))) + (file_entry [1307, 0] - [1309, 24] + file_name: (filename [1307, 6] - [1307, 60]) + (blame_entry [1308, 4] - [1308, 24] + line: (number [1308, 11] - [1308, 13]) + date: (date [1308, 14] - [1308, 24])) + (blame_entry [1309, 4] - [1309, 24] + line: (number [1309, 11] - [1309, 13]) + date: (date [1309, 14] - [1309, 24]))) + (file_entry [1310, 0] - [1311, 25] + file_name: (filename [1310, 6] - [1310, 43]) + (blame_entry [1311, 4] - [1311, 25] + line: (number [1311, 11] - [1311, 14]) + date: (date [1311, 15] - [1311, 25]))) + (file_entry [1312, 0] - [1313, 23] + file_name: (filename [1312, 6] - [1312, 96]) + (blame_entry [1313, 4] - [1313, 23] + line: (number [1313, 11] - [1313, 12]) + date: (date [1313, 13] - [1313, 23]))) + (file_entry [1314, 0] - [1316, 24] + file_name: (filename [1314, 6] - [1314, 42]) + (blame_entry [1315, 4] - [1315, 24] + line: (number [1315, 11] - [1315, 13]) + date: (date [1315, 14] - [1315, 24])) + (blame_entry [1316, 4] - [1316, 24] + line: (number [1316, 11] - [1316, 13]) + date: (date [1316, 14] - [1316, 24]))) + (file_entry [1317, 0] - [1318, 24] + file_name: (filename [1317, 6] - [1317, 64]) + (blame_entry [1318, 4] - [1318, 24] + line: (number [1318, 11] - [1318, 13]) + date: (date [1318, 14] - [1318, 24]))) + (file_entry [1319, 0] - [1323, 25] + file_name: (filename [1319, 6] - [1319, 103]) + (blame_entry [1320, 4] - [1320, 25] + line: (number [1320, 11] - [1320, 14]) + date: (date [1320, 15] - [1320, 25])) + (blame_entry [1321, 4] - [1321, 25] + line: (number [1321, 11] - [1321, 14]) + date: (date [1321, 15] - [1321, 25])) + (blame_entry [1322, 4] - [1322, 25] + line: (number [1322, 11] - [1322, 14]) + date: (date [1322, 15] - [1322, 25])) + (blame_entry [1323, 4] - [1323, 25] + line: (number [1323, 11] - [1323, 14]) + date: (date [1323, 15] - [1323, 25]))) + (file_entry [1324, 0] - [1325, 24] + file_name: (filename [1324, 6] - [1324, 79]) + (blame_entry [1325, 4] - [1325, 24] + line: (number [1325, 11] - [1325, 13]) + date: (date [1325, 14] - [1325, 24]))) + (file_entry [1326, 0] - [1328, 25] + file_name: (filename [1326, 6] - [1326, 83]) + (blame_entry [1327, 4] - [1327, 24] + line: (number [1327, 11] - [1327, 13]) + date: (date [1327, 14] - [1327, 24])) + (blame_entry [1328, 4] - [1328, 25] + line: (number [1328, 11] - [1328, 14]) + date: (date [1328, 15] - [1328, 25]))) + (file_entry [1329, 0] - [1330, 24] + file_name: (filename [1329, 6] - [1329, 70]) + (blame_entry [1330, 4] - [1330, 24] + line: (number [1330, 11] - [1330, 13]) + date: (date [1330, 14] - [1330, 24]))) + (file_entry [1331, 0] - [1334, 24] + file_name: (filename [1331, 6] - [1331, 71]) + (blame_entry [1332, 4] - [1332, 24] + line: (number [1332, 11] - [1332, 13]) + date: (date [1332, 14] - [1332, 24])) + (blame_entry [1333, 4] - [1333, 24] + line: (number [1333, 11] - [1333, 13]) + date: (date [1333, 14] - [1333, 24])) + (blame_entry [1334, 4] - [1334, 24] + line: (number [1334, 11] - [1334, 13]) + date: (date [1334, 14] - [1334, 24]))) + (file_entry [1335, 0] - [1337, 24] + file_name: (filename [1335, 6] - [1335, 61]) + (blame_entry [1336, 4] - [1336, 24] + line: (number [1336, 11] - [1336, 13]) + date: (date [1336, 14] - [1336, 24])) + (blame_entry [1337, 4] - [1337, 24] + line: (number [1337, 11] - [1337, 13]) + date: (date [1337, 14] - [1337, 24]))) + (file_entry [1338, 0] - [1339, 24] + file_name: (filename [1338, 6] - [1338, 54]) + (blame_entry [1339, 4] - [1339, 24] + line: (number [1339, 11] - [1339, 13]) + date: (date [1339, 14] - [1339, 24]))) + (file_entry [1340, 0] - [1341, 24] + file_name: (filename [1340, 6] - [1340, 59]) + (blame_entry [1341, 4] - [1341, 24] + line: (number [1341, 11] - [1341, 13]) + date: (date [1341, 14] - [1341, 24]))) + (file_entry [1342, 0] - [1349, 24] + file_name: (filename [1342, 6] - [1342, 61]) + (blame_entry [1343, 4] - [1343, 23] + line: (number [1343, 11] - [1343, 12]) + date: (date [1343, 13] - [1343, 23])) + (blame_entry [1344, 4] - [1344, 24] + line: (number [1344, 11] - [1344, 13]) + date: (date [1344, 14] - [1344, 24])) + (blame_entry [1345, 4] - [1345, 24] + line: (number [1345, 11] - [1345, 13]) + date: (date [1345, 14] - [1345, 24])) + (blame_entry [1346, 4] - [1346, 24] + line: (number [1346, 11] - [1346, 13]) + date: (date [1346, 14] - [1346, 24])) + (blame_entry [1347, 4] - [1347, 24] + line: (number [1347, 11] - [1347, 13]) + date: (date [1347, 14] - [1347, 24])) + (blame_entry [1348, 4] - [1348, 24] + line: (number [1348, 11] - [1348, 13]) + date: (date [1348, 14] - [1348, 24])) + (blame_entry [1349, 4] - [1349, 24] + line: (number [1349, 11] - [1349, 13]) + date: (date [1349, 14] - [1349, 24]))) + (file_entry [1350, 0] - [1353, 25] + file_name: (filename [1350, 6] - [1350, 45]) + (blame_entry [1351, 4] - [1351, 25] + line: (number [1351, 11] - [1351, 14]) + date: (date [1351, 15] - [1351, 25])) + (blame_entry [1352, 4] - [1352, 25] + line: (number [1352, 11] - [1352, 14]) + date: (date [1352, 15] - [1352, 25])) + (blame_entry [1353, 4] - [1353, 25] + line: (number [1353, 11] - [1353, 14]) + date: (date [1353, 15] - [1353, 25]))) + (file_entry [1354, 0] - [1355, 24] + file_name: (filename [1354, 6] - [1354, 72]) + (blame_entry [1355, 4] - [1355, 24] + line: (number [1355, 11] - [1355, 13]) + date: (date [1355, 14] - [1355, 24]))) + (file_entry [1356, 0] - [1357, 24] + file_name: (filename [1356, 6] - [1356, 65]) + (blame_entry [1357, 4] - [1357, 24] + line: (number [1357, 11] - [1357, 13]) + date: (date [1357, 14] - [1357, 24]))) + (file_entry [1358, 0] - [1359, 24] + file_name: (filename [1358, 6] - [1358, 54]) + (blame_entry [1359, 4] - [1359, 24] + line: (number [1359, 11] - [1359, 13]) + date: (date [1359, 14] - [1359, 24]))) + (file_entry [1360, 0] - [1363, 25] + file_name: (filename [1360, 6] - [1360, 69]) + (blame_entry [1361, 4] - [1361, 24] + line: (number [1361, 11] - [1361, 13]) + date: (date [1361, 14] - [1361, 24])) + (blame_entry [1362, 4] - [1362, 24] + line: (number [1362, 11] - [1362, 13]) + date: (date [1362, 14] - [1362, 24])) + (blame_entry [1363, 4] - [1363, 25] + line: (number [1363, 11] - [1363, 14]) + date: (date [1363, 15] - [1363, 25]))) + (file_entry [1364, 0] - [1365, 23] + file_name: (filename [1364, 6] - [1364, 76]) + (blame_entry [1365, 4] - [1365, 23] + line: (number [1365, 11] - [1365, 12]) + date: (date [1365, 13] - [1365, 23]))) + (file_entry [1366, 0] - [1368, 25] + file_name: (filename [1366, 6] - [1366, 66]) + (blame_entry [1367, 4] - [1367, 24] + line: (number [1367, 11] - [1367, 13]) + date: (date [1367, 14] - [1367, 24])) + (blame_entry [1368, 4] - [1368, 25] + line: (number [1368, 11] - [1368, 14]) + date: (date [1368, 15] - [1368, 25]))) + (file_entry [1369, 0] - [1371, 23] + file_name: (filename [1369, 6] - [1369, 55]) + (blame_entry [1370, 4] - [1370, 23] + line: (number [1370, 11] - [1370, 12]) + date: (date [1370, 13] - [1370, 23])) + (blame_entry [1371, 4] - [1371, 23] + line: (number [1371, 11] - [1371, 12]) + date: (date [1371, 13] - [1371, 23]))) + (file_entry [1372, 0] - [1378, 24] + file_name: (filename [1372, 6] - [1372, 57]) + (blame_entry [1373, 4] - [1373, 23] + line: (number [1373, 11] - [1373, 12]) + date: (date [1373, 13] - [1373, 23])) + (blame_entry [1374, 4] - [1374, 24] + line: (number [1374, 11] - [1374, 13]) + date: (date [1374, 14] - [1374, 24])) + (blame_entry [1375, 4] - [1375, 24] + line: (number [1375, 11] - [1375, 13]) + date: (date [1375, 14] - [1375, 24])) + (blame_entry [1376, 4] - [1376, 24] + line: (number [1376, 11] - [1376, 13]) + date: (date [1376, 14] - [1376, 24])) + (blame_entry [1377, 4] - [1377, 24] + line: (number [1377, 11] - [1377, 13]) + date: (date [1377, 14] - [1377, 24])) + (blame_entry [1378, 4] - [1378, 24] + line: (number [1378, 11] - [1378, 13]) + date: (date [1378, 14] - [1378, 24]))) + (file_entry [1379, 0] - [1381, 24] + file_name: (filename [1379, 6] - [1379, 52]) + (blame_entry [1380, 4] - [1380, 24] + line: (number [1380, 11] - [1380, 13]) + date: (date [1380, 14] - [1380, 24])) + (blame_entry [1381, 4] - [1381, 24] + line: (number [1381, 11] - [1381, 13]) + date: (date [1381, 14] - [1381, 24]))) + (file_entry [1382, 0] - [1392, 24] + file_name: (filename [1382, 6] - [1382, 46]) + (blame_entry [1383, 4] - [1383, 23] + line: (number [1383, 11] - [1383, 12]) + date: (date [1383, 13] - [1383, 23])) + (blame_entry [1384, 4] - [1384, 24] + line: (number [1384, 11] - [1384, 13]) + date: (date [1384, 14] - [1384, 24])) + (blame_entry [1385, 4] - [1385, 24] + line: (number [1385, 11] - [1385, 13]) + date: (date [1385, 14] - [1385, 24])) + (blame_entry [1386, 4] - [1386, 24] + line: (number [1386, 11] - [1386, 13]) + date: (date [1386, 14] - [1386, 24])) + (blame_entry [1387, 4] - [1387, 24] + line: (number [1387, 11] - [1387, 13]) + date: (date [1387, 14] - [1387, 24])) + (blame_entry [1388, 4] - [1388, 24] + line: (number [1388, 11] - [1388, 13]) + date: (date [1388, 14] - [1388, 24])) + (blame_entry [1389, 4] - [1389, 24] + line: (number [1389, 11] - [1389, 13]) + date: (date [1389, 14] - [1389, 24])) + (blame_entry [1390, 4] - [1390, 24] + line: (number [1390, 11] - [1390, 13]) + date: (date [1390, 14] - [1390, 24])) + (blame_entry [1391, 4] - [1391, 24] + line: (number [1391, 11] - [1391, 13]) + date: (date [1391, 14] - [1391, 24])) + (blame_entry [1392, 4] - [1392, 24] + line: (number [1392, 11] - [1392, 13]) + date: (date [1392, 14] - [1392, 24]))) + (file_entry [1393, 0] - [1395, 25] + file_name: (filename [1393, 6] - [1393, 56]) + (blame_entry [1394, 4] - [1394, 24] + line: (number [1394, 11] - [1394, 13]) + date: (date [1394, 14] - [1394, 24])) + (blame_entry [1395, 4] - [1395, 25] + line: (number [1395, 11] - [1395, 14]) + date: (date [1395, 15] - [1395, 25]))) + (file_entry [1396, 0] - [1397, 23] + file_name: (filename [1396, 6] - [1396, 82]) + (blame_entry [1397, 4] - [1397, 23] + line: (number [1397, 11] - [1397, 12]) + date: (date [1397, 13] - [1397, 23]))) + (file_entry [1398, 0] - [1400, 24] + file_name: (filename [1398, 6] - [1398, 65]) + (blame_entry [1399, 4] - [1399, 24] + line: (number [1399, 11] - [1399, 13]) + date: (date [1399, 14] - [1399, 24])) + (blame_entry [1400, 4] - [1400, 24] + line: (number [1400, 11] - [1400, 13]) + date: (date [1400, 14] - [1400, 24]))) + (file_entry [1401, 0] - [1403, 25] + file_name: (filename [1401, 6] - [1401, 74]) + (blame_entry [1402, 4] - [1402, 24] + line: (number [1402, 11] - [1402, 13]) + date: (date [1402, 14] - [1402, 24])) + (blame_entry [1403, 4] - [1403, 25] + line: (number [1403, 11] - [1403, 14]) + date: (date [1403, 15] - [1403, 25]))) + (file_entry [1404, 0] - [1406, 25] + file_name: (filename [1404, 6] - [1404, 53]) + (blame_entry [1405, 4] - [1405, 25] + line: (number [1405, 11] - [1405, 14]) + date: (date [1405, 15] - [1405, 25])) + (blame_entry [1406, 4] - [1406, 25] + line: (number [1406, 11] - [1406, 14]) + date: (date [1406, 15] - [1406, 25]))) + (file_entry [1407, 0] - [1408, 25] + file_name: (filename [1407, 6] - [1407, 47]) + (blame_entry [1408, 4] - [1408, 25] + line: (number [1408, 11] - [1408, 14]) + date: (date [1408, 15] - [1408, 25]))) + (file_entry [1409, 0] - [1410, 24] + file_name: (filename [1409, 6] - [1409, 87]) + (blame_entry [1410, 4] - [1410, 24] + line: (number [1410, 11] - [1410, 13]) + date: (date [1410, 14] - [1410, 24]))) + (file_entry [1411, 0] - [1413, 25] + file_name: (filename [1411, 6] - [1411, 50]) + (blame_entry [1412, 4] - [1412, 25] + line: (number [1412, 11] - [1412, 14]) + date: (date [1412, 15] - [1412, 25])) + (blame_entry [1413, 4] - [1413, 25] + line: (number [1413, 11] - [1413, 14]) + date: (date [1413, 15] - [1413, 25]))) + (file_entry [1414, 0] - [1416, 25] + file_name: (filename [1414, 6] - [1414, 60]) + (blame_entry [1415, 4] - [1415, 25] + line: (number [1415, 11] - [1415, 14]) + date: (date [1415, 15] - [1415, 25])) + (blame_entry [1416, 4] - [1416, 25] + line: (number [1416, 11] - [1416, 14]) + date: (date [1416, 15] - [1416, 25]))) + (file_entry [1417, 0] - [1418, 24] + file_name: (filename [1417, 6] - [1417, 85]) + (blame_entry [1418, 4] - [1418, 24] + line: (number [1418, 11] - [1418, 13]) + date: (date [1418, 14] - [1418, 24]))) + (file_entry [1419, 0] - [1420, 23] + file_name: (filename [1419, 6] - [1419, 66]) + (blame_entry [1420, 4] - [1420, 23] + line: (number [1420, 11] - [1420, 12]) + date: (date [1420, 13] - [1420, 23]))) + (file_entry [1421, 0] - [1423, 24] + file_name: (filename [1421, 6] - [1421, 56]) + (blame_entry [1422, 4] - [1422, 24] + line: (number [1422, 11] - [1422, 13]) + date: (date [1422, 14] - [1422, 24])) + (blame_entry [1423, 4] - [1423, 24] + line: (number [1423, 11] - [1423, 13]) + date: (date [1423, 14] - [1423, 24]))) + (file_entry [1424, 0] - [1426, 24] + file_name: (filename [1424, 6] - [1424, 58]) + (blame_entry [1425, 4] - [1425, 23] + line: (number [1425, 11] - [1425, 12]) + date: (date [1425, 13] - [1425, 23])) + (blame_entry [1426, 4] - [1426, 24] + line: (number [1426, 11] - [1426, 13]) + date: (date [1426, 14] - [1426, 24]))) + (file_entry [1427, 0] - [1428, 24] + file_name: (filename [1427, 6] - [1427, 64]) + (blame_entry [1428, 4] - [1428, 24] + line: (number [1428, 11] - [1428, 13]) + date: (date [1428, 14] - [1428, 24]))) + (file_entry [1429, 0] - [1432, 25] + file_name: (filename [1429, 6] - [1429, 69]) + (blame_entry [1430, 4] - [1430, 24] + line: (number [1430, 11] - [1430, 13]) + date: (date [1430, 14] - [1430, 24])) + (blame_entry [1431, 4] - [1431, 24] + line: (number [1431, 11] - [1431, 13]) + date: (date [1431, 14] - [1431, 24])) + (blame_entry [1432, 4] - [1432, 25] + line: (number [1432, 11] - [1432, 14]) + date: (date [1432, 15] - [1432, 25]))) + (file_entry [1433, 0] - [1437, 25] + file_name: (filename [1433, 6] - [1433, 72]) + (blame_entry [1434, 4] - [1434, 24] + line: (number [1434, 11] - [1434, 13]) + date: (date [1434, 14] - [1434, 24])) + (blame_entry [1435, 4] - [1435, 25] + line: (number [1435, 11] - [1435, 14]) + date: (date [1435, 15] - [1435, 25])) + (blame_entry [1436, 4] - [1436, 25] + line: (number [1436, 11] - [1436, 14]) + date: (date [1436, 15] - [1436, 25])) + (blame_entry [1437, 4] - [1437, 25] + line: (number [1437, 11] - [1437, 14]) + date: (date [1437, 15] - [1437, 25]))) + (file_entry [1438, 0] - [1439, 25] + file_name: (filename [1438, 6] - [1438, 85]) + (blame_entry [1439, 4] - [1439, 25] + line: (number [1439, 11] - [1439, 14]) + date: (date [1439, 15] - [1439, 25]))) + (file_entry [1440, 0] - [1444, 25] + file_name: (filename [1440, 6] - [1440, 90]) + (blame_entry [1441, 4] - [1441, 25] + line: (number [1441, 11] - [1441, 14]) + date: (date [1441, 15] - [1441, 25])) + (blame_entry [1442, 4] - [1442, 25] + line: (number [1442, 11] - [1442, 14]) + date: (date [1442, 15] - [1442, 25])) + (blame_entry [1443, 4] - [1443, 25] + line: (number [1443, 11] - [1443, 14]) + date: (date [1443, 15] - [1443, 25])) + (blame_entry [1444, 4] - [1444, 25] + line: (number [1444, 11] - [1444, 14]) + date: (date [1444, 15] - [1444, 25]))) + (file_entry [1445, 0] - [1447, 24] + file_name: (filename [1445, 6] - [1445, 75]) + (blame_entry [1446, 4] - [1446, 24] + line: (number [1446, 11] - [1446, 13]) + date: (date [1446, 14] - [1446, 24])) + (blame_entry [1447, 4] - [1447, 24] + line: (number [1447, 11] - [1447, 13]) + date: (date [1447, 14] - [1447, 24]))) + (file_entry [1448, 0] - [1455, 25] + file_name: (filename [1448, 6] - [1448, 71]) + (blame_entry [1449, 4] - [1449, 24] + line: (number [1449, 11] - [1449, 13]) + date: (date [1449, 14] - [1449, 24])) + (blame_entry [1450, 4] - [1450, 24] + line: (number [1450, 11] - [1450, 13]) + date: (date [1450, 14] - [1450, 24])) + (blame_entry [1451, 4] - [1451, 24] + line: (number [1451, 11] - [1451, 13]) + date: (date [1451, 14] - [1451, 24])) + (blame_entry [1452, 4] - [1452, 25] + line: (number [1452, 11] - [1452, 14]) + date: (date [1452, 15] - [1452, 25])) + (blame_entry [1453, 4] - [1453, 25] + line: (number [1453, 11] - [1453, 14]) + date: (date [1453, 15] - [1453, 25])) + (blame_entry [1454, 4] - [1454, 25] + line: (number [1454, 11] - [1454, 14]) + date: (date [1454, 15] - [1454, 25])) + (blame_entry [1455, 4] - [1455, 25] + line: (number [1455, 11] - [1455, 14]) + date: (date [1455, 15] - [1455, 25]))) + (file_entry [1456, 0] - [1457, 24] + file_name: (filename [1456, 6] - [1456, 67]) + (blame_entry [1457, 4] - [1457, 24] + line: (number [1457, 11] - [1457, 13]) + date: (date [1457, 14] - [1457, 24]))) + (file_entry [1458, 0] - [1462, 25] + file_name: (filename [1458, 6] - [1458, 84]) + (blame_entry [1459, 4] - [1459, 25] + line: (number [1459, 11] - [1459, 14]) + date: (date [1459, 15] - [1459, 25])) + (blame_entry [1460, 4] - [1460, 25] + line: (number [1460, 11] - [1460, 14]) + date: (date [1460, 15] - [1460, 25])) + (blame_entry [1461, 4] - [1461, 25] + line: (number [1461, 11] - [1461, 14]) + date: (date [1461, 15] - [1461, 25])) + (blame_entry [1462, 4] - [1462, 25] + line: (number [1462, 11] - [1462, 14]) + date: (date [1462, 15] - [1462, 25]))) + (file_entry [1463, 0] - [1476, 25] + file_name: (filename [1463, 6] - [1463, 63]) + (blame_entry [1464, 4] - [1464, 25] + line: (number [1464, 11] - [1464, 14]) + date: (date [1464, 15] - [1464, 25])) + (blame_entry [1465, 4] - [1465, 25] + line: (number [1465, 11] - [1465, 14]) + date: (date [1465, 15] - [1465, 25])) + (blame_entry [1466, 4] - [1466, 25] + line: (number [1466, 11] - [1466, 14]) + date: (date [1466, 15] - [1466, 25])) + (blame_entry [1467, 4] - [1467, 25] + line: (number [1467, 11] - [1467, 14]) + date: (date [1467, 15] - [1467, 25])) + (blame_entry [1468, 4] - [1468, 25] + line: (number [1468, 11] - [1468, 14]) + date: (date [1468, 15] - [1468, 25])) + (blame_entry [1469, 4] - [1469, 25] + line: (number [1469, 11] - [1469, 14]) + date: (date [1469, 15] - [1469, 25])) + (blame_entry [1470, 4] - [1470, 25] + line: (number [1470, 11] - [1470, 14]) + date: (date [1470, 15] - [1470, 25])) + (blame_entry [1471, 4] - [1471, 25] + line: (number [1471, 11] - [1471, 14]) + date: (date [1471, 15] - [1471, 25])) + (blame_entry [1472, 4] - [1472, 25] + line: (number [1472, 11] - [1472, 14]) + date: (date [1472, 15] - [1472, 25])) + (blame_entry [1473, 4] - [1473, 25] + line: (number [1473, 11] - [1473, 14]) + date: (date [1473, 15] - [1473, 25])) + (blame_entry [1474, 4] - [1474, 25] + line: (number [1474, 11] - [1474, 14]) + date: (date [1474, 15] - [1474, 25])) + (blame_entry [1475, 4] - [1475, 25] + line: (number [1475, 11] - [1475, 14]) + date: (date [1475, 15] - [1475, 25])) + (blame_entry [1476, 4] - [1476, 25] + line: (number [1476, 11] - [1476, 14]) + date: (date [1476, 15] - [1476, 25]))) + (file_entry [1477, 0] - [1481, 25] + file_name: (filename [1477, 6] - [1477, 60]) + (blame_entry [1478, 4] - [1478, 24] + line: (number [1478, 11] - [1478, 13]) + date: (date [1478, 14] - [1478, 24])) + (blame_entry [1479, 4] - [1479, 25] + line: (number [1479, 11] - [1479, 14]) + date: (date [1479, 15] - [1479, 25])) + (blame_entry [1480, 4] - [1480, 25] + line: (number [1480, 11] - [1480, 14]) + date: (date [1480, 15] - [1480, 25])) + (blame_entry [1481, 4] - [1481, 25] + line: (number [1481, 11] - [1481, 14]) + date: (date [1481, 15] - [1481, 25]))) + (file_entry [1482, 0] - [1483, 23] + file_name: (filename [1482, 6] - [1482, 64]) + (blame_entry [1483, 4] - [1483, 23] + line: (number [1483, 11] - [1483, 12]) + date: (date [1483, 13] - [1483, 23]))) + (file_entry [1484, 0] - [1488, 25] + file_name: (filename [1484, 6] - [1484, 89]) + (blame_entry [1485, 4] - [1485, 25] + line: (number [1485, 11] - [1485, 14]) + date: (date [1485, 15] - [1485, 25])) + (blame_entry [1486, 4] - [1486, 25] + line: (number [1486, 11] - [1486, 14]) + date: (date [1486, 15] - [1486, 25])) + (blame_entry [1487, 4] - [1487, 25] + line: (number [1487, 11] - [1487, 14]) + date: (date [1487, 15] - [1487, 25])) + (blame_entry [1488, 4] - [1488, 25] + line: (number [1488, 11] - [1488, 14]) + date: (date [1488, 15] - [1488, 25]))) + (file_entry [1489, 0] - [1490, 24] + file_name: (filename [1489, 6] - [1489, 88]) + (blame_entry [1490, 4] - [1490, 24] + line: (number [1490, 11] - [1490, 13]) + date: (date [1490, 14] - [1490, 24]))) + (file_entry [1491, 0] - [1492, 24] + file_name: (filename [1491, 6] - [1491, 57]) + (blame_entry [1492, 4] - [1492, 24] + line: (number [1492, 11] - [1492, 13]) + date: (date [1492, 14] - [1492, 24]))) + (file_entry [1493, 0] - [1494, 24] + file_name: (filename [1493, 6] - [1493, 66]) + (blame_entry [1494, 4] - [1494, 24] + line: (number [1494, 11] - [1494, 13]) + date: (date [1494, 14] - [1494, 24]))) + (file_entry [1495, 0] - [1496, 23] + file_name: (filename [1495, 6] - [1495, 83]) + (blame_entry [1496, 4] - [1496, 23] + line: (number [1496, 11] - [1496, 12]) + date: (date [1496, 13] - [1496, 23]))) + (file_entry [1497, 0] - [1498, 25] + file_name: (filename [1497, 6] - [1497, 82]) + (blame_entry [1498, 4] - [1498, 25] + line: (number [1498, 11] - [1498, 14]) + date: (date [1498, 15] - [1498, 25]))) + (file_entry [1499, 0] - [1501, 24] + file_name: (filename [1499, 6] - [1499, 55]) + (blame_entry [1500, 4] - [1500, 23] + line: (number [1500, 11] - [1500, 12]) + date: (date [1500, 13] - [1500, 23])) + (blame_entry [1501, 4] - [1501, 24] + line: (number [1501, 11] - [1501, 13]) + date: (date [1501, 14] - [1501, 24]))) + (file_entry [1502, 0] - [1503, 23] + file_name: (filename [1502, 6] - [1502, 69]) + (blame_entry [1503, 4] - [1503, 23] + line: (number [1503, 11] - [1503, 12]) + date: (date [1503, 13] - [1503, 23]))) + (file_entry [1504, 0] - [1505, 24] + file_name: (filename [1504, 6] - [1504, 68]) + (blame_entry [1505, 4] - [1505, 24] + line: (number [1505, 11] - [1505, 13]) + date: (date [1505, 14] - [1505, 24]))) + (file_entry [1506, 0] - [1508, 25] + file_name: (filename [1506, 6] - [1506, 86]) + (blame_entry [1507, 4] - [1507, 24] + line: (number [1507, 11] - [1507, 13]) + date: (date [1507, 14] - [1507, 24])) + (blame_entry [1508, 4] - [1508, 25] + line: (number [1508, 11] - [1508, 14]) + date: (date [1508, 15] - [1508, 25]))) + (file_entry [1509, 0] - [1520, 25] + file_name: (filename [1509, 6] - [1509, 49]) + (blame_entry [1510, 4] - [1510, 24] + line: (number [1510, 11] - [1510, 13]) + date: (date [1510, 14] - [1510, 24])) + (blame_entry [1511, 4] - [1511, 24] + line: (number [1511, 11] - [1511, 13]) + date: (date [1511, 14] - [1511, 24])) + (blame_entry [1512, 4] - [1512, 24] + line: (number [1512, 11] - [1512, 13]) + date: (date [1512, 14] - [1512, 24])) + (blame_entry [1513, 4] - [1513, 25] + line: (number [1513, 11] - [1513, 14]) + date: (date [1513, 15] - [1513, 25])) + (blame_entry [1514, 4] - [1514, 25] + line: (number [1514, 11] - [1514, 14]) + date: (date [1514, 15] - [1514, 25])) + (blame_entry [1515, 4] - [1515, 25] + line: (number [1515, 11] - [1515, 14]) + date: (date [1515, 15] - [1515, 25])) + (blame_entry [1516, 4] - [1516, 25] + line: (number [1516, 11] - [1516, 14]) + date: (date [1516, 15] - [1516, 25])) + (blame_entry [1517, 4] - [1517, 25] + line: (number [1517, 11] - [1517, 14]) + date: (date [1517, 15] - [1517, 25])) + (blame_entry [1518, 4] - [1518, 25] + line: (number [1518, 11] - [1518, 14]) + date: (date [1518, 15] - [1518, 25])) + (blame_entry [1519, 4] - [1519, 25] + line: (number [1519, 11] - [1519, 14]) + date: (date [1519, 15] - [1519, 25])) + (blame_entry [1520, 4] - [1520, 25] + line: (number [1520, 11] - [1520, 14]) + date: (date [1520, 15] - [1520, 25]))) + (file_entry [1521, 0] - [1522, 24] + file_name: (filename [1521, 6] - [1521, 119]) + (blame_entry [1522, 4] - [1522, 24] + line: (number [1522, 11] - [1522, 13]) + date: (date [1522, 14] - [1522, 24]))) + (file_entry [1523, 0] - [1524, 23] + file_name: (filename [1523, 6] - [1523, 69]) + (blame_entry [1524, 4] - [1524, 23] + line: (number [1524, 11] - [1524, 12]) + date: (date [1524, 13] - [1524, 23]))) + (file_entry [1525, 0] - [1527, 24] + file_name: (filename [1525, 6] - [1525, 63]) + (blame_entry [1526, 4] - [1526, 24] + line: (number [1526, 11] - [1526, 13]) + date: (date [1526, 14] - [1526, 24])) + (blame_entry [1527, 4] - [1527, 24] + line: (number [1527, 11] - [1527, 13]) + date: (date [1527, 14] - [1527, 24]))) + (file_entry [1528, 0] - [1529, 23] + file_name: (filename [1528, 6] - [1528, 91]) + (blame_entry [1529, 4] - [1529, 23] + line: (number [1529, 11] - [1529, 12]) + date: (date [1529, 13] - [1529, 23]))) + (file_entry [1530, 0] - [1531, 23] + file_name: (filename [1530, 6] - [1530, 82]) + (blame_entry [1531, 4] - [1531, 23] + line: (number [1531, 11] - [1531, 12]) + date: (date [1531, 13] - [1531, 23]))) + (file_entry [1532, 0] - [1533, 24] + file_name: (filename [1532, 6] - [1532, 78]) + (blame_entry [1533, 4] - [1533, 24] + line: (number [1533, 11] - [1533, 13]) + date: (date [1533, 14] - [1533, 24]))) + (file_entry [1534, 0] - [1536, 25] + file_name: (filename [1534, 6] - [1534, 57]) + (blame_entry [1535, 4] - [1535, 25] + line: (number [1535, 11] - [1535, 14]) + date: (date [1535, 15] - [1535, 25])) + (blame_entry [1536, 4] - [1536, 25] + line: (number [1536, 11] - [1536, 14]) + date: (date [1536, 15] - [1536, 25]))) + (file_entry [1537, 0] - [1539, 24] + file_name: (filename [1537, 6] - [1537, 56]) + (blame_entry [1538, 4] - [1538, 23] + line: (number [1538, 11] - [1538, 12]) + date: (date [1538, 13] - [1538, 23])) + (blame_entry [1539, 4] - [1539, 24] + line: (number [1539, 11] - [1539, 13]) + date: (date [1539, 14] - [1539, 24]))) + (file_entry [1540, 0] - [1544, 25] + file_name: (filename [1540, 6] - [1540, 89]) + (blame_entry [1541, 4] - [1541, 25] + line: (number [1541, 11] - [1541, 14]) + date: (date [1541, 15] - [1541, 25])) + (blame_entry [1542, 4] - [1542, 25] + line: (number [1542, 11] - [1542, 14]) + date: (date [1542, 15] - [1542, 25])) + (blame_entry [1543, 4] - [1543, 25] + line: (number [1543, 11] - [1543, 14]) + date: (date [1543, 15] - [1543, 25])) + (blame_entry [1544, 4] - [1544, 25] + line: (number [1544, 11] - [1544, 14]) + date: (date [1544, 15] - [1544, 25]))) + (file_entry [1545, 0] - [1551, 25] + file_name: (filename [1545, 6] - [1545, 67]) + (blame_entry [1546, 4] - [1546, 25] + line: (number [1546, 11] - [1546, 14]) + date: (date [1546, 15] - [1546, 25])) + (blame_entry [1547, 4] - [1547, 25] + line: (number [1547, 11] - [1547, 14]) + date: (date [1547, 15] - [1547, 25])) + (blame_entry [1548, 4] - [1548, 25] + line: (number [1548, 11] - [1548, 14]) + date: (date [1548, 15] - [1548, 25])) + (blame_entry [1549, 4] - [1549, 25] + line: (number [1549, 11] - [1549, 14]) + date: (date [1549, 15] - [1549, 25])) + (blame_entry [1550, 4] - [1550, 25] + line: (number [1550, 11] - [1550, 14]) + date: (date [1550, 15] - [1550, 25])) + (blame_entry [1551, 4] - [1551, 25] + line: (number [1551, 11] - [1551, 14]) + date: (date [1551, 15] - [1551, 25]))) + (file_entry [1552, 0] - [1553, 23] + file_name: (filename [1552, 6] - [1552, 49]) + (blame_entry [1553, 4] - [1553, 23] + line: (number [1553, 11] - [1553, 12]) + date: (date [1553, 13] - [1553, 23]))) + (file_entry [1554, 0] - [1560, 25] + file_name: (filename [1554, 6] - [1554, 71]) + (blame_entry [1555, 4] - [1555, 24] + line: (number [1555, 11] - [1555, 13]) + date: (date [1555, 14] - [1555, 24])) + (blame_entry [1556, 4] - [1556, 24] + line: (number [1556, 11] - [1556, 13]) + date: (date [1556, 14] - [1556, 24])) + (blame_entry [1557, 4] - [1557, 25] + line: (number [1557, 11] - [1557, 14]) + date: (date [1557, 15] - [1557, 25])) + (blame_entry [1558, 4] - [1558, 25] + line: (number [1558, 11] - [1558, 14]) + date: (date [1558, 15] - [1558, 25])) + (blame_entry [1559, 4] - [1559, 25] + line: (number [1559, 11] - [1559, 14]) + date: (date [1559, 15] - [1559, 25])) + (blame_entry [1560, 4] - [1560, 25] + line: (number [1560, 11] - [1560, 14]) + date: (date [1560, 15] - [1560, 25]))) + (file_entry [1561, 0] - [1566, 24] + file_name: (filename [1561, 6] - [1561, 57]) + (blame_entry [1562, 4] - [1562, 23] + line: (number [1562, 11] - [1562, 12]) + date: (date [1562, 13] - [1562, 23])) + (blame_entry [1563, 4] - [1563, 23] + line: (number [1563, 11] - [1563, 12]) + date: (date [1563, 13] - [1563, 23])) + (blame_entry [1564, 4] - [1564, 24] + line: (number [1564, 11] - [1564, 13]) + date: (date [1564, 14] - [1564, 24])) + (blame_entry [1565, 4] - [1565, 24] + line: (number [1565, 11] - [1565, 13]) + date: (date [1565, 14] - [1565, 24])) + (blame_entry [1566, 4] - [1566, 24] + line: (number [1566, 11] - [1566, 13]) + date: (date [1566, 14] - [1566, 24]))) + (file_entry [1567, 0] - [1574, 24] + file_name: (filename [1567, 6] - [1567, 56]) + (blame_entry [1568, 4] - [1568, 23] + line: (number [1568, 11] - [1568, 12]) + date: (date [1568, 13] - [1568, 23])) + (blame_entry [1569, 4] - [1569, 23] + line: (number [1569, 11] - [1569, 12]) + date: (date [1569, 13] - [1569, 23])) + (blame_entry [1570, 4] - [1570, 24] + line: (number [1570, 11] - [1570, 13]) + date: (date [1570, 14] - [1570, 24])) + (blame_entry [1571, 4] - [1571, 24] + line: (number [1571, 11] - [1571, 13]) + date: (date [1571, 14] - [1571, 24])) + (blame_entry [1572, 4] - [1572, 24] + line: (number [1572, 11] - [1572, 13]) + date: (date [1572, 14] - [1572, 24])) + (blame_entry [1573, 4] - [1573, 24] + line: (number [1573, 11] - [1573, 13]) + date: (date [1573, 14] - [1573, 24])) + (blame_entry [1574, 4] - [1574, 24] + line: (number [1574, 11] - [1574, 13]) + date: (date [1574, 14] - [1574, 24]))) + (file_entry [1575, 0] - [1579, 25] + file_name: (filename [1575, 6] - [1575, 74]) + (blame_entry [1576, 4] - [1576, 24] + line: (number [1576, 11] - [1576, 13]) + date: (date [1576, 14] - [1576, 24])) + (blame_entry [1577, 4] - [1577, 25] + line: (number [1577, 11] - [1577, 14]) + date: (date [1577, 15] - [1577, 25])) + (blame_entry [1578, 4] - [1578, 25] + line: (number [1578, 11] - [1578, 14]) + date: (date [1578, 15] - [1578, 25])) + (blame_entry [1579, 4] - [1579, 25] + line: (number [1579, 11] - [1579, 14]) + date: (date [1579, 15] - [1579, 25]))) + (file_entry [1580, 0] - [1581, 24] + file_name: (filename [1580, 6] - [1580, 74]) + (blame_entry [1581, 4] - [1581, 24] + line: (number [1581, 11] - [1581, 13]) + date: (date [1581, 14] - [1581, 24]))) + (file_entry [1582, 0] - [1584, 24] + file_name: (filename [1582, 6] - [1582, 74]) + (blame_entry [1583, 4] - [1583, 24] + line: (number [1583, 11] - [1583, 13]) + date: (date [1583, 14] - [1583, 24])) + (blame_entry [1584, 4] - [1584, 24] + line: (number [1584, 11] - [1584, 13]) + date: (date [1584, 14] - [1584, 24]))) + (file_entry [1585, 0] - [1586, 24] + file_name: (filename [1585, 6] - [1585, 72]) + (blame_entry [1586, 4] - [1586, 24] + line: (number [1586, 11] - [1586, 13]) + date: (date [1586, 14] - [1586, 24]))) + (file_entry [1587, 0] - [1588, 24] + file_name: (filename [1587, 6] - [1587, 63]) + (blame_entry [1588, 4] - [1588, 24] + line: (number [1588, 11] - [1588, 13]) + date: (date [1588, 14] - [1588, 24]))) + (file_entry [1589, 0] - [1591, 25] + file_name: (filename [1589, 6] - [1589, 66]) + (blame_entry [1590, 4] - [1590, 25] + line: (number [1590, 11] - [1590, 14]) + date: (date [1590, 15] - [1590, 25])) + (blame_entry [1591, 4] - [1591, 25] + line: (number [1591, 11] - [1591, 14]) + date: (date [1591, 15] - [1591, 25]))) + (file_entry [1592, 0] - [1595, 24] + file_name: (filename [1592, 6] - [1592, 55]) + (blame_entry [1593, 4] - [1593, 23] + line: (number [1593, 11] - [1593, 12]) + date: (date [1593, 13] - [1593, 23])) + (blame_entry [1594, 4] - [1594, 24] + line: (number [1594, 11] - [1594, 13]) + date: (date [1594, 14] - [1594, 24])) + (blame_entry [1595, 4] - [1595, 24] + line: (number [1595, 11] - [1595, 13]) + date: (date [1595, 14] - [1595, 24]))) + (file_entry [1596, 0] - [1597, 24] + file_name: (filename [1596, 6] - [1596, 74]) + (blame_entry [1597, 4] - [1597, 24] + line: (number [1597, 11] - [1597, 13]) + date: (date [1597, 14] - [1597, 24]))) + (file_entry [1598, 0] - [1600, 24] + file_name: (filename [1598, 6] - [1598, 55]) + (blame_entry [1599, 4] - [1599, 23] + line: (number [1599, 11] - [1599, 12]) + date: (date [1599, 13] - [1599, 23])) + (blame_entry [1600, 4] - [1600, 24] + line: (number [1600, 11] - [1600, 13]) + date: (date [1600, 14] - [1600, 24]))) + (file_entry [1601, 0] - [1602, 24] + file_name: (filename [1601, 6] - [1601, 77]) + (blame_entry [1602, 4] - [1602, 24] + line: (number [1602, 11] - [1602, 13]) + date: (date [1602, 14] - [1602, 24]))) + (file_entry [1603, 0] - [1604, 25] + file_name: (filename [1603, 6] - [1603, 65]) + (blame_entry [1604, 4] - [1604, 25] + line: (number [1604, 11] - [1604, 14]) + date: (date [1604, 15] - [1604, 25]))) + (file_entry [1605, 0] - [1618, 25] + file_name: (filename [1605, 6] - [1605, 49]) + (blame_entry [1606, 4] - [1606, 24] + line: (number [1606, 11] - [1606, 13]) + date: (date [1606, 14] - [1606, 24])) + (blame_entry [1607, 4] - [1607, 24] + line: (number [1607, 11] - [1607, 13]) + date: (date [1607, 14] - [1607, 24])) + (blame_entry [1608, 4] - [1608, 25] + line: (number [1608, 11] - [1608, 14]) + date: (date [1608, 15] - [1608, 25])) + (blame_entry [1609, 4] - [1609, 25] + line: (number [1609, 11] - [1609, 14]) + date: (date [1609, 15] - [1609, 25])) + (blame_entry [1610, 4] - [1610, 25] + line: (number [1610, 11] - [1610, 14]) + date: (date [1610, 15] - [1610, 25])) + (blame_entry [1611, 4] - [1611, 25] + line: (number [1611, 11] - [1611, 14]) + date: (date [1611, 15] - [1611, 25])) + (blame_entry [1612, 4] - [1612, 25] + line: (number [1612, 11] - [1612, 14]) + date: (date [1612, 15] - [1612, 25])) + (blame_entry [1613, 4] - [1613, 25] + line: (number [1613, 11] - [1613, 14]) + date: (date [1613, 15] - [1613, 25])) + (blame_entry [1614, 4] - [1614, 25] + line: (number [1614, 11] - [1614, 14]) + date: (date [1614, 15] - [1614, 25])) + (blame_entry [1615, 4] - [1615, 25] + line: (number [1615, 11] - [1615, 14]) + date: (date [1615, 15] - [1615, 25])) + (blame_entry [1616, 4] - [1616, 25] + line: (number [1616, 11] - [1616, 14]) + date: (date [1616, 15] - [1616, 25])) + (blame_entry [1617, 4] - [1617, 25] + line: (number [1617, 11] - [1617, 14]) + date: (date [1617, 15] - [1617, 25])) + (blame_entry [1618, 4] - [1618, 25] + line: (number [1618, 11] - [1618, 14]) + date: (date [1618, 15] - [1618, 25]))) + (file_entry [1619, 0] - [1622, 25] + file_name: (filename [1619, 6] - [1619, 72]) + (blame_entry [1620, 4] - [1620, 24] + line: (number [1620, 11] - [1620, 13]) + date: (date [1620, 14] - [1620, 24])) + (blame_entry [1621, 4] - [1621, 24] + line: (number [1621, 11] - [1621, 13]) + date: (date [1621, 14] - [1621, 24])) + (blame_entry [1622, 4] - [1622, 25] + line: (number [1622, 11] - [1622, 14]) + date: (date [1622, 15] - [1622, 25]))) + (file_entry [1623, 0] - [1630, 25] + file_name: (filename [1623, 6] - [1623, 60]) + (blame_entry [1624, 4] - [1624, 24] + line: (number [1624, 11] - [1624, 13]) + date: (date [1624, 14] - [1624, 24])) + (blame_entry [1625, 4] - [1625, 24] + line: (number [1625, 11] - [1625, 13]) + date: (date [1625, 14] - [1625, 24])) + (blame_entry [1626, 4] - [1626, 24] + line: (number [1626, 11] - [1626, 13]) + date: (date [1626, 14] - [1626, 24])) + (blame_entry [1627, 4] - [1627, 25] + line: (number [1627, 11] - [1627, 14]) + date: (date [1627, 15] - [1627, 25])) + (blame_entry [1628, 4] - [1628, 25] + line: (number [1628, 11] - [1628, 14]) + date: (date [1628, 15] - [1628, 25])) + (blame_entry [1629, 4] - [1629, 25] + line: (number [1629, 11] - [1629, 14]) + date: (date [1629, 15] - [1629, 25])) + (blame_entry [1630, 4] - [1630, 25] + line: (number [1630, 11] - [1630, 14]) + date: (date [1630, 15] - [1630, 25]))) + (file_entry [1631, 0] - [1634, 25] + file_name: (filename [1631, 6] - [1631, 46]) + (blame_entry [1632, 4] - [1632, 24] + line: (number [1632, 11] - [1632, 13]) + date: (date [1632, 14] - [1632, 24])) + (blame_entry [1633, 4] - [1633, 24] + line: (number [1633, 11] - [1633, 13]) + date: (date [1633, 14] - [1633, 24])) + (blame_entry [1634, 4] - [1634, 25] + line: (number [1634, 11] - [1634, 14]) + date: (date [1634, 15] - [1634, 25]))) + (file_entry [1635, 0] - [1636, 24] + file_name: (filename [1635, 6] - [1635, 65]) + (blame_entry [1636, 4] - [1636, 24] + line: (number [1636, 11] - [1636, 13]) + date: (date [1636, 14] - [1636, 24]))) + (file_entry [1637, 0] - [1638, 26] + file_name: (filename [1637, 6] - [1637, 70]) + (blame_entry [1638, 4] - [1638, 26] + line: (number [1638, 11] - [1638, 15]) + date: (date [1638, 16] - [1638, 26]))) + (file_entry [1639, 0] - [1640, 24] + file_name: (filename [1639, 6] - [1639, 83]) + (blame_entry [1640, 4] - [1640, 24] + line: (number [1640, 11] - [1640, 13]) + date: (date [1640, 14] - [1640, 24]))) + (file_entry [1641, 0] - [1643, 24] + file_name: (filename [1641, 6] - [1641, 57]) + (blame_entry [1642, 4] - [1642, 24] + line: (number [1642, 11] - [1642, 13]) + date: (date [1642, 14] - [1642, 24])) + (blame_entry [1643, 4] - [1643, 24] + line: (number [1643, 11] - [1643, 13]) + date: (date [1643, 14] - [1643, 24]))) + (file_entry [1644, 0] - [1645, 24] + file_name: (filename [1644, 6] - [1644, 43]) + (blame_entry [1645, 4] - [1645, 24] + line: (number [1645, 11] - [1645, 13]) + date: (date [1645, 14] - [1645, 24]))) + (file_entry [1646, 0] - [1648, 24] + file_name: (filename [1646, 6] - [1646, 54]) + (blame_entry [1647, 4] - [1647, 24] + line: (number [1647, 11] - [1647, 13]) + date: (date [1647, 14] - [1647, 24])) + (blame_entry [1648, 4] - [1648, 24] + line: (number [1648, 11] - [1648, 13]) + date: (date [1648, 14] - [1648, 24]))) + (file_entry [1649, 0] - [1650, 25] + file_name: (filename [1649, 6] - [1649, 43]) + (blame_entry [1650, 4] - [1650, 25] + line: (number [1650, 11] - [1650, 14]) + date: (date [1650, 15] - [1650, 25]))) + (file_entry [1651, 0] - [1653, 24] + file_name: (filename [1651, 6] - [1651, 57]) + (blame_entry [1652, 4] - [1652, 23] + line: (number [1652, 11] - [1652, 12]) + date: (date [1652, 13] - [1652, 23])) + (blame_entry [1653, 4] - [1653, 24] + line: (number [1653, 11] - [1653, 13]) + date: (date [1653, 14] - [1653, 24]))) + (file_entry [1654, 0] - [1655, 24] + file_name: (filename [1654, 6] - [1654, 61]) + (blame_entry [1655, 4] - [1655, 24] + line: (number [1655, 11] - [1655, 13]) + date: (date [1655, 14] - [1655, 24]))) + (file_entry [1656, 0] - [1658, 25] + file_name: (filename [1656, 6] - [1656, 86]) + (blame_entry [1657, 4] - [1657, 25] + line: (number [1657, 11] - [1657, 14]) + date: (date [1657, 15] - [1657, 25])) + (blame_entry [1658, 4] - [1658, 25] + line: (number [1658, 11] - [1658, 14]) + date: (date [1658, 15] - [1658, 25]))) + (file_entry [1659, 0] - [1660, 25] + file_name: (filename [1659, 6] - [1659, 82]) + (blame_entry [1660, 4] - [1660, 25] + line: (number [1660, 11] - [1660, 14]) + date: (date [1660, 15] - [1660, 25]))) + (file_entry [1661, 0] - [1662, 24] + file_name: (filename [1661, 6] - [1661, 70]) + (blame_entry [1662, 4] - [1662, 24] + line: (number [1662, 11] - [1662, 13]) + date: (date [1662, 14] - [1662, 24]))) + (file_entry [1663, 0] - [1671, 25] + file_name: (filename [1663, 6] - [1663, 46]) + (blame_entry [1664, 4] - [1664, 24] + line: (number [1664, 11] - [1664, 13]) + date: (date [1664, 14] - [1664, 24])) + (blame_entry [1665, 4] - [1665, 25] + line: (number [1665, 11] - [1665, 14]) + date: (date [1665, 15] - [1665, 25])) + (blame_entry [1666, 4] - [1666, 25] + line: (number [1666, 11] - [1666, 14]) + date: (date [1666, 15] - [1666, 25])) + (blame_entry [1667, 4] - [1667, 25] + line: (number [1667, 11] - [1667, 14]) + date: (date [1667, 15] - [1667, 25])) + (blame_entry [1668, 4] - [1668, 25] + line: (number [1668, 11] - [1668, 14]) + date: (date [1668, 15] - [1668, 25])) + (blame_entry [1669, 4] - [1669, 25] + line: (number [1669, 11] - [1669, 14]) + date: (date [1669, 15] - [1669, 25])) + (blame_entry [1670, 4] - [1670, 25] + line: (number [1670, 11] - [1670, 14]) + date: (date [1670, 15] - [1670, 25])) + (blame_entry [1671, 4] - [1671, 25] + line: (number [1671, 11] - [1671, 14]) + date: (date [1671, 15] - [1671, 25]))) + (file_entry [1672, 0] - [1675, 24] + file_name: (filename [1672, 6] - [1672, 44]) + (blame_entry [1673, 4] - [1673, 23] + line: (number [1673, 11] - [1673, 12]) + date: (date [1673, 13] - [1673, 23])) + (blame_entry [1674, 4] - [1674, 24] + line: (number [1674, 11] - [1674, 13]) + date: (date [1674, 14] - [1674, 24])) + (blame_entry [1675, 4] - [1675, 24] + line: (number [1675, 11] - [1675, 13]) + date: (date [1675, 14] - [1675, 24]))) + (file_entry [1676, 0] - [1679, 24] + file_name: (filename [1676, 6] - [1676, 68]) + (blame_entry [1677, 4] - [1677, 23] + line: (number [1677, 11] - [1677, 12]) + date: (date [1677, 13] - [1677, 23])) + (blame_entry [1678, 4] - [1678, 24] + line: (number [1678, 11] - [1678, 13]) + date: (date [1678, 14] - [1678, 24])) + (blame_entry [1679, 4] - [1679, 24] + line: (number [1679, 11] - [1679, 13]) + date: (date [1679, 14] - [1679, 24]))) + (file_entry [1680, 0] - [1684, 25] + file_name: (filename [1680, 6] - [1680, 80]) + (blame_entry [1681, 4] - [1681, 25] + line: (number [1681, 11] - [1681, 14]) + date: (date [1681, 15] - [1681, 25])) + (blame_entry [1682, 4] - [1682, 25] + line: (number [1682, 11] - [1682, 14]) + date: (date [1682, 15] - [1682, 25])) + (blame_entry [1683, 4] - [1683, 25] + line: (number [1683, 11] - [1683, 14]) + date: (date [1683, 15] - [1683, 25])) + (blame_entry [1684, 4] - [1684, 25] + line: (number [1684, 11] - [1684, 14]) + date: (date [1684, 15] - [1684, 25]))) + (file_entry [1685, 0] - [1688, 25] + file_name: (filename [1685, 6] - [1685, 92]) + (blame_entry [1686, 4] - [1686, 24] + line: (number [1686, 11] - [1686, 13]) + date: (date [1686, 14] - [1686, 24])) + (blame_entry [1687, 4] - [1687, 25] + line: (number [1687, 11] - [1687, 14]) + date: (date [1687, 15] - [1687, 25])) + (blame_entry [1688, 4] - [1688, 25] + line: (number [1688, 11] - [1688, 14]) + date: (date [1688, 15] - [1688, 25]))) + (file_entry [1689, 0] - [1690, 23] + file_name: (filename [1689, 6] - [1689, 72]) + (blame_entry [1690, 4] - [1690, 23] + line: (number [1690, 11] - [1690, 12]) + date: (date [1690, 13] - [1690, 23]))) + (file_entry [1691, 0] - [1692, 24] + file_name: (filename [1691, 6] - [1691, 92]) + (blame_entry [1692, 4] - [1692, 24] + line: (number [1692, 11] - [1692, 13]) + date: (date [1692, 14] - [1692, 24]))) + (file_entry [1693, 0] - [1695, 24] + file_name: (filename [1693, 6] - [1693, 65]) + (blame_entry [1694, 4] - [1694, 24] + line: (number [1694, 11] - [1694, 13]) + date: (date [1694, 14] - [1694, 24])) + (blame_entry [1695, 4] - [1695, 24] + line: (number [1695, 11] - [1695, 13]) + date: (date [1695, 14] - [1695, 24]))) + (file_entry [1696, 0] - [1698, 24] + file_name: (filename [1696, 6] - [1696, 62]) + (blame_entry [1697, 4] - [1697, 24] + line: (number [1697, 11] - [1697, 13]) + date: (date [1697, 14] - [1697, 24])) + (blame_entry [1698, 4] - [1698, 24] + line: (number [1698, 11] - [1698, 13]) + date: (date [1698, 14] - [1698, 24]))) + (file_entry [1699, 0] - [1703, 25] + file_name: (filename [1699, 6] - [1699, 93]) + (blame_entry [1700, 4] - [1700, 25] + line: (number [1700, 11] - [1700, 14]) + date: (date [1700, 15] - [1700, 25])) + (blame_entry [1701, 4] - [1701, 25] + line: (number [1701, 11] - [1701, 14]) + date: (date [1701, 15] - [1701, 25])) + (blame_entry [1702, 4] - [1702, 25] + line: (number [1702, 11] - [1702, 14]) + date: (date [1702, 15] - [1702, 25])) + (blame_entry [1703, 4] - [1703, 25] + line: (number [1703, 11] - [1703, 14]) + date: (date [1703, 15] - [1703, 25]))) + (file_entry [1704, 0] - [1708, 25] + file_name: (filename [1704, 6] - [1704, 71]) + (blame_entry [1705, 4] - [1705, 24] + line: (number [1705, 11] - [1705, 13]) + date: (date [1705, 14] - [1705, 24])) + (blame_entry [1706, 4] - [1706, 25] + line: (number [1706, 11] - [1706, 14]) + date: (date [1706, 15] - [1706, 25])) + (blame_entry [1707, 4] - [1707, 25] + line: (number [1707, 11] - [1707, 14]) + date: (date [1707, 15] - [1707, 25])) + (blame_entry [1708, 4] - [1708, 25] + line: (number [1708, 11] - [1708, 14]) + date: (date [1708, 15] - [1708, 25]))) + (file_entry [1709, 0] - [1710, 24] + file_name: (filename [1709, 6] - [1709, 68]) + (blame_entry [1710, 4] - [1710, 24] + line: (number [1710, 11] - [1710, 13]) + date: (date [1710, 14] - [1710, 24]))) + (file_entry [1711, 0] - [1715, 26] + file_name: (filename [1711, 6] - [1711, 52]) + (blame_entry [1712, 4] - [1712, 26] + line: (number [1712, 11] - [1712, 15]) + date: (date [1712, 16] - [1712, 26])) + (blame_entry [1713, 4] - [1713, 26] + line: (number [1713, 11] - [1713, 15]) + date: (date [1713, 16] - [1713, 26])) + (blame_entry [1714, 4] - [1714, 26] + line: (number [1714, 11] - [1714, 15]) + date: (date [1714, 16] - [1714, 26])) + (blame_entry [1715, 4] - [1715, 26] + line: (number [1715, 11] - [1715, 15]) + date: (date [1715, 16] - [1715, 26]))) + (file_entry [1716, 0] - [1719, 25] + file_name: (filename [1716, 6] - [1716, 58]) + (blame_entry [1717, 4] - [1717, 25] + line: (number [1717, 11] - [1717, 14]) + date: (date [1717, 15] - [1717, 25])) + (blame_entry [1718, 4] - [1718, 25] + line: (number [1718, 11] - [1718, 14]) + date: (date [1718, 15] - [1718, 25])) + (blame_entry [1719, 4] - [1719, 25] + line: (number [1719, 11] - [1719, 14]) + date: (date [1719, 15] - [1719, 25]))) + (file_entry [1720, 0] - [1722, 24] + file_name: (filename [1720, 6] - [1720, 101]) + (blame_entry [1721, 4] - [1721, 23] + line: (number [1721, 11] - [1721, 12]) + date: (date [1721, 13] - [1721, 23])) + (blame_entry [1722, 4] - [1722, 24] + line: (number [1722, 11] - [1722, 13]) + date: (date [1722, 14] - [1722, 24]))) + (file_entry [1723, 0] - [1725, 24] + file_name: (filename [1723, 6] - [1723, 62]) + (blame_entry [1724, 4] - [1724, 24] + line: (number [1724, 11] - [1724, 13]) + date: (date [1724, 14] - [1724, 24])) + (blame_entry [1725, 4] - [1725, 24] + line: (number [1725, 11] - [1725, 13]) + date: (date [1725, 14] - [1725, 24]))) + (file_entry [1726, 0] - [1728, 24] + file_name: (filename [1726, 6] - [1726, 82]) + (blame_entry [1727, 4] - [1727, 24] + line: (number [1727, 11] - [1727, 13]) + date: (date [1727, 14] - [1727, 24])) + (blame_entry [1728, 4] - [1728, 24] + line: (number [1728, 11] - [1728, 13]) + date: (date [1728, 14] - [1728, 24]))) + (file_entry [1729, 0] - [1730, 23] + file_name: (filename [1729, 6] - [1729, 64]) + (blame_entry [1730, 4] - [1730, 23] + line: (number [1730, 11] - [1730, 12]) + date: (date [1730, 13] - [1730, 23]))) + (file_entry [1731, 0] - [1732, 23] + file_name: (filename [1731, 6] - [1731, 61]) + (blame_entry [1732, 4] - [1732, 23] + line: (number [1732, 11] - [1732, 12]) + date: (date [1732, 13] - [1732, 23]))) + (file_entry [1733, 0] - [1744, 24] + file_name: (filename [1733, 6] - [1733, 55]) + (blame_entry [1734, 4] - [1734, 23] + line: (number [1734, 11] - [1734, 12]) + date: (date [1734, 13] - [1734, 23])) + (blame_entry [1735, 4] - [1735, 23] + line: (number [1735, 11] - [1735, 12]) + date: (date [1735, 13] - [1735, 23])) + (blame_entry [1736, 4] - [1736, 24] + line: (number [1736, 11] - [1736, 13]) + date: (date [1736, 14] - [1736, 24])) + (blame_entry [1737, 4] - [1737, 24] + line: (number [1737, 11] - [1737, 13]) + date: (date [1737, 14] - [1737, 24])) + (blame_entry [1738, 4] - [1738, 24] + line: (number [1738, 11] - [1738, 13]) + date: (date [1738, 14] - [1738, 24])) + (blame_entry [1739, 4] - [1739, 24] + line: (number [1739, 11] - [1739, 13]) + date: (date [1739, 14] - [1739, 24])) + (blame_entry [1740, 4] - [1740, 24] + line: (number [1740, 11] - [1740, 13]) + date: (date [1740, 14] - [1740, 24])) + (blame_entry [1741, 4] - [1741, 24] + line: (number [1741, 11] - [1741, 13]) + date: (date [1741, 14] - [1741, 24])) + (blame_entry [1742, 4] - [1742, 24] + line: (number [1742, 11] - [1742, 13]) + date: (date [1742, 14] - [1742, 24])) + (blame_entry [1743, 4] - [1743, 24] + line: (number [1743, 11] - [1743, 13]) + date: (date [1743, 14] - [1743, 24])) + (blame_entry [1744, 4] - [1744, 24] + line: (number [1744, 11] - [1744, 13]) + date: (date [1744, 14] - [1744, 24]))) + (file_entry [1745, 0] - [1748, 24] + file_name: (filename [1745, 6] - [1745, 63]) + (blame_entry [1746, 4] - [1746, 24] + line: (number [1746, 11] - [1746, 13]) + date: (date [1746, 14] - [1746, 24])) + (blame_entry [1747, 4] - [1747, 24] + line: (number [1747, 11] - [1747, 13]) + date: (date [1747, 14] - [1747, 24])) + (blame_entry [1748, 4] - [1748, 24] + line: (number [1748, 11] - [1748, 13]) + date: (date [1748, 14] - [1748, 24]))) + (file_entry [1749, 0] - [1753, 25] + file_name: (filename [1749, 6] - [1749, 90]) + (blame_entry [1750, 4] - [1750, 25] + line: (number [1750, 11] - [1750, 14]) + date: (date [1750, 15] - [1750, 25])) + (blame_entry [1751, 4] - [1751, 25] + line: (number [1751, 11] - [1751, 14]) + date: (date [1751, 15] - [1751, 25])) + (blame_entry [1752, 4] - [1752, 25] + line: (number [1752, 11] - [1752, 14]) + date: (date [1752, 15] - [1752, 25])) + (blame_entry [1753, 4] - [1753, 25] + line: (number [1753, 11] - [1753, 14]) + date: (date [1753, 15] - [1753, 25]))) + (file_entry [1754, 0] - [1765, 25] + file_name: (filename [1754, 6] - [1754, 70]) + (blame_entry [1755, 4] - [1755, 23] + line: (number [1755, 11] - [1755, 12]) + date: (date [1755, 13] - [1755, 23])) + (blame_entry [1756, 4] - [1756, 24] + line: (number [1756, 11] - [1756, 13]) + date: (date [1756, 14] - [1756, 24])) + (blame_entry [1757, 4] - [1757, 24] + line: (number [1757, 11] - [1757, 13]) + date: (date [1757, 14] - [1757, 24])) + (blame_entry [1758, 4] - [1758, 24] + line: (number [1758, 11] - [1758, 13]) + date: (date [1758, 14] - [1758, 24])) + (blame_entry [1759, 4] - [1759, 24] + line: (number [1759, 11] - [1759, 13]) + date: (date [1759, 14] - [1759, 24])) + (blame_entry [1760, 4] - [1760, 24] + line: (number [1760, 11] - [1760, 13]) + date: (date [1760, 14] - [1760, 24])) + (blame_entry [1761, 4] - [1761, 24] + line: (number [1761, 11] - [1761, 13]) + date: (date [1761, 14] - [1761, 24])) + (blame_entry [1762, 4] - [1762, 24] + line: (number [1762, 11] - [1762, 13]) + date: (date [1762, 14] - [1762, 24])) + (blame_entry [1763, 4] - [1763, 24] + line: (number [1763, 11] - [1763, 13]) + date: (date [1763, 14] - [1763, 24])) + (blame_entry [1764, 4] - [1764, 24] + line: (number [1764, 11] - [1764, 13]) + date: (date [1764, 14] - [1764, 24])) + (blame_entry [1765, 4] - [1765, 25] + line: (number [1765, 11] - [1765, 14]) + date: (date [1765, 15] - [1765, 25]))) + (file_entry [1766, 0] - [1768, 24] + file_name: (filename [1766, 6] - [1766, 62]) + (blame_entry [1767, 4] - [1767, 24] + line: (number [1767, 11] - [1767, 13]) + date: (date [1767, 14] - [1767, 24])) + (blame_entry [1768, 4] - [1768, 24] + line: (number [1768, 11] - [1768, 13]) + date: (date [1768, 14] - [1768, 24]))) + (file_entry [1769, 0] - [1773, 25] + file_name: (filename [1769, 6] - [1769, 67]) + (blame_entry [1770, 4] - [1770, 24] + line: (number [1770, 11] - [1770, 13]) + date: (date [1770, 14] - [1770, 24])) + (blame_entry [1771, 4] - [1771, 25] + line: (number [1771, 11] - [1771, 14]) + date: (date [1771, 15] - [1771, 25])) + (blame_entry [1772, 4] - [1772, 25] + line: (number [1772, 11] - [1772, 14]) + date: (date [1772, 15] - [1772, 25])) + (blame_entry [1773, 4] - [1773, 25] + line: (number [1773, 11] - [1773, 14]) + date: (date [1773, 15] - [1773, 25]))) + (file_entry [1774, 0] - [1780, 25] + file_name: (filename [1774, 6] - [1774, 55]) + (blame_entry [1775, 4] - [1775, 25] + line: (number [1775, 11] - [1775, 14]) + date: (date [1775, 15] - [1775, 25])) + (blame_entry [1776, 4] - [1776, 25] + line: (number [1776, 11] - [1776, 14]) + date: (date [1776, 15] - [1776, 25])) + (blame_entry [1777, 4] - [1777, 25] + line: (number [1777, 11] - [1777, 14]) + date: (date [1777, 15] - [1777, 25])) + (blame_entry [1778, 4] - [1778, 25] + line: (number [1778, 11] - [1778, 14]) + date: (date [1778, 15] - [1778, 25])) + (blame_entry [1779, 4] - [1779, 25] + line: (number [1779, 11] - [1779, 14]) + date: (date [1779, 15] - [1779, 25])) + (blame_entry [1780, 4] - [1780, 25] + line: (number [1780, 11] - [1780, 14]) + date: (date [1780, 15] - [1780, 25]))) + (file_entry [1781, 0] - [1783, 24] + file_name: (filename [1781, 6] - [1781, 64]) + (blame_entry [1782, 4] - [1782, 24] + line: (number [1782, 11] - [1782, 13]) + date: (date [1782, 14] - [1782, 24])) + (blame_entry [1783, 4] - [1783, 24] + line: (number [1783, 11] - [1783, 13]) + date: (date [1783, 14] - [1783, 24]))) + (file_entry [1784, 0] - [1785, 23] + file_name: (filename [1784, 6] - [1784, 83]) + (blame_entry [1785, 4] - [1785, 23] + line: (number [1785, 11] - [1785, 12]) + date: (date [1785, 13] - [1785, 23]))) + (file_entry [1786, 0] - [1789, 24] + file_name: (filename [1786, 6] - [1786, 75]) + (blame_entry [1787, 4] - [1787, 24] + line: (number [1787, 11] - [1787, 13]) + date: (date [1787, 14] - [1787, 24])) + (blame_entry [1788, 4] - [1788, 24] + line: (number [1788, 11] - [1788, 13]) + date: (date [1788, 14] - [1788, 24])) + (blame_entry [1789, 4] - [1789, 24] + line: (number [1789, 11] - [1789, 13]) + date: (date [1789, 14] - [1789, 24]))) + (file_entry [1790, 0] - [1792, 24] + file_name: (filename [1790, 6] - [1790, 62]) + (blame_entry [1791, 4] - [1791, 24] + line: (number [1791, 11] - [1791, 13]) + date: (date [1791, 14] - [1791, 24])) + (blame_entry [1792, 4] - [1792, 24] + line: (number [1792, 11] - [1792, 13]) + date: (date [1792, 14] - [1792, 24]))) + (file_entry [1793, 0] - [1794, 24] + file_name: (filename [1793, 6] - [1793, 52]) + (blame_entry [1794, 4] - [1794, 24] + line: (number [1794, 11] - [1794, 13]) + date: (date [1794, 14] - [1794, 24]))) + (file_entry [1795, 0] - [1797, 25] + file_name: (filename [1795, 6] - [1795, 55]) + (blame_entry [1796, 4] - [1796, 24] + line: (number [1796, 11] - [1796, 13]) + date: (date [1796, 14] - [1796, 24])) + (blame_entry [1797, 4] - [1797, 25] + line: (number [1797, 11] - [1797, 14]) + date: (date [1797, 15] - [1797, 25]))) + (file_entry [1798, 0] - [1799, 23] + file_name: (filename [1798, 6] - [1798, 70]) + (blame_entry [1799, 4] - [1799, 23] + line: (number [1799, 11] - [1799, 12]) + date: (date [1799, 13] - [1799, 23]))) + (file_entry [1800, 0] - [1801, 24] + file_name: (filename [1800, 6] - [1800, 75]) + (blame_entry [1801, 4] - [1801, 24] + line: (number [1801, 11] - [1801, 13]) + date: (date [1801, 14] - [1801, 24]))) + (file_entry [1802, 0] - [1805, 25] + file_name: (filename [1802, 6] - [1802, 79]) + (blame_entry [1803, 4] - [1803, 24] + line: (number [1803, 11] - [1803, 13]) + date: (date [1803, 14] - [1803, 24])) + (blame_entry [1804, 4] - [1804, 24] + line: (number [1804, 11] - [1804, 13]) + date: (date [1804, 14] - [1804, 24])) + (blame_entry [1805, 4] - [1805, 25] + line: (number [1805, 11] - [1805, 14]) + date: (date [1805, 15] - [1805, 25]))) + (file_entry [1806, 0] - [1810, 25] + file_name: (filename [1806, 6] - [1806, 66]) + (blame_entry [1807, 4] - [1807, 24] + line: (number [1807, 11] - [1807, 13]) + date: (date [1807, 14] - [1807, 24])) + (blame_entry [1808, 4] - [1808, 25] + line: (number [1808, 11] - [1808, 14]) + date: (date [1808, 15] - [1808, 25])) + (blame_entry [1809, 4] - [1809, 25] + line: (number [1809, 11] - [1809, 14]) + date: (date [1809, 15] - [1809, 25])) + (blame_entry [1810, 4] - [1810, 25] + line: (number [1810, 11] - [1810, 14]) + date: (date [1810, 15] - [1810, 25]))) + (file_entry [1811, 0] - [1820, 25] + file_name: (filename [1811, 6] - [1811, 68]) + (blame_entry [1812, 4] - [1812, 24] + line: (number [1812, 11] - [1812, 13]) + date: (date [1812, 14] - [1812, 24])) + (blame_entry [1813, 4] - [1813, 24] + line: (number [1813, 11] - [1813, 13]) + date: (date [1813, 14] - [1813, 24])) + (blame_entry [1814, 4] - [1814, 24] + line: (number [1814, 11] - [1814, 13]) + date: (date [1814, 14] - [1814, 24])) + (blame_entry [1815, 4] - [1815, 24] + line: (number [1815, 11] - [1815, 13]) + date: (date [1815, 14] - [1815, 24])) + (blame_entry [1816, 4] - [1816, 24] + line: (number [1816, 11] - [1816, 13]) + date: (date [1816, 14] - [1816, 24])) + (blame_entry [1817, 4] - [1817, 25] + line: (number [1817, 11] - [1817, 14]) + date: (date [1817, 15] - [1817, 25])) + (blame_entry [1818, 4] - [1818, 25] + line: (number [1818, 11] - [1818, 14]) + date: (date [1818, 15] - [1818, 25])) + (blame_entry [1819, 4] - [1819, 25] + line: (number [1819, 11] - [1819, 14]) + date: (date [1819, 15] - [1819, 25])) + (blame_entry [1820, 4] - [1820, 25] + line: (number [1820, 11] - [1820, 14]) + date: (date [1820, 15] - [1820, 25]))) + (file_entry [1821, 0] - [1824, 24] + file_name: (filename [1821, 6] - [1821, 87]) + (blame_entry [1822, 4] - [1822, 24] + line: (number [1822, 11] - [1822, 13]) + date: (date [1822, 14] - [1822, 24])) + (blame_entry [1823, 4] - [1823, 24] + line: (number [1823, 11] - [1823, 13]) + date: (date [1823, 14] - [1823, 24])) + (blame_entry [1824, 4] - [1824, 24] + line: (number [1824, 11] - [1824, 13]) + date: (date [1824, 14] - [1824, 24]))) + (file_entry [1825, 0] - [1829, 25] + file_name: (filename [1825, 6] - [1825, 71]) + (blame_entry [1826, 4] - [1826, 24] + line: (number [1826, 11] - [1826, 13]) + date: (date [1826, 14] - [1826, 24])) + (blame_entry [1827, 4] - [1827, 25] + line: (number [1827, 11] - [1827, 14]) + date: (date [1827, 15] - [1827, 25])) + (blame_entry [1828, 4] - [1828, 25] + line: (number [1828, 11] - [1828, 14]) + date: (date [1828, 15] - [1828, 25])) + (blame_entry [1829, 4] - [1829, 25] + line: (number [1829, 11] - [1829, 14]) + date: (date [1829, 15] - [1829, 25]))) + (file_entry [1830, 0] - [1831, 23] + file_name: (filename [1830, 6] - [1830, 78]) + (blame_entry [1831, 4] - [1831, 23] + line: (number [1831, 11] - [1831, 12]) + date: (date [1831, 13] - [1831, 23]))) + (file_entry [1832, 0] - [1841, 25] + file_name: (filename [1832, 6] - [1832, 86]) + (blame_entry [1833, 4] - [1833, 24] + line: (number [1833, 11] - [1833, 13]) + date: (date [1833, 14] - [1833, 24])) + (blame_entry [1834, 4] - [1834, 25] + line: (number [1834, 11] - [1834, 14]) + date: (date [1834, 15] - [1834, 25])) + (blame_entry [1835, 4] - [1835, 25] + line: (number [1835, 11] - [1835, 14]) + date: (date [1835, 15] - [1835, 25])) + (blame_entry [1836, 4] - [1836, 25] + line: (number [1836, 11] - [1836, 14]) + date: (date [1836, 15] - [1836, 25])) + (blame_entry [1837, 4] - [1837, 25] + line: (number [1837, 11] - [1837, 14]) + date: (date [1837, 15] - [1837, 25])) + (blame_entry [1838, 4] - [1838, 25] + line: (number [1838, 11] - [1838, 14]) + date: (date [1838, 15] - [1838, 25])) + (blame_entry [1839, 4] - [1839, 25] + line: (number [1839, 11] - [1839, 14]) + date: (date [1839, 15] - [1839, 25])) + (blame_entry [1840, 4] - [1840, 25] + line: (number [1840, 11] - [1840, 14]) + date: (date [1840, 15] - [1840, 25])) + (blame_entry [1841, 4] - [1841, 25] + line: (number [1841, 11] - [1841, 14]) + date: (date [1841, 15] - [1841, 25]))) + (file_entry [1842, 0] - [1843, 26] + file_name: (filename [1842, 6] - [1842, 83]) + (blame_entry [1843, 4] - [1843, 26] + line: (number [1843, 11] - [1843, 15]) + date: (date [1843, 16] - [1843, 26]))) + (file_entry [1844, 0] - [1845, 23] + file_name: (filename [1844, 6] - [1844, 76]) + (blame_entry [1845, 4] - [1845, 23] + line: (number [1845, 11] - [1845, 12]) + date: (date [1845, 13] - [1845, 23]))) + (file_entry [1846, 0] - [1853, 25] + file_name: (filename [1846, 6] - [1846, 49]) + (blame_entry [1847, 4] - [1847, 25] + line: (number [1847, 11] - [1847, 14]) + date: (date [1847, 15] - [1847, 25])) + (blame_entry [1848, 4] - [1848, 25] + line: (number [1848, 11] - [1848, 14]) + date: (date [1848, 15] - [1848, 25])) + (blame_entry [1849, 4] - [1849, 25] + line: (number [1849, 11] - [1849, 14]) + date: (date [1849, 15] - [1849, 25])) + (blame_entry [1850, 4] - [1850, 25] + line: (number [1850, 11] - [1850, 14]) + date: (date [1850, 15] - [1850, 25])) + (blame_entry [1851, 4] - [1851, 25] + line: (number [1851, 11] - [1851, 14]) + date: (date [1851, 15] - [1851, 25])) + (blame_entry [1852, 4] - [1852, 25] + line: (number [1852, 11] - [1852, 14]) + date: (date [1852, 15] - [1852, 25])) + (blame_entry [1853, 4] - [1853, 25] + line: (number [1853, 11] - [1853, 14]) + date: (date [1853, 15] - [1853, 25]))) + (file_entry [1854, 0] - [1856, 24] + file_name: (filename [1854, 6] - [1854, 57]) + (blame_entry [1855, 4] - [1855, 23] + line: (number [1855, 11] - [1855, 12]) + date: (date [1855, 13] - [1855, 23])) + (blame_entry [1856, 4] - [1856, 24] + line: (number [1856, 11] - [1856, 13]) + date: (date [1856, 14] - [1856, 24]))) + (file_entry [1857, 0] - [1858, 23] + file_name: (filename [1857, 6] - [1857, 48]) + (blame_entry [1858, 4] - [1858, 23] + line: (number [1858, 11] - [1858, 12]) + date: (date [1858, 13] - [1858, 23]))) + (file_entry [1859, 0] - [1861, 25] + file_name: (filename [1859, 6] - [1859, 70]) + (blame_entry [1860, 4] - [1860, 25] + line: (number [1860, 11] - [1860, 14]) + date: (date [1860, 15] - [1860, 25])) + (blame_entry [1861, 4] - [1861, 25] + line: (number [1861, 11] - [1861, 14]) + date: (date [1861, 15] - [1861, 25]))) + (file_entry [1862, 0] - [1866, 24] + file_name: (filename [1862, 6] - [1862, 56]) + (blame_entry [1863, 4] - [1863, 23] + line: (number [1863, 11] - [1863, 12]) + date: (date [1863, 13] - [1863, 23])) + (blame_entry [1864, 4] - [1864, 23] + line: (number [1864, 11] - [1864, 12]) + date: (date [1864, 13] - [1864, 23])) + (blame_entry [1865, 4] - [1865, 24] + line: (number [1865, 11] - [1865, 13]) + date: (date [1865, 14] - [1865, 24])) + (blame_entry [1866, 4] - [1866, 24] + line: (number [1866, 11] - [1866, 13]) + date: (date [1866, 14] - [1866, 24]))) + (file_entry [1867, 0] - [1871, 24] + file_name: (filename [1867, 6] - [1867, 60]) + (blame_entry [1868, 4] - [1868, 24] + line: (number [1868, 11] - [1868, 13]) + date: (date [1868, 14] - [1868, 24])) + (blame_entry [1869, 4] - [1869, 24] + line: (number [1869, 11] - [1869, 13]) + date: (date [1869, 14] - [1869, 24])) + (blame_entry [1870, 4] - [1870, 24] + line: (number [1870, 11] - [1870, 13]) + date: (date [1870, 14] - [1870, 24])) + (blame_entry [1871, 4] - [1871, 24] + line: (number [1871, 11] - [1871, 13]) + date: (date [1871, 14] - [1871, 24]))) + (file_entry [1872, 0] - [1873, 25] + file_name: (filename [1872, 6] - [1872, 74]) + (blame_entry [1873, 4] - [1873, 25] + line: (number [1873, 11] - [1873, 14]) + date: (date [1873, 15] - [1873, 25]))) + (file_entry [1874, 0] - [1878, 25] + file_name: (filename [1874, 6] - [1874, 87]) + (blame_entry [1875, 4] - [1875, 24] + line: (number [1875, 11] - [1875, 13]) + date: (date [1875, 14] - [1875, 24])) + (blame_entry [1876, 4] - [1876, 25] + line: (number [1876, 11] - [1876, 14]) + date: (date [1876, 15] - [1876, 25])) + (blame_entry [1877, 4] - [1877, 25] + line: (number [1877, 11] - [1877, 14]) + date: (date [1877, 15] - [1877, 25])) + (blame_entry [1878, 4] - [1878, 25] + line: (number [1878, 11] - [1878, 14]) + date: (date [1878, 15] - [1878, 25]))) + (file_entry [1879, 0] - [1880, 24] + file_name: (filename [1879, 6] - [1879, 84]) + (blame_entry [1880, 4] - [1880, 24] + line: (number [1880, 11] - [1880, 13]) + date: (date [1880, 14] - [1880, 24]))) + (file_entry [1881, 0] - [1886, 26] + file_name: (filename [1881, 6] - [1881, 37]) + (blame_entry [1882, 4] - [1882, 26] + line: (number [1882, 11] - [1882, 15]) + date: (date [1882, 16] - [1882, 26])) + (blame_entry [1883, 4] - [1883, 26] + line: (number [1883, 11] - [1883, 15]) + date: (date [1883, 16] - [1883, 26])) + (blame_entry [1884, 4] - [1884, 26] + line: (number [1884, 11] - [1884, 15]) + date: (date [1884, 16] - [1884, 26])) + (blame_entry [1885, 4] - [1885, 26] + line: (number [1885, 11] - [1885, 15]) + date: (date [1885, 16] - [1885, 26])) + (blame_entry [1886, 4] - [1886, 26] + line: (number [1886, 11] - [1886, 15]) + date: (date [1886, 16] - [1886, 26]))) + (file_entry [1887, 0] - [1891, 25] + file_name: (filename [1887, 6] - [1887, 53]) + (blame_entry [1888, 4] - [1888, 23] + line: (number [1888, 11] - [1888, 12]) + date: (date [1888, 13] - [1888, 23])) + (blame_entry [1889, 4] - [1889, 24] + line: (number [1889, 11] - [1889, 13]) + date: (date [1889, 14] - [1889, 24])) + (blame_entry [1890, 4] - [1890, 24] + line: (number [1890, 11] - [1890, 13]) + date: (date [1890, 14] - [1890, 24])) + (blame_entry [1891, 4] - [1891, 25] + line: (number [1891, 11] - [1891, 14]) + date: (date [1891, 15] - [1891, 25]))) + (file_entry [1892, 0] - [1899, 25] + file_name: (filename [1892, 6] - [1892, 34]) + (blame_entry [1893, 4] - [1893, 24] + line: (number [1893, 11] - [1893, 13]) + date: (date [1893, 14] - [1893, 24])) + (blame_entry [1894, 4] - [1894, 24] + line: (number [1894, 11] - [1894, 13]) + date: (date [1894, 14] - [1894, 24])) + (blame_entry [1895, 4] - [1895, 24] + line: (number [1895, 11] - [1895, 13]) + date: (date [1895, 14] - [1895, 24])) + (blame_entry [1896, 4] - [1896, 24] + line: (number [1896, 11] - [1896, 13]) + date: (date [1896, 14] - [1896, 24])) + (blame_entry [1897, 4] - [1897, 25] + line: (number [1897, 11] - [1897, 14]) + date: (date [1897, 15] - [1897, 25])) + (blame_entry [1898, 4] - [1898, 25] + line: (number [1898, 11] - [1898, 14]) + date: (date [1898, 15] - [1898, 25])) + (blame_entry [1899, 4] - [1899, 25] + line: (number [1899, 11] - [1899, 14]) + date: (date [1899, 15] - [1899, 25]))) + (file_entry [1900, 0] - [1901, 23] + file_name: (filename [1900, 6] - [1900, 90]) + (blame_entry [1901, 4] - [1901, 23] + line: (number [1901, 11] - [1901, 12]) + date: (date [1901, 13] - [1901, 23]))) + (file_entry [1902, 0] - [1903, 25] + file_name: (filename [1902, 6] - [1902, 67]) + (blame_entry [1903, 4] - [1903, 25] + line: (number [1903, 11] - [1903, 14]) + date: (date [1903, 15] - [1903, 25]))) + (file_entry [1904, 0] - [1906, 26] + file_name: (filename [1904, 6] - [1904, 60]) + (blame_entry [1905, 4] - [1905, 26] + line: (number [1905, 11] - [1905, 15]) + date: (date [1905, 16] - [1905, 26])) + (blame_entry [1906, 4] - [1906, 26] + line: (number [1906, 11] - [1906, 15]) + date: (date [1906, 16] - [1906, 26]))) + (file_entry [1907, 0] - [1911, 25] + file_name: (filename [1907, 6] - [1907, 84]) + (blame_entry [1908, 4] - [1908, 24] + line: (number [1908, 11] - [1908, 13]) + date: (date [1908, 14] - [1908, 24])) + (blame_entry [1909, 4] - [1909, 25] + line: (number [1909, 11] - [1909, 14]) + date: (date [1909, 15] - [1909, 25])) + (blame_entry [1910, 4] - [1910, 25] + line: (number [1910, 11] - [1910, 14]) + date: (date [1910, 15] - [1910, 25])) + (blame_entry [1911, 4] - [1911, 25] + line: (number [1911, 11] - [1911, 14]) + date: (date [1911, 15] - [1911, 25]))) + (file_entry [1912, 0] - [1914, 24] + file_name: (filename [1912, 6] - [1912, 62]) + (blame_entry [1913, 4] - [1913, 24] + line: (number [1913, 11] - [1913, 13]) + date: (date [1913, 14] - [1913, 24])) + (blame_entry [1914, 4] - [1914, 24] + line: (number [1914, 11] - [1914, 13]) + date: (date [1914, 14] - [1914, 24]))) + (file_entry [1915, 0] - [1917, 24] + file_name: (filename [1915, 6] - [1915, 60]) + (blame_entry [1916, 4] - [1916, 23] + line: (number [1916, 11] - [1916, 12]) + date: (date [1916, 13] - [1916, 23])) + (blame_entry [1917, 4] - [1917, 24] + line: (number [1917, 11] - [1917, 13]) + date: (date [1917, 14] - [1917, 24]))) + (file_entry [1918, 0] - [1919, 24] + file_name: (filename [1918, 6] - [1918, 64]) + (blame_entry [1919, 4] - [1919, 24] + line: (number [1919, 11] - [1919, 13]) + date: (date [1919, 14] - [1919, 24]))) + (file_entry [1920, 0] - [1922, 25] + file_name: (filename [1920, 6] - [1920, 53]) + (blame_entry [1921, 4] - [1921, 25] + line: (number [1921, 11] - [1921, 14]) + date: (date [1921, 15] - [1921, 25])) + (blame_entry [1922, 4] - [1922, 25] + line: (number [1922, 11] - [1922, 14]) + date: (date [1922, 15] - [1922, 25]))) + (file_entry [1923, 0] - [1924, 24] + file_name: (filename [1923, 6] - [1923, 76]) + (blame_entry [1924, 4] - [1924, 24] + line: (number [1924, 11] - [1924, 13]) + date: (date [1924, 14] - [1924, 24]))) + (file_entry [1925, 0] - [1926, 24] + file_name: (filename [1925, 6] - [1925, 78]) + (blame_entry [1926, 4] - [1926, 24] + line: (number [1926, 11] - [1926, 13]) + date: (date [1926, 14] - [1926, 24]))) + (file_entry [1927, 0] - [1944, 25] + file_name: (filename [1927, 6] - [1927, 63]) + (blame_entry [1928, 4] - [1928, 23] + line: (number [1928, 11] - [1928, 12]) + date: (date [1928, 13] - [1928, 23])) + (blame_entry [1929, 4] - [1929, 24] + line: (number [1929, 11] - [1929, 13]) + date: (date [1929, 14] - [1929, 24])) + (blame_entry [1930, 4] - [1930, 24] + line: (number [1930, 11] - [1930, 13]) + date: (date [1930, 14] - [1930, 24])) + (blame_entry [1931, 4] - [1931, 24] + line: (number [1931, 11] - [1931, 13]) + date: (date [1931, 14] - [1931, 24])) + (blame_entry [1932, 4] - [1932, 24] + line: (number [1932, 11] - [1932, 13]) + date: (date [1932, 14] - [1932, 24])) + (blame_entry [1933, 4] - [1933, 24] + line: (number [1933, 11] - [1933, 13]) + date: (date [1933, 14] - [1933, 24])) + (blame_entry [1934, 4] - [1934, 25] + line: (number [1934, 11] - [1934, 14]) + date: (date [1934, 15] - [1934, 25])) + (blame_entry [1935, 4] - [1935, 25] + line: (number [1935, 11] - [1935, 14]) + date: (date [1935, 15] - [1935, 25])) + (blame_entry [1936, 4] - [1936, 25] + line: (number [1936, 11] - [1936, 14]) + date: (date [1936, 15] - [1936, 25])) + (blame_entry [1937, 4] - [1937, 25] + line: (number [1937, 11] - [1937, 14]) + date: (date [1937, 15] - [1937, 25])) + (blame_entry [1938, 4] - [1938, 25] + line: (number [1938, 11] - [1938, 14]) + date: (date [1938, 15] - [1938, 25])) + (blame_entry [1939, 4] - [1939, 25] + line: (number [1939, 11] - [1939, 14]) + date: (date [1939, 15] - [1939, 25])) + (blame_entry [1940, 4] - [1940, 25] + line: (number [1940, 11] - [1940, 14]) + date: (date [1940, 15] - [1940, 25])) + (blame_entry [1941, 4] - [1941, 25] + line: (number [1941, 11] - [1941, 14]) + date: (date [1941, 15] - [1941, 25])) + (blame_entry [1942, 4] - [1942, 25] + line: (number [1942, 11] - [1942, 14]) + date: (date [1942, 15] - [1942, 25])) + (blame_entry [1943, 4] - [1943, 25] + line: (number [1943, 11] - [1943, 14]) + date: (date [1943, 15] - [1943, 25])) + (blame_entry [1944, 4] - [1944, 25] + line: (number [1944, 11] - [1944, 14]) + date: (date [1944, 15] - [1944, 25]))) + (file_entry [1945, 0] - [1949, 24] + file_name: (filename [1945, 6] - [1945, 55]) + (blame_entry [1946, 4] - [1946, 24] + line: (number [1946, 11] - [1946, 13]) + date: (date [1946, 14] - [1946, 24])) + (blame_entry [1947, 4] - [1947, 24] + line: (number [1947, 11] - [1947, 13]) + date: (date [1947, 14] - [1947, 24])) + (blame_entry [1948, 4] - [1948, 24] + line: (number [1948, 11] - [1948, 13]) + date: (date [1948, 14] - [1948, 24])) + (blame_entry [1949, 4] - [1949, 24] + line: (number [1949, 11] - [1949, 13]) + date: (date [1949, 14] - [1949, 24]))) + (file_entry [1950, 0] - [1953, 24] + file_name: (filename [1950, 6] - [1950, 67]) + (blame_entry [1951, 4] - [1951, 23] + line: (number [1951, 11] - [1951, 12]) + date: (date [1951, 13] - [1951, 23])) + (blame_entry [1952, 4] - [1952, 24] + line: (number [1952, 11] - [1952, 13]) + date: (date [1952, 14] - [1952, 24])) + (blame_entry [1953, 4] - [1953, 24] + line: (number [1953, 11] - [1953, 13]) + date: (date [1953, 14] - [1953, 24]))) + (file_entry [1954, 0] - [1965, 25] + file_name: (filename [1954, 6] - [1954, 49]) + (blame_entry [1955, 4] - [1955, 24] + line: (number [1955, 11] - [1955, 13]) + date: (date [1955, 14] - [1955, 24])) + (blame_entry [1956, 4] - [1956, 24] + line: (number [1956, 11] - [1956, 13]) + date: (date [1956, 14] - [1956, 24])) + (blame_entry [1957, 4] - [1957, 24] + line: (number [1957, 11] - [1957, 13]) + date: (date [1957, 14] - [1957, 24])) + (blame_entry [1958, 4] - [1958, 24] + line: (number [1958, 11] - [1958, 13]) + date: (date [1958, 14] - [1958, 24])) + (blame_entry [1959, 4] - [1959, 24] + line: (number [1959, 11] - [1959, 13]) + date: (date [1959, 14] - [1959, 24])) + (blame_entry [1960, 4] - [1960, 24] + line: (number [1960, 11] - [1960, 13]) + date: (date [1960, 14] - [1960, 24])) + (blame_entry [1961, 4] - [1961, 24] + line: (number [1961, 11] - [1961, 13]) + date: (date [1961, 14] - [1961, 24])) + (blame_entry [1962, 4] - [1962, 25] + line: (number [1962, 11] - [1962, 14]) + date: (date [1962, 15] - [1962, 25])) + (blame_entry [1963, 4] - [1963, 25] + line: (number [1963, 11] - [1963, 14]) + date: (date [1963, 15] - [1963, 25])) + (blame_entry [1964, 4] - [1964, 25] + line: (number [1964, 11] - [1964, 14]) + date: (date [1964, 15] - [1964, 25])) + (blame_entry [1965, 4] - [1965, 25] + line: (number [1965, 11] - [1965, 14]) + date: (date [1965, 15] - [1965, 25]))) + (file_entry [1966, 0] - [1970, 24] + file_name: (filename [1966, 6] - [1966, 60]) + (blame_entry [1967, 4] - [1967, 24] + line: (number [1967, 11] - [1967, 13]) + date: (date [1967, 14] - [1967, 24])) + (blame_entry [1968, 4] - [1968, 24] + line: (number [1968, 11] - [1968, 13]) + date: (date [1968, 14] - [1968, 24])) + (blame_entry [1969, 4] - [1969, 24] + line: (number [1969, 11] - [1969, 13]) + date: (date [1969, 14] - [1969, 24])) + (blame_entry [1970, 4] - [1970, 24] + line: (number [1970, 11] - [1970, 13]) + date: (date [1970, 14] - [1970, 24]))) + (file_entry [1971, 0] - [1974, 24] + file_name: (filename [1971, 6] - [1971, 72]) + (blame_entry [1972, 4] - [1972, 24] + line: (number [1972, 11] - [1972, 13]) + date: (date [1972, 14] - [1972, 24])) + (blame_entry [1973, 4] - [1973, 24] + line: (number [1973, 11] - [1973, 13]) + date: (date [1973, 14] - [1973, 24])) + (blame_entry [1974, 4] - [1974, 24] + line: (number [1974, 11] - [1974, 13]) + date: (date [1974, 14] - [1974, 24]))) + (file_entry [1975, 0] - [1976, 25] + file_name: (filename [1975, 6] - [1975, 64]) + (blame_entry [1976, 4] - [1976, 25] + line: (number [1976, 11] - [1976, 14]) + date: (date [1976, 15] - [1976, 25]))) + (file_entry [1977, 0] - [1981, 25] + file_name: (filename [1977, 6] - [1977, 84]) + (blame_entry [1978, 4] - [1978, 24] + line: (number [1978, 11] - [1978, 13]) + date: (date [1978, 14] - [1978, 24])) + (blame_entry [1979, 4] - [1979, 25] + line: (number [1979, 11] - [1979, 14]) + date: (date [1979, 15] - [1979, 25])) + (blame_entry [1980, 4] - [1980, 25] + line: (number [1980, 11] - [1980, 14]) + date: (date [1980, 15] - [1980, 25])) + (blame_entry [1981, 4] - [1981, 25] + line: (number [1981, 11] - [1981, 14]) + date: (date [1981, 15] - [1981, 25]))) + (file_entry [1982, 0] - [1991, 26] + file_name: (filename [1982, 6] - [1982, 42]) + (blame_entry [1983, 4] - [1983, 25] + line: (number [1983, 11] - [1983, 14]) + date: (date [1983, 15] - [1983, 25])) + (blame_entry [1984, 4] - [1984, 25] + line: (number [1984, 11] - [1984, 14]) + date: (date [1984, 15] - [1984, 25])) + (blame_entry [1985, 4] - [1985, 25] + line: (number [1985, 11] - [1985, 14]) + date: (date [1985, 15] - [1985, 25])) + (blame_entry [1986, 4] - [1986, 25] + line: (number [1986, 11] - [1986, 14]) + date: (date [1986, 15] - [1986, 25])) + (blame_entry [1987, 4] - [1987, 25] + line: (number [1987, 11] - [1987, 14]) + date: (date [1987, 15] - [1987, 25])) + (blame_entry [1988, 4] - [1988, 25] + line: (number [1988, 11] - [1988, 14]) + date: (date [1988, 15] - [1988, 25])) + (blame_entry [1989, 4] - [1989, 25] + line: (number [1989, 11] - [1989, 14]) + date: (date [1989, 15] - [1989, 25])) + (blame_entry [1990, 4] - [1990, 26] + line: (number [1990, 11] - [1990, 15]) + date: (date [1990, 16] - [1990, 26])) + (blame_entry [1991, 4] - [1991, 26] + line: (number [1991, 11] - [1991, 15]) + date: (date [1991, 16] - [1991, 26]))) + (file_entry [1992, 0] - [1993, 24] + file_name: (filename [1992, 6] - [1992, 80]) + (blame_entry [1993, 4] - [1993, 24] + line: (number [1993, 11] - [1993, 13]) + date: (date [1993, 14] - [1993, 24]))) + (file_entry [1994, 0] - [1996, 25] + file_name: (filename [1994, 6] - [1994, 49]) + (blame_entry [1995, 4] - [1995, 25] + line: (number [1995, 11] - [1995, 14]) + date: (date [1995, 15] - [1995, 25])) + (blame_entry [1996, 4] - [1996, 25] + line: (number [1996, 11] - [1996, 14]) + date: (date [1996, 15] - [1996, 25]))) + (file_entry [1997, 0] - [1999, 24] + file_name: (filename [1997, 6] - [1997, 77]) + (blame_entry [1998, 4] - [1998, 24] + line: (number [1998, 11] - [1998, 13]) + date: (date [1998, 14] - [1998, 24])) + (blame_entry [1999, 4] - [1999, 24] + line: (number [1999, 11] - [1999, 13]) + date: (date [1999, 14] - [1999, 24]))) + (file_entry [2000, 0] - [2007, 24] + file_name: (filename [2000, 6] - [2000, 55]) + (blame_entry [2001, 4] - [2001, 23] + line: (number [2001, 11] - [2001, 12]) + date: (date [2001, 13] - [2001, 23])) + (blame_entry [2002, 4] - [2002, 23] + line: (number [2002, 11] - [2002, 12]) + date: (date [2002, 13] - [2002, 23])) + (blame_entry [2003, 4] - [2003, 24] + line: (number [2003, 11] - [2003, 13]) + date: (date [2003, 14] - [2003, 24])) + (blame_entry [2004, 4] - [2004, 24] + line: (number [2004, 11] - [2004, 13]) + date: (date [2004, 14] - [2004, 24])) + (blame_entry [2005, 4] - [2005, 24] + line: (number [2005, 11] - [2005, 13]) + date: (date [2005, 14] - [2005, 24])) + (blame_entry [2006, 4] - [2006, 24] + line: (number [2006, 11] - [2006, 13]) + date: (date [2006, 14] - [2006, 24])) + (blame_entry [2007, 4] - [2007, 24] + line: (number [2007, 11] - [2007, 13]) + date: (date [2007, 14] - [2007, 24]))) + (file_entry [2008, 0] - [2010, 25] + file_name: (filename [2008, 6] - [2008, 59]) + (blame_entry [2009, 4] - [2009, 24] + line: (number [2009, 11] - [2009, 13]) + date: (date [2009, 14] - [2009, 24])) + (blame_entry [2010, 4] - [2010, 25] + line: (number [2010, 11] - [2010, 14]) + date: (date [2010, 15] - [2010, 25]))) + (file_entry [2011, 0] - [2014, 25] + file_name: (filename [2011, 6] - [2011, 61]) + (blame_entry [2012, 4] - [2012, 24] + line: (number [2012, 11] - [2012, 13]) + date: (date [2012, 14] - [2012, 24])) + (blame_entry [2013, 4] - [2013, 25] + line: (number [2013, 11] - [2013, 14]) + date: (date [2013, 15] - [2013, 25])) + (blame_entry [2014, 4] - [2014, 25] + line: (number [2014, 11] - [2014, 14]) + date: (date [2014, 15] - [2014, 25]))) + (file_entry [2015, 0] - [2016, 24] + file_name: (filename [2015, 6] - [2015, 77]) + (blame_entry [2016, 4] - [2016, 24] + line: (number [2016, 11] - [2016, 13]) + date: (date [2016, 14] - [2016, 24]))) + (file_entry [2017, 0] - [2018, 23] + file_name: (filename [2017, 6] - [2017, 52]) + (blame_entry [2018, 4] - [2018, 23] + line: (number [2018, 11] - [2018, 12]) + date: (date [2018, 13] - [2018, 23]))) + (file_entry [2019, 0] - [2025, 25] + file_name: (filename [2019, 6] - [2019, 35]) + (blame_entry [2020, 4] - [2020, 25] + line: (number [2020, 11] - [2020, 14]) + date: (date [2020, 15] - [2020, 25])) + (blame_entry [2021, 4] - [2021, 25] + line: (number [2021, 11] - [2021, 14]) + date: (date [2021, 15] - [2021, 25])) + (blame_entry [2022, 4] - [2022, 25] + line: (number [2022, 11] - [2022, 14]) + date: (date [2022, 15] - [2022, 25])) + (blame_entry [2023, 4] - [2023, 25] + line: (number [2023, 11] - [2023, 14]) + date: (date [2023, 15] - [2023, 25])) + (blame_entry [2024, 4] - [2024, 25] + line: (number [2024, 11] - [2024, 14]) + date: (date [2024, 15] - [2024, 25])) + (blame_entry [2025, 4] - [2025, 25] + line: (number [2025, 11] - [2025, 14]) + date: (date [2025, 15] - [2025, 25]))) + (file_entry [2026, 0] - [2034, 25] + file_name: (filename [2026, 6] - [2026, 56]) + (blame_entry [2027, 4] - [2027, 23] + line: (number [2027, 11] - [2027, 12]) + date: (date [2027, 13] - [2027, 23])) + (blame_entry [2028, 4] - [2028, 24] + line: (number [2028, 11] - [2028, 13]) + date: (date [2028, 14] - [2028, 24])) + (blame_entry [2029, 4] - [2029, 24] + line: (number [2029, 11] - [2029, 13]) + date: (date [2029, 14] - [2029, 24])) + (blame_entry [2030, 4] - [2030, 24] + line: (number [2030, 11] - [2030, 13]) + date: (date [2030, 14] - [2030, 24])) + (blame_entry [2031, 4] - [2031, 24] + line: (number [2031, 11] - [2031, 13]) + date: (date [2031, 14] - [2031, 24])) + (blame_entry [2032, 4] - [2032, 24] + line: (number [2032, 11] - [2032, 13]) + date: (date [2032, 14] - [2032, 24])) + (blame_entry [2033, 4] - [2033, 24] + line: (number [2033, 11] - [2033, 13]) + date: (date [2033, 14] - [2033, 24])) + (blame_entry [2034, 4] - [2034, 25] + line: (number [2034, 11] - [2034, 14]) + date: (date [2034, 15] - [2034, 25]))) + (file_entry [2035, 0] - [2037, 24] + file_name: (filename [2035, 6] - [2035, 61]) + (blame_entry [2036, 4] - [2036, 24] + line: (number [2036, 11] - [2036, 13]) + date: (date [2036, 14] - [2036, 24])) + (blame_entry [2037, 4] - [2037, 24] + line: (number [2037, 11] - [2037, 13]) + date: (date [2037, 14] - [2037, 24]))) + (file_entry [2038, 0] - [2040, 24] + file_name: (filename [2038, 6] - [2038, 85]) + (blame_entry [2039, 4] - [2039, 24] + line: (number [2039, 11] - [2039, 13]) + date: (date [2039, 14] - [2039, 24])) + (blame_entry [2040, 4] - [2040, 24] + line: (number [2040, 11] - [2040, 13]) + date: (date [2040, 14] - [2040, 24]))) + (file_entry [2041, 0] - [2043, 24] + file_name: (filename [2041, 6] - [2041, 58]) + (blame_entry [2042, 4] - [2042, 24] + line: (number [2042, 11] - [2042, 13]) + date: (date [2042, 14] - [2042, 24])) + (blame_entry [2043, 4] - [2043, 24] + line: (number [2043, 11] - [2043, 13]) + date: (date [2043, 14] - [2043, 24]))) + (file_entry [2044, 0] - [2045, 24] + file_name: (filename [2044, 6] - [2044, 60]) + (blame_entry [2045, 4] - [2045, 24] + line: (number [2045, 11] - [2045, 13]) + date: (date [2045, 14] - [2045, 24]))) + (file_entry [2046, 0] - [2054, 25] + file_name: (filename [2046, 6] - [2046, 76]) + (blame_entry [2047, 4] - [2047, 24] + line: (number [2047, 11] - [2047, 13]) + date: (date [2047, 14] - [2047, 24])) + (blame_entry [2048, 4] - [2048, 24] + line: (number [2048, 11] - [2048, 13]) + date: (date [2048, 14] - [2048, 24])) + (blame_entry [2049, 4] - [2049, 24] + line: (number [2049, 11] - [2049, 13]) + date: (date [2049, 14] - [2049, 24])) + (blame_entry [2050, 4] - [2050, 24] + line: (number [2050, 11] - [2050, 13]) + date: (date [2050, 14] - [2050, 24])) + (blame_entry [2051, 4] - [2051, 24] + line: (number [2051, 11] - [2051, 13]) + date: (date [2051, 14] - [2051, 24])) + (blame_entry [2052, 4] - [2052, 24] + line: (number [2052, 11] - [2052, 13]) + date: (date [2052, 14] - [2052, 24])) + (blame_entry [2053, 4] - [2053, 25] + line: (number [2053, 11] - [2053, 14]) + date: (date [2053, 15] - [2053, 25])) + (blame_entry [2054, 4] - [2054, 25] + line: (number [2054, 11] - [2054, 14]) + date: (date [2054, 15] - [2054, 25]))) + (file_entry [2055, 0] - [2058, 24] + file_name: (filename [2055, 6] - [2055, 57]) + (blame_entry [2056, 4] - [2056, 24] + line: (number [2056, 11] - [2056, 13]) + date: (date [2056, 14] - [2056, 24])) + (blame_entry [2057, 4] - [2057, 24] + line: (number [2057, 11] - [2057, 13]) + date: (date [2057, 14] - [2057, 24])) + (blame_entry [2058, 4] - [2058, 24] + line: (number [2058, 11] - [2058, 13]) + date: (date [2058, 14] - [2058, 24]))) + (file_entry [2059, 0] - [2064, 24] + file_name: (filename [2059, 6] - [2059, 57]) + (blame_entry [2060, 4] - [2060, 24] + line: (number [2060, 11] - [2060, 13]) + date: (date [2060, 14] - [2060, 24])) + (blame_entry [2061, 4] - [2061, 24] + line: (number [2061, 11] - [2061, 13]) + date: (date [2061, 14] - [2061, 24])) + (blame_entry [2062, 4] - [2062, 24] + line: (number [2062, 11] - [2062, 13]) + date: (date [2062, 14] - [2062, 24])) + (blame_entry [2063, 4] - [2063, 24] + line: (number [2063, 11] - [2063, 13]) + date: (date [2063, 14] - [2063, 24])) + (blame_entry [2064, 4] - [2064, 24] + line: (number [2064, 11] - [2064, 13]) + date: (date [2064, 14] - [2064, 24]))) + (file_entry [2065, 0] - [2067, 25] + file_name: (filename [2065, 6] - [2065, 76]) + (blame_entry [2066, 4] - [2066, 24] + line: (number [2066, 11] - [2066, 13]) + date: (date [2066, 14] - [2066, 24])) + (blame_entry [2067, 4] - [2067, 25] + line: (number [2067, 11] - [2067, 14]) + date: (date [2067, 15] - [2067, 25]))) + (file_entry [2068, 0] - [2072, 25] + file_name: (filename [2068, 6] - [2068, 73]) + (blame_entry [2069, 4] - [2069, 24] + line: (number [2069, 11] - [2069, 13]) + date: (date [2069, 14] - [2069, 24])) + (blame_entry [2070, 4] - [2070, 25] + line: (number [2070, 11] - [2070, 14]) + date: (date [2070, 15] - [2070, 25])) + (blame_entry [2071, 4] - [2071, 25] + line: (number [2071, 11] - [2071, 14]) + date: (date [2071, 15] - [2071, 25])) + (blame_entry [2072, 4] - [2072, 25] + line: (number [2072, 11] - [2072, 14]) + date: (date [2072, 15] - [2072, 25]))) + (file_entry [2073, 0] - [2077, 25] + file_name: (filename [2073, 6] - [2073, 68]) + (blame_entry [2074, 4] - [2074, 24] + line: (number [2074, 11] - [2074, 13]) + date: (date [2074, 14] - [2074, 24])) + (blame_entry [2075, 4] - [2075, 25] + line: (number [2075, 11] - [2075, 14]) + date: (date [2075, 15] - [2075, 25])) + (blame_entry [2076, 4] - [2076, 25] + line: (number [2076, 11] - [2076, 14]) + date: (date [2076, 15] - [2076, 25])) + (blame_entry [2077, 4] - [2077, 25] + line: (number [2077, 11] - [2077, 14]) + date: (date [2077, 15] - [2077, 25]))) + (file_entry [2078, 0] - [2090, 26] + file_name: (filename [2078, 6] - [2078, 55]) + (blame_entry [2079, 4] - [2079, 25] + line: (number [2079, 11] - [2079, 14]) + date: (date [2079, 15] - [2079, 25])) + (blame_entry [2080, 4] - [2080, 25] + line: (number [2080, 11] - [2080, 14]) + date: (date [2080, 15] - [2080, 25])) + (blame_entry [2081, 4] - [2081, 25] + line: (number [2081, 11] - [2081, 14]) + date: (date [2081, 15] - [2081, 25])) + (blame_entry [2082, 4] - [2082, 25] + line: (number [2082, 11] - [2082, 14]) + date: (date [2082, 15] - [2082, 25])) + (blame_entry [2083, 4] - [2083, 25] + line: (number [2083, 11] - [2083, 14]) + date: (date [2083, 15] - [2083, 25])) + (blame_entry [2084, 4] - [2084, 26] + line: (number [2084, 11] - [2084, 15]) + date: (date [2084, 16] - [2084, 26])) + (blame_entry [2085, 4] - [2085, 26] + line: (number [2085, 11] - [2085, 15]) + date: (date [2085, 16] - [2085, 26])) + (blame_entry [2086, 4] - [2086, 26] + line: (number [2086, 11] - [2086, 15]) + date: (date [2086, 16] - [2086, 26])) + (blame_entry [2087, 4] - [2087, 26] + line: (number [2087, 11] - [2087, 15]) + date: (date [2087, 16] - [2087, 26])) + (blame_entry [2088, 4] - [2088, 26] + line: (number [2088, 11] - [2088, 15]) + date: (date [2088, 16] - [2088, 26])) + (blame_entry [2089, 4] - [2089, 26] + line: (number [2089, 11] - [2089, 15]) + date: (date [2089, 16] - [2089, 26])) + (blame_entry [2090, 4] - [2090, 26] + line: (number [2090, 11] - [2090, 15]) + date: (date [2090, 16] - [2090, 26]))) + (file_entry [2091, 0] - [2092, 24] + file_name: (filename [2091, 6] - [2091, 46]) + (blame_entry [2092, 4] - [2092, 24] + line: (number [2092, 11] - [2092, 13]) + date: (date [2092, 14] - [2092, 24]))) + (file_entry [2093, 0] - [2097, 25] + file_name: (filename [2093, 6] - [2093, 93]) + (blame_entry [2094, 4] - [2094, 25] + line: (number [2094, 11] - [2094, 14]) + date: (date [2094, 15] - [2094, 25])) + (blame_entry [2095, 4] - [2095, 25] + line: (number [2095, 11] - [2095, 14]) + date: (date [2095, 15] - [2095, 25])) + (blame_entry [2096, 4] - [2096, 25] + line: (number [2096, 11] - [2096, 14]) + date: (date [2096, 15] - [2096, 25])) + (blame_entry [2097, 4] - [2097, 25] + line: (number [2097, 11] - [2097, 14]) + date: (date [2097, 15] - [2097, 25]))) + (file_entry [2098, 0] - [2100, 24] + file_name: (filename [2098, 6] - [2098, 69]) + (blame_entry [2099, 4] - [2099, 23] + line: (number [2099, 11] - [2099, 12]) + date: (date [2099, 13] - [2099, 23])) + (blame_entry [2100, 4] - [2100, 24] + line: (number [2100, 11] - [2100, 13]) + date: (date [2100, 14] - [2100, 24]))) + (file_entry [2101, 0] - [2102, 24] + file_name: (filename [2101, 6] - [2101, 47]) + (blame_entry [2102, 4] - [2102, 24] + line: (number [2102, 11] - [2102, 13]) + date: (date [2102, 14] - [2102, 24]))) + (file_entry [2103, 0] - [2104, 25] + file_name: (filename [2103, 6] - [2103, 66]) + (blame_entry [2104, 4] - [2104, 25] + line: (number [2104, 11] - [2104, 14]) + date: (date [2104, 15] - [2104, 25]))) + (file_entry [2105, 0] - [2106, 23] + file_name: (filename [2105, 6] - [2105, 64]) + (blame_entry [2106, 4] - [2106, 23] + line: (number [2106, 11] - [2106, 12]) + date: (date [2106, 13] - [2106, 23]))) + (file_entry [2107, 0] - [2108, 23] + file_name: (filename [2107, 6] - [2107, 75]) + (blame_entry [2108, 4] - [2108, 23] + line: (number [2108, 11] - [2108, 12]) + date: (date [2108, 13] - [2108, 23]))) + (file_entry [2109, 0] - [2110, 25] + file_name: (filename [2109, 6] - [2109, 60]) + (blame_entry [2110, 4] - [2110, 25] + line: (number [2110, 11] - [2110, 14]) + date: (date [2110, 15] - [2110, 25]))) + (file_entry [2111, 0] - [2115, 25] + file_name: (filename [2111, 6] - [2111, 88]) + (blame_entry [2112, 4] - [2112, 24] + line: (number [2112, 11] - [2112, 13]) + date: (date [2112, 14] - [2112, 24])) + (blame_entry [2113, 4] - [2113, 25] + line: (number [2113, 11] - [2113, 14]) + date: (date [2113, 15] - [2113, 25])) + (blame_entry [2114, 4] - [2114, 25] + line: (number [2114, 11] - [2114, 14]) + date: (date [2114, 15] - [2114, 25])) + (blame_entry [2115, 4] - [2115, 25] + line: (number [2115, 11] - [2115, 14]) + date: (date [2115, 15] - [2115, 25]))) + (file_entry [2116, 0] - [2121, 24] + file_name: (filename [2116, 6] - [2116, 69]) + (blame_entry [2117, 4] - [2117, 24] + line: (number [2117, 11] - [2117, 13]) + date: (date [2117, 14] - [2117, 24])) + (blame_entry [2118, 4] - [2118, 24] + line: (number [2118, 11] - [2118, 13]) + date: (date [2118, 14] - [2118, 24])) + (blame_entry [2119, 4] - [2119, 24] + line: (number [2119, 11] - [2119, 13]) + date: (date [2119, 14] - [2119, 24])) + (blame_entry [2120, 4] - [2120, 24] + line: (number [2120, 11] - [2120, 13]) + date: (date [2120, 14] - [2120, 24])) + (blame_entry [2121, 4] - [2121, 24] + line: (number [2121, 11] - [2121, 13]) + date: (date [2121, 14] - [2121, 24]))) + (file_entry [2122, 0] - [2126, 25] + file_name: (filename [2122, 6] - [2122, 65]) + (blame_entry [2123, 4] - [2123, 24] + line: (number [2123, 11] - [2123, 13]) + date: (date [2123, 14] - [2123, 24])) + (blame_entry [2124, 4] - [2124, 25] + line: (number [2124, 11] - [2124, 14]) + date: (date [2124, 15] - [2124, 25])) + (blame_entry [2125, 4] - [2125, 25] + line: (number [2125, 11] - [2125, 14]) + date: (date [2125, 15] - [2125, 25])) + (blame_entry [2126, 4] - [2126, 25] + line: (number [2126, 11] - [2126, 14]) + date: (date [2126, 15] - [2126, 25]))) + (file_entry [2127, 0] - [2131, 25] + file_name: (filename [2127, 6] - [2127, 74]) + (blame_entry [2128, 4] - [2128, 24] + line: (number [2128, 11] - [2128, 13]) + date: (date [2128, 14] - [2128, 24])) + (blame_entry [2129, 4] - [2129, 25] + line: (number [2129, 11] - [2129, 14]) + date: (date [2129, 15] - [2129, 25])) + (blame_entry [2130, 4] - [2130, 25] + line: (number [2130, 11] - [2130, 14]) + date: (date [2130, 15] - [2130, 25])) + (blame_entry [2131, 4] - [2131, 25] + line: (number [2131, 11] - [2131, 14]) + date: (date [2131, 15] - [2131, 25]))) + (file_entry [2132, 0] - [2155, 25] + file_name: (filename [2132, 6] - [2132, 51]) + (blame_entry [2133, 4] - [2133, 24] + line: (number [2133, 11] - [2133, 13]) + date: (date [2133, 14] - [2133, 24])) + (blame_entry [2134, 4] - [2134, 24] + line: (number [2134, 11] - [2134, 13]) + date: (date [2134, 14] - [2134, 24])) + (blame_entry [2135, 4] - [2135, 24] + line: (number [2135, 11] - [2135, 13]) + date: (date [2135, 14] - [2135, 24])) + (blame_entry [2136, 4] - [2136, 24] + line: (number [2136, 11] - [2136, 13]) + date: (date [2136, 14] - [2136, 24])) + (blame_entry [2137, 4] - [2137, 24] + line: (number [2137, 11] - [2137, 13]) + date: (date [2137, 14] - [2137, 24])) + (blame_entry [2138, 4] - [2138, 24] + line: (number [2138, 11] - [2138, 13]) + date: (date [2138, 14] - [2138, 24])) + (blame_entry [2139, 4] - [2139, 24] + line: (number [2139, 11] - [2139, 13]) + date: (date [2139, 14] - [2139, 24])) + (blame_entry [2140, 4] - [2140, 24] + line: (number [2140, 11] - [2140, 13]) + date: (date [2140, 14] - [2140, 24])) + (blame_entry [2141, 4] - [2141, 25] + line: (number [2141, 11] - [2141, 14]) + date: (date [2141, 15] - [2141, 25])) + (blame_entry [2142, 4] - [2142, 25] + line: (number [2142, 11] - [2142, 14]) + date: (date [2142, 15] - [2142, 25])) + (blame_entry [2143, 4] - [2143, 25] + line: (number [2143, 11] - [2143, 14]) + date: (date [2143, 15] - [2143, 25])) + (blame_entry [2144, 4] - [2144, 25] + line: (number [2144, 11] - [2144, 14]) + date: (date [2144, 15] - [2144, 25])) + (blame_entry [2145, 4] - [2145, 25] + line: (number [2145, 11] - [2145, 14]) + date: (date [2145, 15] - [2145, 25])) + (blame_entry [2146, 4] - [2146, 25] + line: (number [2146, 11] - [2146, 14]) + date: (date [2146, 15] - [2146, 25])) + (blame_entry [2147, 4] - [2147, 25] + line: (number [2147, 11] - [2147, 14]) + date: (date [2147, 15] - [2147, 25])) + (blame_entry [2148, 4] - [2148, 25] + line: (number [2148, 11] - [2148, 14]) + date: (date [2148, 15] - [2148, 25])) + (blame_entry [2149, 4] - [2149, 25] + line: (number [2149, 11] - [2149, 14]) + date: (date [2149, 15] - [2149, 25])) + (blame_entry [2150, 4] - [2150, 25] + line: (number [2150, 11] - [2150, 14]) + date: (date [2150, 15] - [2150, 25])) + (blame_entry [2151, 4] - [2151, 25] + line: (number [2151, 11] - [2151, 14]) + date: (date [2151, 15] - [2151, 25])) + (blame_entry [2152, 4] - [2152, 25] + line: (number [2152, 11] - [2152, 14]) + date: (date [2152, 15] - [2152, 25])) + (blame_entry [2153, 4] - [2153, 25] + line: (number [2153, 11] - [2153, 14]) + date: (date [2153, 15] - [2153, 25])) + (blame_entry [2154, 4] - [2154, 25] + line: (number [2154, 11] - [2154, 14]) + date: (date [2154, 15] - [2154, 25])) + (blame_entry [2155, 4] - [2155, 25] + line: (number [2155, 11] - [2155, 14]) + date: (date [2155, 15] - [2155, 25]))) + (file_entry [2156, 0] - [2157, 23] + file_name: (filename [2156, 6] - [2156, 70]) + (blame_entry [2157, 4] - [2157, 23] + line: (number [2157, 11] - [2157, 12]) + date: (date [2157, 13] - [2157, 23]))) + (file_entry [2158, 0] - [2159, 24] + file_name: (filename [2158, 6] - [2158, 54]) + (blame_entry [2159, 4] - [2159, 24] + line: (number [2159, 11] - [2159, 13]) + date: (date [2159, 14] - [2159, 24]))) + (file_entry [2160, 0] - [2178, 25] + file_name: (filename [2160, 6] - [2160, 50]) + (blame_entry [2161, 4] - [2161, 24] + line: (number [2161, 11] - [2161, 13]) + date: (date [2161, 14] - [2161, 24])) + (blame_entry [2162, 4] - [2162, 25] + line: (number [2162, 11] - [2162, 14]) + date: (date [2162, 15] - [2162, 25])) + (blame_entry [2163, 4] - [2163, 25] + line: (number [2163, 11] - [2163, 14]) + date: (date [2163, 15] - [2163, 25])) + (blame_entry [2164, 4] - [2164, 25] + line: (number [2164, 11] - [2164, 14]) + date: (date [2164, 15] - [2164, 25])) + (blame_entry [2165, 4] - [2165, 25] + line: (number [2165, 11] - [2165, 14]) + date: (date [2165, 15] - [2165, 25])) + (blame_entry [2166, 4] - [2166, 25] + line: (number [2166, 11] - [2166, 14]) + date: (date [2166, 15] - [2166, 25])) + (blame_entry [2167, 4] - [2167, 25] + line: (number [2167, 11] - [2167, 14]) + date: (date [2167, 15] - [2167, 25])) + (blame_entry [2168, 4] - [2168, 25] + line: (number [2168, 11] - [2168, 14]) + date: (date [2168, 15] - [2168, 25])) + (blame_entry [2169, 4] - [2169, 25] + line: (number [2169, 11] - [2169, 14]) + date: (date [2169, 15] - [2169, 25])) + (blame_entry [2170, 4] - [2170, 25] + line: (number [2170, 11] - [2170, 14]) + date: (date [2170, 15] - [2170, 25])) + (blame_entry [2171, 4] - [2171, 25] + line: (number [2171, 11] - [2171, 14]) + date: (date [2171, 15] - [2171, 25])) + (blame_entry [2172, 4] - [2172, 25] + line: (number [2172, 11] - [2172, 14]) + date: (date [2172, 15] - [2172, 25])) + (blame_entry [2173, 4] - [2173, 25] + line: (number [2173, 11] - [2173, 14]) + date: (date [2173, 15] - [2173, 25])) + (blame_entry [2174, 4] - [2174, 25] + line: (number [2174, 11] - [2174, 14]) + date: (date [2174, 15] - [2174, 25])) + (blame_entry [2175, 4] - [2175, 25] + line: (number [2175, 11] - [2175, 14]) + date: (date [2175, 15] - [2175, 25])) + (blame_entry [2176, 4] - [2176, 25] + line: (number [2176, 11] - [2176, 14]) + date: (date [2176, 15] - [2176, 25])) + (blame_entry [2177, 4] - [2177, 25] + line: (number [2177, 11] - [2177, 14]) + date: (date [2177, 15] - [2177, 25])) + (blame_entry [2178, 4] - [2178, 25] + line: (number [2178, 11] - [2178, 14]) + date: (date [2178, 15] - [2178, 25]))) + (file_entry [2179, 0] - [2181, 24] + file_name: (filename [2179, 6] - [2179, 55]) + (blame_entry [2180, 4] - [2180, 24] + line: (number [2180, 11] - [2180, 13]) + date: (date [2180, 14] - [2180, 24])) + (blame_entry [2181, 4] - [2181, 24] + line: (number [2181, 11] - [2181, 13]) + date: (date [2181, 14] - [2181, 24]))) + (file_entry [2182, 0] - [2183, 23] + file_name: (filename [2182, 6] - [2182, 90]) + (blame_entry [2183, 4] - [2183, 23] + line: (number [2183, 11] - [2183, 12]) + date: (date [2183, 13] - [2183, 23]))) + (file_entry [2184, 0] - [2185, 23] + file_name: (filename [2184, 6] - [2184, 78]) + (blame_entry [2185, 4] - [2185, 23] + line: (number [2185, 11] - [2185, 12]) + date: (date [2185, 13] - [2185, 23]))) + (file_entry [2186, 0] - [2190, 25] + file_name: (filename [2186, 6] - [2186, 87]) + (blame_entry [2187, 4] - [2187, 25] + line: (number [2187, 11] - [2187, 14]) + date: (date [2187, 15] - [2187, 25])) + (blame_entry [2188, 4] - [2188, 25] + line: (number [2188, 11] - [2188, 14]) + date: (date [2188, 15] - [2188, 25])) + (blame_entry [2189, 4] - [2189, 25] + line: (number [2189, 11] - [2189, 14]) + date: (date [2189, 15] - [2189, 25])) + (blame_entry [2190, 4] - [2190, 25] + line: (number [2190, 11] - [2190, 14]) + date: (date [2190, 15] - [2190, 25]))) + (file_entry [2191, 0] - [2192, 24] + file_name: (filename [2191, 6] - [2191, 59]) + (blame_entry [2192, 4] - [2192, 24] + line: (number [2192, 11] - [2192, 13]) + date: (date [2192, 14] - [2192, 24]))) + (file_entry [2193, 0] - [2194, 24] + file_name: (filename [2193, 6] - [2193, 58]) + (blame_entry [2194, 4] - [2194, 24] + line: (number [2194, 11] - [2194, 13]) + date: (date [2194, 14] - [2194, 24]))) + (file_entry [2195, 0] - [2196, 25] + file_name: (filename [2195, 6] - [2195, 62]) + (blame_entry [2196, 4] - [2196, 25] + line: (number [2196, 11] - [2196, 14]) + date: (date [2196, 15] - [2196, 25]))) + (file_entry [2197, 0] - [2202, 24] + file_name: (filename [2197, 6] - [2197, 56]) + (blame_entry [2198, 4] - [2198, 23] + line: (number [2198, 11] - [2198, 12]) + date: (date [2198, 13] - [2198, 23])) + (blame_entry [2199, 4] - [2199, 23] + line: (number [2199, 11] - [2199, 12]) + date: (date [2199, 13] - [2199, 23])) + (blame_entry [2200, 4] - [2200, 24] + line: (number [2200, 11] - [2200, 13]) + date: (date [2200, 14] - [2200, 24])) + (blame_entry [2201, 4] - [2201, 24] + line: (number [2201, 11] - [2201, 13]) + date: (date [2201, 14] - [2201, 24])) + (blame_entry [2202, 4] - [2202, 24] + line: (number [2202, 11] - [2202, 13]) + date: (date [2202, 14] - [2202, 24]))) + (file_entry [2203, 0] - [2207, 24] + file_name: (filename [2203, 6] - [2203, 56]) + (blame_entry [2204, 4] - [2204, 24] + line: (number [2204, 11] - [2204, 13]) + date: (date [2204, 14] - [2204, 24])) + (blame_entry [2205, 4] - [2205, 24] + line: (number [2205, 11] - [2205, 13]) + date: (date [2205, 14] - [2205, 24])) + (blame_entry [2206, 4] - [2206, 24] + line: (number [2206, 11] - [2206, 13]) + date: (date [2206, 14] - [2206, 24])) + (blame_entry [2207, 4] - [2207, 24] + line: (number [2207, 11] - [2207, 13]) + date: (date [2207, 14] - [2207, 24]))) + (file_entry [2208, 0] - [2210, 24] + file_name: (filename [2208, 6] - [2208, 57]) + (blame_entry [2209, 4] - [2209, 24] + line: (number [2209, 11] - [2209, 13]) + date: (date [2209, 14] - [2209, 24])) + (blame_entry [2210, 4] - [2210, 24] + line: (number [2210, 11] - [2210, 13]) + date: (date [2210, 14] - [2210, 24]))) + (file_entry [2211, 0] - [2221, 24] + file_name: (filename [2211, 6] - [2211, 60]) + (blame_entry [2212, 4] - [2212, 24] + line: (number [2212, 11] - [2212, 13]) + date: (date [2212, 14] - [2212, 24])) + (blame_entry [2213, 4] - [2213, 24] + line: (number [2213, 11] - [2213, 13]) + date: (date [2213, 14] - [2213, 24])) + (blame_entry [2214, 4] - [2214, 24] + line: (number [2214, 11] - [2214, 13]) + date: (date [2214, 14] - [2214, 24])) + (blame_entry [2215, 4] - [2215, 24] + line: (number [2215, 11] - [2215, 13]) + date: (date [2215, 14] - [2215, 24])) + (blame_entry [2216, 4] - [2216, 24] + line: (number [2216, 11] - [2216, 13]) + date: (date [2216, 14] - [2216, 24])) + (blame_entry [2217, 4] - [2217, 24] + line: (number [2217, 11] - [2217, 13]) + date: (date [2217, 14] - [2217, 24])) + (blame_entry [2218, 4] - [2218, 24] + line: (number [2218, 11] - [2218, 13]) + date: (date [2218, 14] - [2218, 24])) + (blame_entry [2219, 4] - [2219, 24] + line: (number [2219, 11] - [2219, 13]) + date: (date [2219, 14] - [2219, 24])) + (blame_entry [2220, 4] - [2220, 24] + line: (number [2220, 11] - [2220, 13]) + date: (date [2220, 14] - [2220, 24])) + (blame_entry [2221, 4] - [2221, 24] + line: (number [2221, 11] - [2221, 13]) + date: (date [2221, 14] - [2221, 24]))) + (file_entry [2222, 0] - [2223, 23] + file_name: (filename [2222, 6] - [2222, 59]) + (blame_entry [2223, 4] - [2223, 23] + line: (number [2223, 11] - [2223, 12]) + date: (date [2223, 13] - [2223, 23]))) + (file_entry [2224, 0] - [2225, 25] + file_name: (filename [2224, 6] - [2224, 58]) + (blame_entry [2225, 4] - [2225, 25] + line: (number [2225, 11] - [2225, 14]) + date: (date [2225, 15] - [2225, 25]))) + (file_entry [2226, 0] - [2228, 24] + file_name: (filename [2226, 6] - [2226, 52]) + (blame_entry [2227, 4] - [2227, 23] + line: (number [2227, 11] - [2227, 12]) + date: (date [2227, 13] - [2227, 23])) + (blame_entry [2228, 4] - [2228, 24] + line: (number [2228, 11] - [2228, 13]) + date: (date [2228, 14] - [2228, 24]))) + (file_entry [2229, 0] - [2230, 23] + file_name: (filename [2229, 6] - [2229, 85]) + (blame_entry [2230, 4] - [2230, 23] + line: (number [2230, 11] - [2230, 12]) + date: (date [2230, 13] - [2230, 23]))) + (file_entry [2231, 0] - [2234, 24] + file_name: (filename [2231, 6] - [2231, 63]) + (blame_entry [2232, 4] - [2232, 24] + line: (number [2232, 11] - [2232, 13]) + date: (date [2232, 14] - [2232, 24])) + (blame_entry [2233, 4] - [2233, 24] + line: (number [2233, 11] - [2233, 13]) + date: (date [2233, 14] - [2233, 24])) + (blame_entry [2234, 4] - [2234, 24] + line: (number [2234, 11] - [2234, 13]) + date: (date [2234, 14] - [2234, 24]))) + (file_entry [2235, 0] - [2237, 25] + file_name: (filename [2235, 6] - [2235, 71]) + (blame_entry [2236, 4] - [2236, 25] + line: (number [2236, 11] - [2236, 14]) + date: (date [2236, 15] - [2236, 25])) + (blame_entry [2237, 4] - [2237, 25] + line: (number [2237, 11] - [2237, 14]) + date: (date [2237, 15] - [2237, 25]))) + (file_entry [2238, 0] - [2239, 24] + file_name: (filename [2238, 6] - [2238, 51]) + (blame_entry [2239, 4] - [2239, 24] + line: (number [2239, 11] - [2239, 13]) + date: (date [2239, 14] - [2239, 24]))) + (file_entry [2240, 0] - [2241, 24] + file_name: (filename [2240, 6] - [2240, 51]) + (blame_entry [2241, 4] - [2241, 24] + line: (number [2241, 11] - [2241, 13]) + date: (date [2241, 14] - [2241, 24]))) + (file_entry [2242, 0] - [2244, 25] + file_name: (filename [2242, 6] - [2242, 100]) + (blame_entry [2243, 4] - [2243, 25] + line: (number [2243, 11] - [2243, 14]) + date: (date [2243, 15] - [2243, 25])) + (blame_entry [2244, 4] - [2244, 25] + line: (number [2244, 11] - [2244, 14]) + date: (date [2244, 15] - [2244, 25]))) + (file_entry [2245, 0] - [2246, 24] + file_name: (filename [2245, 6] - [2245, 67]) + (blame_entry [2246, 4] - [2246, 24] + line: (number [2246, 11] - [2246, 13]) + date: (date [2246, 14] - [2246, 24]))) + (file_entry [2247, 0] - [2251, 25] + file_name: (filename [2247, 6] - [2247, 71]) + (blame_entry [2248, 4] - [2248, 24] + line: (number [2248, 11] - [2248, 13]) + date: (date [2248, 14] - [2248, 24])) + (blame_entry [2249, 4] - [2249, 25] + line: (number [2249, 11] - [2249, 14]) + date: (date [2249, 15] - [2249, 25])) + (blame_entry [2250, 4] - [2250, 25] + line: (number [2250, 11] - [2250, 14]) + date: (date [2250, 15] - [2250, 25])) + (blame_entry [2251, 4] - [2251, 25] + line: (number [2251, 11] - [2251, 14]) + date: (date [2251, 15] - [2251, 25]))) + (file_entry [2252, 0] - [2253, 24] + file_name: (filename [2252, 6] - [2252, 79]) + (blame_entry [2253, 4] - [2253, 24] + line: (number [2253, 11] - [2253, 13]) + date: (date [2253, 14] - [2253, 24]))) + (file_entry [2254, 0] - [2256, 24] + file_name: (filename [2254, 6] - [2254, 61]) + (blame_entry [2255, 4] - [2255, 23] + line: (number [2255, 11] - [2255, 12]) + date: (date [2255, 13] - [2255, 23])) + (blame_entry [2256, 4] - [2256, 24] + line: (number [2256, 11] - [2256, 13]) + date: (date [2256, 14] - [2256, 24]))) + (file_entry [2257, 0] - [2258, 23] + file_name: (filename [2257, 6] - [2257, 51]) + (blame_entry [2258, 4] - [2258, 23] + line: (number [2258, 11] - [2258, 12]) + date: (date [2258, 13] - [2258, 23]))) + (file_entry [2259, 0] - [2260, 24] + file_name: (filename [2259, 6] - [2259, 69]) + (blame_entry [2260, 4] - [2260, 24] + line: (number [2260, 11] - [2260, 13]) + date: (date [2260, 14] - [2260, 24]))) + (file_entry [2261, 0] - [2278, 26] + file_name: (filename [2261, 6] - [2261, 55]) + (blame_entry [2262, 4] - [2262, 25] + line: (number [2262, 11] - [2262, 14]) + date: (date [2262, 15] - [2262, 25])) + (blame_entry [2263, 4] - [2263, 26] + line: (number [2263, 11] - [2263, 15]) + date: (date [2263, 16] - [2263, 26])) + (blame_entry [2264, 4] - [2264, 26] + line: (number [2264, 11] - [2264, 15]) + date: (date [2264, 16] - [2264, 26])) + (blame_entry [2265, 4] - [2265, 26] + line: (number [2265, 11] - [2265, 15]) + date: (date [2265, 16] - [2265, 26])) + (blame_entry [2266, 4] - [2266, 26] + line: (number [2266, 11] - [2266, 15]) + date: (date [2266, 16] - [2266, 26])) + (blame_entry [2267, 4] - [2267, 26] + line: (number [2267, 11] - [2267, 15]) + date: (date [2267, 16] - [2267, 26])) + (blame_entry [2268, 4] - [2268, 26] + line: (number [2268, 11] - [2268, 15]) + date: (date [2268, 16] - [2268, 26])) + (blame_entry [2269, 4] - [2269, 26] + line: (number [2269, 11] - [2269, 15]) + date: (date [2269, 16] - [2269, 26])) + (blame_entry [2270, 4] - [2270, 26] + line: (number [2270, 11] - [2270, 15]) + date: (date [2270, 16] - [2270, 26])) + (blame_entry [2271, 4] - [2271, 26] + line: (number [2271, 11] - [2271, 15]) + date: (date [2271, 16] - [2271, 26])) + (blame_entry [2272, 4] - [2272, 26] + line: (number [2272, 11] - [2272, 15]) + date: (date [2272, 16] - [2272, 26])) + (blame_entry [2273, 4] - [2273, 26] + line: (number [2273, 11] - [2273, 15]) + date: (date [2273, 16] - [2273, 26])) + (blame_entry [2274, 4] - [2274, 26] + line: (number [2274, 11] - [2274, 15]) + date: (date [2274, 16] - [2274, 26])) + (blame_entry [2275, 4] - [2275, 26] + line: (number [2275, 11] - [2275, 15]) + date: (date [2275, 16] - [2275, 26])) + (blame_entry [2276, 4] - [2276, 26] + line: (number [2276, 11] - [2276, 15]) + date: (date [2276, 16] - [2276, 26])) + (blame_entry [2277, 4] - [2277, 26] + line: (number [2277, 11] - [2277, 15]) + date: (date [2277, 16] - [2277, 26])) + (blame_entry [2278, 4] - [2278, 26] + line: (number [2278, 11] - [2278, 15]) + date: (date [2278, 16] - [2278, 26]))) + (file_entry [2279, 0] - [2280, 24] + file_name: (filename [2279, 6] - [2279, 73]) + (blame_entry [2280, 4] - [2280, 24] + line: (number [2280, 11] - [2280, 13]) + date: (date [2280, 14] - [2280, 24]))) + (file_entry [2281, 0] - [2282, 24] + file_name: (filename [2281, 6] - [2281, 62]) + (blame_entry [2282, 4] - [2282, 24] + line: (number [2282, 11] - [2282, 13]) + date: (date [2282, 14] - [2282, 24]))) + (file_entry [2283, 0] - [2284, 24] + file_name: (filename [2283, 6] - [2283, 78]) + (blame_entry [2284, 4] - [2284, 24] + line: (number [2284, 11] - [2284, 13]) + date: (date [2284, 14] - [2284, 24]))) + (file_entry [2285, 0] - [2287, 25] + file_name: (filename [2285, 6] - [2285, 64]) + (blame_entry [2286, 4] - [2286, 24] + line: (number [2286, 11] - [2286, 13]) + date: (date [2286, 14] - [2286, 24])) + (blame_entry [2287, 4] - [2287, 25] + line: (number [2287, 11] - [2287, 14]) + date: (date [2287, 15] - [2287, 25]))) + (file_entry [2288, 0] - [2292, 25] + file_name: (filename [2288, 6] - [2288, 86]) + (blame_entry [2289, 4] - [2289, 25] + line: (number [2289, 11] - [2289, 14]) + date: (date [2289, 15] - [2289, 25])) + (blame_entry [2290, 4] - [2290, 25] + line: (number [2290, 11] - [2290, 14]) + date: (date [2290, 15] - [2290, 25])) + (blame_entry [2291, 4] - [2291, 25] + line: (number [2291, 11] - [2291, 14]) + date: (date [2291, 15] - [2291, 25])) + (blame_entry [2292, 4] - [2292, 25] + line: (number [2292, 11] - [2292, 14]) + date: (date [2292, 15] - [2292, 25]))) + (file_entry [2293, 0] - [2295, 24] + file_name: (filename [2293, 6] - [2293, 54]) + (blame_entry [2294, 4] - [2294, 24] + line: (number [2294, 11] - [2294, 13]) + date: (date [2294, 14] - [2294, 24])) + (blame_entry [2295, 4] - [2295, 24] + line: (number [2295, 11] - [2295, 13]) + date: (date [2295, 14] - [2295, 24]))) + (file_entry [2296, 0] - [2297, 25] + file_name: (filename [2296, 6] - [2296, 65]) + (blame_entry [2297, 4] - [2297, 25] + line: (number [2297, 11] - [2297, 14]) + date: (date [2297, 15] - [2297, 25]))) + (file_entry [2298, 0] - [2302, 25] + file_name: (filename [2298, 6] - [2298, 64]) + (blame_entry [2299, 4] - [2299, 24] + line: (number [2299, 11] - [2299, 13]) + date: (date [2299, 14] - [2299, 24])) + (blame_entry [2300, 4] - [2300, 25] + line: (number [2300, 11] - [2300, 14]) + date: (date [2300, 15] - [2300, 25])) + (blame_entry [2301, 4] - [2301, 25] + line: (number [2301, 11] - [2301, 14]) + date: (date [2301, 15] - [2301, 25])) + (blame_entry [2302, 4] - [2302, 25] + line: (number [2302, 11] - [2302, 14]) + date: (date [2302, 15] - [2302, 25]))) + (file_entry [2303, 0] - [2304, 23] + file_name: (filename [2303, 6] - [2303, 69]) + (blame_entry [2304, 4] - [2304, 23] + line: (number [2304, 11] - [2304, 12]) + date: (date [2304, 13] - [2304, 23]))) + (file_entry [2305, 0] - [2306, 24] + file_name: (filename [2305, 6] - [2305, 73]) + (blame_entry [2306, 4] - [2306, 24] + line: (number [2306, 11] - [2306, 13]) + date: (date [2306, 14] - [2306, 24]))) + (file_entry [2307, 0] - [2311, 25] + file_name: (filename [2307, 6] - [2307, 73]) + (blame_entry [2308, 4] - [2308, 24] + line: (number [2308, 11] - [2308, 13]) + date: (date [2308, 14] - [2308, 24])) + (blame_entry [2309, 4] - [2309, 25] + line: (number [2309, 11] - [2309, 14]) + date: (date [2309, 15] - [2309, 25])) + (blame_entry [2310, 4] - [2310, 25] + line: (number [2310, 11] - [2310, 14]) + date: (date [2310, 15] - [2310, 25])) + (blame_entry [2311, 4] - [2311, 25] + line: (number [2311, 11] - [2311, 14]) + date: (date [2311, 15] - [2311, 25]))) + (file_entry [2312, 0] - [2317, 25] + file_name: (filename [2312, 6] - [2312, 92]) + (blame_entry [2313, 4] - [2313, 25] + line: (number [2313, 11] - [2313, 14]) + date: (date [2313, 15] - [2313, 25])) + (blame_entry [2314, 4] - [2314, 25] + line: (number [2314, 11] - [2314, 14]) + date: (date [2314, 15] - [2314, 25])) + (blame_entry [2315, 4] - [2315, 25] + line: (number [2315, 11] - [2315, 14]) + date: (date [2315, 15] - [2315, 25])) + (blame_entry [2316, 4] - [2316, 25] + line: (number [2316, 11] - [2316, 14]) + date: (date [2316, 15] - [2316, 25])) + (blame_entry [2317, 4] - [2317, 25] + line: (number [2317, 11] - [2317, 14]) + date: (date [2317, 15] - [2317, 25]))) + (file_entry [2318, 0] - [2319, 24] + file_name: (filename [2318, 6] - [2318, 44]) + (blame_entry [2319, 4] - [2319, 24] + line: (number [2319, 11] - [2319, 13]) + date: (date [2319, 14] - [2319, 24]))) + (file_entry [2320, 0] - [2322, 24] + file_name: (filename [2320, 6] - [2320, 53]) + (blame_entry [2321, 4] - [2321, 23] + line: (number [2321, 11] - [2321, 12]) + date: (date [2321, 13] - [2321, 23])) + (blame_entry [2322, 4] - [2322, 24] + line: (number [2322, 11] - [2322, 13]) + date: (date [2322, 14] - [2322, 24]))) + (file_entry [2323, 0] - [2330, 25] + file_name: (filename [2323, 6] - [2323, 79]) + (blame_entry [2324, 4] - [2324, 24] + line: (number [2324, 11] - [2324, 13]) + date: (date [2324, 14] - [2324, 24])) + (blame_entry [2325, 4] - [2325, 24] + line: (number [2325, 11] - [2325, 13]) + date: (date [2325, 14] - [2325, 24])) + (blame_entry [2326, 4] - [2326, 25] + line: (number [2326, 11] - [2326, 14]) + date: (date [2326, 15] - [2326, 25])) + (blame_entry [2327, 4] - [2327, 25] + line: (number [2327, 11] - [2327, 14]) + date: (date [2327, 15] - [2327, 25])) + (blame_entry [2328, 4] - [2328, 25] + line: (number [2328, 11] - [2328, 14]) + date: (date [2328, 15] - [2328, 25])) + (blame_entry [2329, 4] - [2329, 25] + line: (number [2329, 11] - [2329, 14]) + date: (date [2329, 15] - [2329, 25])) + (blame_entry [2330, 4] - [2330, 25] + line: (number [2330, 11] - [2330, 14]) + date: (date [2330, 15] - [2330, 25]))) + (file_entry [2331, 0] - [2333, 25] + file_name: (filename [2331, 6] - [2331, 66]) + (blame_entry [2332, 4] - [2332, 24] + line: (number [2332, 11] - [2332, 13]) + date: (date [2332, 14] - [2332, 24])) + (blame_entry [2333, 4] - [2333, 25] + line: (number [2333, 11] - [2333, 14]) + date: (date [2333, 15] - [2333, 25]))) + (file_entry [2334, 0] - [2339, 25] + file_name: (filename [2334, 6] - [2334, 91]) + (blame_entry [2335, 4] - [2335, 24] + line: (number [2335, 11] - [2335, 13]) + date: (date [2335, 14] - [2335, 24])) + (blame_entry [2336, 4] - [2336, 25] + line: (number [2336, 11] - [2336, 14]) + date: (date [2336, 15] - [2336, 25])) + (blame_entry [2337, 4] - [2337, 25] + line: (number [2337, 11] - [2337, 14]) + date: (date [2337, 15] - [2337, 25])) + (blame_entry [2338, 4] - [2338, 25] + line: (number [2338, 11] - [2338, 14]) + date: (date [2338, 15] - [2338, 25])) + (blame_entry [2339, 4] - [2339, 25] + line: (number [2339, 11] - [2339, 14]) + date: (date [2339, 15] - [2339, 25]))) + (file_entry [2340, 0] - [2353, 25] + file_name: (filename [2340, 6] - [2340, 41]) + (blame_entry [2341, 4] - [2341, 24] + line: (number [2341, 11] - [2341, 13]) + date: (date [2341, 14] - [2341, 24])) + (blame_entry [2342, 4] - [2342, 24] + line: (number [2342, 11] - [2342, 13]) + date: (date [2342, 14] - [2342, 24])) + (blame_entry [2343, 4] - [2343, 25] + line: (number [2343, 11] - [2343, 14]) + date: (date [2343, 15] - [2343, 25])) + (blame_entry [2344, 4] - [2344, 25] + line: (number [2344, 11] - [2344, 14]) + date: (date [2344, 15] - [2344, 25])) + (blame_entry [2345, 4] - [2345, 25] + line: (number [2345, 11] - [2345, 14]) + date: (date [2345, 15] - [2345, 25])) + (blame_entry [2346, 4] - [2346, 25] + line: (number [2346, 11] - [2346, 14]) + date: (date [2346, 15] - [2346, 25])) + (blame_entry [2347, 4] - [2347, 25] + line: (number [2347, 11] - [2347, 14]) + date: (date [2347, 15] - [2347, 25])) + (blame_entry [2348, 4] - [2348, 25] + line: (number [2348, 11] - [2348, 14]) + date: (date [2348, 15] - [2348, 25])) + (blame_entry [2349, 4] - [2349, 25] + line: (number [2349, 11] - [2349, 14]) + date: (date [2349, 15] - [2349, 25])) + (blame_entry [2350, 4] - [2350, 25] + line: (number [2350, 11] - [2350, 14]) + date: (date [2350, 15] - [2350, 25])) + (blame_entry [2351, 4] - [2351, 25] + line: (number [2351, 11] - [2351, 14]) + date: (date [2351, 15] - [2351, 25])) + (blame_entry [2352, 4] - [2352, 25] + line: (number [2352, 11] - [2352, 14]) + date: (date [2352, 15] - [2352, 25])) + (blame_entry [2353, 4] - [2353, 25] + line: (number [2353, 11] - [2353, 14]) + date: (date [2353, 15] - [2353, 25]))) + (file_entry [2354, 0] - [2356, 24] + file_name: (filename [2354, 6] - [2354, 69]) + (blame_entry [2355, 4] - [2355, 23] + line: (number [2355, 11] - [2355, 12]) + date: (date [2355, 13] - [2355, 23])) + (blame_entry [2356, 4] - [2356, 24] + line: (number [2356, 11] - [2356, 13]) + date: (date [2356, 14] - [2356, 24]))) + (file_entry [2357, 0] - [2360, 24] + file_name: (filename [2357, 6] - [2357, 57]) + (blame_entry [2358, 4] - [2358, 23] + line: (number [2358, 11] - [2358, 12]) + date: (date [2358, 13] - [2358, 23])) + (blame_entry [2359, 4] - [2359, 24] + line: (number [2359, 11] - [2359, 13]) + date: (date [2359, 14] - [2359, 24])) + (blame_entry [2360, 4] - [2360, 24] + line: (number [2360, 11] - [2360, 13]) + date: (date [2360, 14] - [2360, 24]))) + (file_entry [2361, 0] - [2363, 25] + file_name: (filename [2361, 6] - [2361, 91]) + (blame_entry [2362, 4] - [2362, 24] + line: (number [2362, 11] - [2362, 13]) + date: (date [2362, 14] - [2362, 24])) + (blame_entry [2363, 4] - [2363, 25] + line: (number [2363, 11] - [2363, 14]) + date: (date [2363, 15] - [2363, 25]))) + (file_entry [2364, 0] - [2367, 24] + file_name: (filename [2364, 6] - [2364, 58]) + (blame_entry [2365, 4] - [2365, 23] + line: (number [2365, 11] - [2365, 12]) + date: (date [2365, 13] - [2365, 23])) + (blame_entry [2366, 4] - [2366, 24] + line: (number [2366, 11] - [2366, 13]) + date: (date [2366, 14] - [2366, 24])) + (blame_entry [2367, 4] - [2367, 24] + line: (number [2367, 11] - [2367, 13]) + date: (date [2367, 14] - [2367, 24]))) + (file_entry [2368, 0] - [2369, 25] + file_name: (filename [2368, 6] - [2368, 69]) + (blame_entry [2369, 4] - [2369, 25] + line: (number [2369, 11] - [2369, 14]) + date: (date [2369, 15] - [2369, 25]))) + (file_entry [2370, 0] - [2374, 25] + file_name: (filename [2370, 6] - [2370, 72]) + (blame_entry [2371, 4] - [2371, 24] + line: (number [2371, 11] - [2371, 13]) + date: (date [2371, 14] - [2371, 24])) + (blame_entry [2372, 4] - [2372, 24] + line: (number [2372, 11] - [2372, 13]) + date: (date [2372, 14] - [2372, 24])) + (blame_entry [2373, 4] - [2373, 25] + line: (number [2373, 11] - [2373, 14]) + date: (date [2373, 15] - [2373, 25])) + (blame_entry [2374, 4] - [2374, 25] + line: (number [2374, 11] - [2374, 14]) + date: (date [2374, 15] - [2374, 25]))) + (file_entry [2375, 0] - [2376, 24] + file_name: (filename [2375, 6] - [2375, 83]) + (blame_entry [2376, 4] - [2376, 24] + line: (number [2376, 11] - [2376, 13]) + date: (date [2376, 14] - [2376, 24]))) + (file_entry [2377, 0] - [2378, 25] + file_name: (filename [2377, 6] - [2377, 85]) + (blame_entry [2378, 4] - [2378, 25] + line: (number [2378, 11] - [2378, 14]) + date: (date [2378, 15] - [2378, 25]))) + (file_entry [2379, 0] - [2380, 25] + file_name: (filename [2379, 6] - [2379, 79]) + (blame_entry [2380, 4] - [2380, 25] + line: (number [2380, 11] - [2380, 14]) + date: (date [2380, 15] - [2380, 25]))) + (file_entry [2381, 0] - [2382, 24] + file_name: (filename [2381, 6] - [2381, 67]) + (blame_entry [2382, 4] - [2382, 24] + line: (number [2382, 11] - [2382, 13]) + date: (date [2382, 14] - [2382, 24]))) + (file_entry [2383, 0] - [2384, 24] + file_name: (filename [2383, 6] - [2383, 74]) + (blame_entry [2384, 4] - [2384, 24] + line: (number [2384, 11] - [2384, 13]) + date: (date [2384, 14] - [2384, 24]))) + (file_entry [2385, 0] - [2387, 24] + file_name: (filename [2385, 6] - [2385, 57]) + (blame_entry [2386, 4] - [2386, 24] + line: (number [2386, 11] - [2386, 13]) + date: (date [2386, 14] - [2386, 24])) + (blame_entry [2387, 4] - [2387, 24] + line: (number [2387, 11] - [2387, 13]) + date: (date [2387, 14] - [2387, 24]))) + (file_entry [2388, 0] - [2389, 24] + file_name: (filename [2388, 6] - [2388, 52]) + (blame_entry [2389, 4] - [2389, 24] + line: (number [2389, 11] - [2389, 13]) + date: (date [2389, 14] - [2389, 24]))) + (file_entry [2390, 0] - [2391, 24] + file_name: (filename [2390, 6] - [2390, 56]) + (blame_entry [2391, 4] - [2391, 24] + line: (number [2391, 11] - [2391, 13]) + date: (date [2391, 14] - [2391, 24]))) + (file_entry [2392, 0] - [2393, 24] + file_name: (filename [2392, 6] - [2392, 84]) + (blame_entry [2393, 4] - [2393, 24] + line: (number [2393, 11] - [2393, 13]) + date: (date [2393, 14] - [2393, 24]))) + (file_entry [2394, 0] - [2395, 24] + file_name: (filename [2394, 6] - [2394, 84]) + (blame_entry [2395, 4] - [2395, 24] + line: (number [2395, 11] - [2395, 13]) + date: (date [2395, 14] - [2395, 24]))) + (file_entry [2396, 0] - [2401, 25] + file_name: (filename [2396, 6] - [2396, 52]) + (blame_entry [2397, 4] - [2397, 25] + line: (number [2397, 11] - [2397, 14]) + date: (date [2397, 15] - [2397, 25])) + (blame_entry [2398, 4] - [2398, 25] + line: (number [2398, 11] - [2398, 14]) + date: (date [2398, 15] - [2398, 25])) + (blame_entry [2399, 4] - [2399, 25] + line: (number [2399, 11] - [2399, 14]) + date: (date [2399, 15] - [2399, 25])) + (blame_entry [2400, 4] - [2400, 25] + line: (number [2400, 11] - [2400, 14]) + date: (date [2400, 15] - [2400, 25])) + (blame_entry [2401, 4] - [2401, 25] + line: (number [2401, 11] - [2401, 14]) + date: (date [2401, 15] - [2401, 25]))) + (file_entry [2402, 0] - [2405, 24] + file_name: (filename [2402, 6] - [2402, 72]) + (blame_entry [2403, 4] - [2403, 24] + line: (number [2403, 11] - [2403, 13]) + date: (date [2403, 14] - [2403, 24])) + (blame_entry [2404, 4] - [2404, 24] + line: (number [2404, 11] - [2404, 13]) + date: (date [2404, 14] - [2404, 24])) + (blame_entry [2405, 4] - [2405, 24] + line: (number [2405, 11] - [2405, 13]) + date: (date [2405, 14] - [2405, 24]))) + (file_entry [2406, 0] - [2409, 25] + file_name: (filename [2406, 6] - [2406, 94]) + (blame_entry [2407, 4] - [2407, 24] + line: (number [2407, 11] - [2407, 13]) + date: (date [2407, 14] - [2407, 24])) + (blame_entry [2408, 4] - [2408, 24] + line: (number [2408, 11] - [2408, 13]) + date: (date [2408, 14] - [2408, 24])) + (blame_entry [2409, 4] - [2409, 25] + line: (number [2409, 11] - [2409, 14]) + date: (date [2409, 15] - [2409, 25]))) + (file_entry [2410, 0] - [2414, 25] + file_name: (filename [2410, 6] - [2410, 89]) + (blame_entry [2411, 4] - [2411, 25] + line: (number [2411, 11] - [2411, 14]) + date: (date [2411, 15] - [2411, 25])) + (blame_entry [2412, 4] - [2412, 25] + line: (number [2412, 11] - [2412, 14]) + date: (date [2412, 15] - [2412, 25])) + (blame_entry [2413, 4] - [2413, 25] + line: (number [2413, 11] - [2413, 14]) + date: (date [2413, 15] - [2413, 25])) + (blame_entry [2414, 4] - [2414, 25] + line: (number [2414, 11] - [2414, 14]) + date: (date [2414, 15] - [2414, 25]))) + (file_entry [2415, 0] - [2416, 24] + file_name: (filename [2415, 6] - [2415, 71]) + (blame_entry [2416, 4] - [2416, 24] + line: (number [2416, 11] - [2416, 13]) + date: (date [2416, 14] - [2416, 24]))) + (file_entry [2417, 0] - [2418, 24] + file_name: (filename [2417, 6] - [2417, 56]) + (blame_entry [2418, 4] - [2418, 24] + line: (number [2418, 11] - [2418, 13]) + date: (date [2418, 14] - [2418, 24]))) + (file_entry [2419, 0] - [2421, 24] + file_name: (filename [2419, 6] - [2419, 70]) + (blame_entry [2420, 4] - [2420, 23] + line: (number [2420, 11] - [2420, 12]) + date: (date [2420, 13] - [2420, 23])) + (blame_entry [2421, 4] - [2421, 24] + line: (number [2421, 11] - [2421, 13]) + date: (date [2421, 14] - [2421, 24]))) + (file_entry [2422, 0] - [2423, 24] + file_name: (filename [2422, 6] - [2422, 61]) + (blame_entry [2423, 4] - [2423, 24] + line: (number [2423, 11] - [2423, 13]) + date: (date [2423, 14] - [2423, 24]))) + (file_entry [2424, 0] - [2426, 24] + file_name: (filename [2424, 6] - [2424, 79]) + (blame_entry [2425, 4] - [2425, 24] + line: (number [2425, 11] - [2425, 13]) + date: (date [2425, 14] - [2425, 24])) + (blame_entry [2426, 4] - [2426, 24] + line: (number [2426, 11] - [2426, 13]) + date: (date [2426, 14] - [2426, 24]))) + (file_entry [2427, 0] - [2428, 25] + file_name: (filename [2427, 6] - [2427, 47]) + (blame_entry [2428, 4] - [2428, 25] + line: (number [2428, 11] - [2428, 14]) + date: (date [2428, 15] - [2428, 25]))) + (file_entry [2429, 0] - [2433, 25] + file_name: (filename [2429, 6] - [2429, 86]) + (blame_entry [2430, 4] - [2430, 24] + line: (number [2430, 11] - [2430, 13]) + date: (date [2430, 14] - [2430, 24])) + (blame_entry [2431, 4] - [2431, 25] + line: (number [2431, 11] - [2431, 14]) + date: (date [2431, 15] - [2431, 25])) + (blame_entry [2432, 4] - [2432, 25] + line: (number [2432, 11] - [2432, 14]) + date: (date [2432, 15] - [2432, 25])) + (blame_entry [2433, 4] - [2433, 25] + line: (number [2433, 11] - [2433, 14]) + date: (date [2433, 15] - [2433, 25]))) + (file_entry [2434, 0] - [2435, 25] + file_name: (filename [2434, 6] - [2434, 51]) + (blame_entry [2435, 4] - [2435, 25] + line: (number [2435, 11] - [2435, 14]) + date: (date [2435, 15] - [2435, 25]))) + (file_entry [2436, 0] - [2437, 23] + file_name: (filename [2436, 6] - [2436, 57]) + (blame_entry [2437, 4] - [2437, 23] + line: (number [2437, 11] - [2437, 12]) + date: (date [2437, 13] - [2437, 23]))) + (file_entry [2438, 0] - [2439, 24] + file_name: (filename [2438, 6] - [2438, 102]) + (blame_entry [2439, 4] - [2439, 24] + line: (number [2439, 11] - [2439, 13]) + date: (date [2439, 14] - [2439, 24]))) + (file_entry [2440, 0] - [2441, 24] + file_name: (filename [2440, 6] - [2440, 55]) + (blame_entry [2441, 4] - [2441, 24] + line: (number [2441, 11] - [2441, 13]) + date: (date [2441, 14] - [2441, 24])))) +today: + 2023-02-16 + + file: + cpp/ql/lib/semmle/code/cpp/valuenumbering/GlobalValueNumberingImpl.qll + + blame: + 186 + + 2023-01-03 + + + blame: + 195 + + 2023-01-03 + + + blame: + 204 + + 2023-01-03 + + + blame: + 205 + + 2023-01-03 + + + blame: + 206 + + 2023-01-03 + + + blame: + 207 + + 2023-01-03 + + + blame: + 230 + + 2022-11-14 + + + blame: + 345 + + 2023-01-03 + + + blame: + 358 + + 2023-01-03 + + + blame: + 371 + + 2023-01-03 + + + blame: + 396 + + 2023-01-03 + + + blame: + 405 + + 2023-01-03 + + + blame: + 439 + + 2023-01-03 + + + blame: + 453 + + 2023-01-03 + + + blame: + 468 + + 2023-01-03 + + + blame: + 491 + + 2023-01-03 + + + blame: + 506 + + 2023-01-03 + + + blame: + 514 + + 2022-11-14 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll + + blame: + 12 + + 2022-11-01 + + + + file: + csharp/ql/lib/semmle/code/cil/Ssa.qll + + blame: + 27 + + 2022-10-11 + + + blame: + 30 + + 2022-10-11 + + + blame: + 61 + + 2022-10-11 + + + + file: + java/ql/lib/semmle/code/java/frameworks/android/Intent.qll + + blame: + 72 + + 2022-09-28 + + + + file: + python/ql/lib/semmle/python/essa/SsaDefinitions.qll + + blame: + 88 + + 2022-09-06 + + + + file: + java/ql/lib/semmle/code/java/JMX.qll + + blame: + 54 + + 2022-08-24 + + + blame: + 94 + + 2022-08-24 + + + blame: + 104 + + 2022-08-24 + + + blame: + 112 + + 2022-08-24 + + + blame: + 120 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll + + blame: + 21 + + 2022-08-24 + + + blame: + 38 + + 2022-08-24 + + + + file: + java/ql/lib/semmle/code/java/deadcode/DeadField.qll + + blame: + 101 + + 2022-08-24 + + + blame: + 177 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll + + blame: + 3 + + 2022-05-25 + + + + file: + python/ql/lib/semmle/python/security/dataflow/SqlInjectionQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/commons/StringAnalysis.qll + + blame: + 31 + + 2022-05-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll + + blame: + 214 + + 2022-03-11 + + + blame: + 468 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll + + blame: + 61 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 169 + + 2022-03-11 + + + + file: + csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll + + blame: + 74 + + 2022-03-11 + + + blame: + 109 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll + + blame: + 181 + + 2022-03-11 + + + blame: + 524 + + 2022-03-11 + + + blame: + 558 + + 2022-03-11 + + + blame: + 582 + + 2022-03-11 + + + blame: + 623 + + 2022-03-11 + + + + file: + javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/FunctionBodyFeatures.qll + + blame: + 45 + + 2022-03-11 + + + blame: + 134 + + 2022-03-11 + + + + file: + cpp/ql/src/external/CodeDuplication.qll + + blame: + 5 + + 2022-03-08 + + + blame: + 12 + + 2022-03-08 + + + blame: + 66 + + 2022-03-08 + + + blame: + 77 + + 2022-03-08 + + + blame: + 88 + + 2022-03-08 + + + blame: + 99 + + 2022-03-08 + + + blame: + 107 + + 2022-03-08 + + + blame: + 116 + + 2022-03-08 + + + blame: + 122 + + 2022-03-08 + + + blame: + 141 + + 2022-03-08 + + + blame: + 153 + + 2022-03-08 + + + blame: + 164 + + 2022-03-08 + + + blame: + 168 + + 2022-03-08 + + + blame: + 178 + + 2022-03-08 + + + blame: + 199 + + 2022-03-08 + + + blame: + 220 + + 2022-03-08 + + + blame: + 226 + + 2022-03-08 + + + blame: + 241 + + 2022-03-08 + + + blame: + 270 + + 2022-03-08 + + + blame: + 285 + + 2022-03-08 + + + blame: + 300 + + 2022-03-08 + + + blame: + 322 + + 2022-03-08 + + + blame: + 351 + + 2022-03-08 + + + blame: + 361 + + 2022-03-08 + + + blame: + 371 + + 2022-03-08 + + + + file: + cpp/ql/lib/semmle/code/cpp/File.qll + + blame: + 43 + + 2022-03-07 + + + blame: + 191 + + 2022-03-07 + + + blame: + 220 + + 2022-03-07 + + + + file: + cpp/ql/lib/semmle/code/cpp/controlflow/internal/CFG.qll + + blame: + 1389 + + 2022-03-11 + + + blame: + 1402 + + 2022-03-11 + + + blame: + 1415 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/controlflow/SSAUtils.qll + + blame: + 316 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgery.qll + + blame: + 10 + + 2022-03-21 + + + blame: + 17 + + 2022-03-21 + + + blame: + 21 + + 2022-03-21 + + + + file: + javascript/ql/lib/semmle/javascript/NPM.qll + + blame: + 177 + + 2022-08-24 + + + blame: + 187 + + 2022-08-24 + + + blame: + 248 + + 2022-03-11 + + + blame: + 356 + + 2022-03-11 + + + blame: + 397 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll + + blame: + 425 + + 2022-03-11 + + + blame: + 995 + + 2022-03-11 + + + blame: + 1007 + + 2022-03-11 + + + blame: + 1120 + + 2022-03-11 + + + blame: + 1139 + + 2022-09-09 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + go/ql/lib/semmle/go/security/FlowSources.qll + + blame: + 33 + + 2022-12-19 + + + + file: + python/ql/lib/semmle/python/security/Exceptions.qll + + blame: + 10 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 28 + + 2022-01-19 + + + blame: + 33 + + 2022-01-19 + + + blame: + 49 + + 2022-01-19 + + + blame: + 68 + + 2022-01-19 + + + blame: + 76 + + 2022-01-19 + + + blame: + 97 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/frameworks/spring/SpringAutowire.qll + + blame: + 104 + + 2022-03-11 + + + + file: + csharp/ql/lib/semmle/code/cil/DataFlow.qll + + blame: + 23 + + 2022-10-11 + + + blame: + 29 + + 2022-10-11 + + + blame: + 34 + + 2022-10-11 + + + blame: + 43 + + 2022-10-11 + + + blame: + 48 + + 2022-10-11 + + + blame: + 57 + + 2022-10-11 + + + blame: + 60 + + 2022-10-11 + + + blame: + 62 + + 2022-10-11 + + + blame: + 81 + + 2022-10-11 + + + blame: + 108 + + 2022-10-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll + + blame: + 22 + + 2022-03-11 + + + blame: + 28 + + 2022-03-30 + + + blame: + 39 + + 2022-03-30 + + + blame: + 52 + + 2022-03-13 + + + blame: + 58 + + 2022-03-13 + + + blame: + 64 + + 2022-03-14 + + + blame: + 67 + + 2022-03-11 + + + blame: + 77 + + 2022-03-30 + + + blame: + 87 + + 2022-03-30 + + + blame: + 93 + + 2022-03-30 + + + blame: + 98 + + 2022-03-30 + + + blame: + 103 + + 2022-03-30 + + + blame: + 158 + + 2022-04-28 + + + blame: + 163 + + 2022-04-28 + + + blame: + 172 + + 2022-03-30 + + + blame: + 183 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/Concepts.qll + + blame: + 603 + + 2022-09-09 + + + blame: + 1059 + + 2022-09-09 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + javascript/ql/src/Expressions/TypoDatabase.qll + + blame: + 4 + + 2022-09-08 + + + + file: + csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll + + blame: + 45 + + 2021-10-14 + + + blame: + 58 + + 2021-10-14 + + + + file: + python/ql/lib/semmle/python/frameworks/SqlAlchemy.qll + + blame: + 13 + + 2021-09-01 + + + blame: + 173 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll + + blame: + 3 + + 2022-08-16 + + + + file: + csharp/ql/lib/semmle/code/csharp/XML.qll + + blame: + 36 + + 2022-08-16 + + + blame: + 99 + + 2022-08-16 + + + blame: + 116 + + 2021-10-14 + + + blame: + 123 + + 2021-10-14 + + + blame: + 138 + + 2022-08-23 + + + blame: + 142 + + 2022-08-16 + + + blame: + 181 + + 2022-08-23 + + + blame: + 239 + + 2022-08-16 + + + blame: + 272 + + 2022-08-16 + + + blame: + 291 + + 2022-08-22 + + + blame: + 304 + + 2022-08-16 + + + blame: + 327 + + 2022-08-16 + + + blame: + 354 + + 2022-08-16 + + + + file: + csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll + + blame: + 196 + + 2023-01-06 + + + blame: + 208 + + 2023-01-06 + + + + file: + csharp/ql/lib/semmle/code/cil/internal/SsaImpl.qll + + blame: + 81 + + 2022-10-21 + + + blame: + 89 + + 2022-10-21 + + + blame: + 97 + + 2022-10-21 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-17 + + + blame: + 126 + + 2022-06-17 + + + blame: + 136 + + 2022-10-20 + + + blame: + 140 + + 2022-10-20 + + + + file: + python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll + + blame: + 40 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll + + blame: + 7 + + 2022-11-22 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll + + blame: + 161 + + 2022-03-30 + + + + file: + ruby/ql/lib/codeql/ruby/security/OpenSSL.qll + + blame: + 143 + + 2022-08-18 + + + blame: + 273 + + 2022-08-18 + + + blame: + 286 + + 2022-08-18 + + + blame: + 338 + + 2022-08-18 + + + + file: + javascript/ql/lib/semmle/javascript/security/regexp/SuperlinearBackTracking.qll + + blame: + 40 + + 2022-11-01 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-09-09 + + + blame: + 106 + + 2022-09-09 + + + blame: + 358 + + 2022-09-09 + + + blame: + 365 + + 2022-09-09 + + + + file: + go/ql/lib/semmle/go/security/XPathInjectionCustomizations.qll + + blame: + 32 + + 2022-06-17 + + + + file: + java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll + + blame: + 116 + + 2022-08-18 + + + blame: + 136 + + 2022-08-18 + + + blame: + 156 + + 2022-08-18 + + + blame: + 194 + + 2022-08-18 + + + blame: + 249 + + 2022-08-22 + + + blame: + 278 + + 2022-08-22 + + + blame: + 317 + + 2022-08-22 + + + blame: + 454 + + 2022-08-22 + + + blame: + 474 + + 2022-08-22 + + + blame: + 499 + + 2022-08-22 + + + blame: + 527 + + 2022-08-22 + + + blame: + 547 + + 2022-08-22 + + + blame: + 572 + + 2022-08-22 + + + blame: + 597 + + 2022-08-22 + + + blame: + 864 + + 2022-08-18 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Electron.qll + + blame: + 136 + + 2022-08-24 + + + blame: + 175 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/security/dataflow/RegexInjectionQuery.qll + + blame: + 27 + + 2022-06-17 + + + + file: + java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll + + blame: + 12 + + 2022-11-01 + + + + file: + java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll + + blame: + 27 + + 2022-06-15 + + + + file: + ruby/ql/lib/codeql/ruby/security/PathInjectionQuery.qll + + blame: + 30 + + 2022-06-20 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll + + blame: + 116 + + 2022-01-19 + + + blame: + 211 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/strings/Basic.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 45 + + 2022-01-19 + + + blame: + 67 + + 2022-01-19 + + + blame: + 73 + + 2022-01-19 + + + blame: + 87 + + 2022-01-19 + + + blame: + 97 + + 2022-01-19 + + + blame: + 107 + + 2022-01-19 + + + blame: + 113 + + 2022-01-19 + + + blame: + 122 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/security/CodeInjectionQuery.qll + + blame: + 39 + + 2022-06-20 + + + + file: + cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll + + blame: + 66 + + 2021-10-14 + + + blame: + 71 + + 2021-10-14 + + + blame: + 76 + + 2021-10-14 + + + blame: + 81 + + 2021-10-14 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll + + blame: + 57 + + 2022-06-20 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll + + blame: + 214 + + 2022-03-11 + + + blame: + 468 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LogInjection.qll + + blame: + 8 + + 2022-03-21 + + + + file: + python/ql/src/experimental/semmle/python/templates/Cheetah.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 27 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/security/dataflow/StackTraceExposure.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + + file: + cpp/ql/lib/semmle/code/cpp/Class.qll + + blame: + 191 + + 2022-01-20 + + + blame: + 234 + + 2021-10-14 + + + blame: + 240 + + 2021-10-14 + + + blame: + 410 + + 2022-08-24 + + + + file: + go/ql/lib/semmle/go/security/XPathInjection.qll + + blame: + 31 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/E4X.qll + + blame: + 20 + + 2022-03-11 + + + blame: + 61 + + 2022-03-11 + + + blame: + 93 + + 2022-03-11 + + + blame: + 121 + + 2022-03-11 + + + blame: + 149 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/SensitiveData.qll + + blame: + 18 + + 2022-01-19 + + + blame: + 26 + + 2022-01-19 + + + blame: + 118 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/frameworks/Starlette.qll + + blame: + 164 + + 2022-09-09 + + + + file: + python/ql/lib/semmle/python/web/turbogears/TurboGears.qll + + blame: + 4 + + 2022-01-19 + + + blame: + 8 + + 2022-01-19 + + + blame: + 12 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Pattern.qll + + blame: + 13 + + 2021-12-14 + + + blame: + 35 + + 2021-12-14 + + + blame: + 51 + + 2021-12-14 + + + blame: + 450 + + 2022-01-27 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/RegexpMatching.qll + + blame: + 8 + + 2022-11-01 + + + + file: + go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll + + blame: + 42 + + 2022-06-17 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll + + blame: + 67 + + 2022-11-01 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll + + blame: + 45 + + 2022-03-11 + + + blame: + 234 + + 2022-03-11 + + + blame: + 263 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll + + blame: + 145 + + 2022-03-30 + + + blame: + 1821 + + 2022-03-13 + + + + file: + java/ql/lib/semmle/code/java/J2EE.qll + + blame: + 29 + + 2022-08-18 + + + blame: + 39 + + 2022-08-18 + + + blame: + 49 + + 2022-08-18 + + + blame: + 59 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/pointsto/Filters.qll + + blame: + 16 + + 2022-09-06 + + + blame: + 29 + + 2022-09-06 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll + + blame: + 68 + + 2022-03-11 + + + blame: + 87 + + 2022-03-11 + + + blame: + 376 + + 2022-03-11 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll + + blame: + 214 + + 2022-03-11 + + + blame: + 468 + + 2022-03-11 + + + + file: + ql/ql/src/queries/style/docs/PredicateDocs.ql + + blame: + 21 + + 2022-08-15 + + + + file: + shared/regex/codeql/regex/nfa/NfaUtils.qll + + blame: + 80 + + 2022-11-01 + + + + file: + csharp/ql/lib/semmle/code/csharp/security/dataflow/ExternalAPIsQuery.qll + + blame: + 18 + + 2022-03-11 + + + blame: + 83 + + 2022-11-24 + + + blame: + 91 + + 2022-03-11 + + + blame: + 103 + + 2022-03-11 + + + blame: + 116 + + 2022-03-11 + + + blame: + 154 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/dataflow/barrierguardutil/RedirectCheckBarrierGuard.qll + + blame: + 30 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/injection/RegexInjection.qll + + blame: + 6 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryCustomizations.qll + + blame: + 39 + + 2022-06-20 + + + + file: + ruby/ql/lib/codeql/ruby/frameworks/core/internal/IOOrFile.qll + + blame: + 67 + + 2022-04-01 + + + blame: + 119 + + 2022-04-01 + + + blame: + 163 + + 2022-04-01 + + + + file: + ql/ql/src/queries/style/NameCasing.ql + + blame: + 42 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll + + blame: + 7 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/protocols.qll + + blame: + 4 + + 2022-09-06 + + + blame: + 7 + + 2022-09-06 + + + blame: + 10 + + 2022-09-06 + + + blame: + 13 + + 2022-09-06 + + + blame: + 16 + + 2022-09-06 + + + blame: + 19 + + 2022-09-06 + + + + file: + javascript/ql/lib/semmle/javascript/ApiGraphs.qll + + blame: + 157 + + 2022-05-23 + + + blame: + 160 + + 2022-04-05 + + + blame: + 216 + + 2022-05-23 + + + blame: + 219 + + 2022-04-05 + + + blame: + 585 + + 2022-04-05 + + + blame: + 588 + + 2022-04-05 + + + blame: + 600 + + 2022-03-16 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll + + blame: + 22 + + 2022-03-11 + + + blame: + 58 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/security/XSS.qll + + blame: + 113 + + 2021-09-14 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll + + blame: + 274 + + 2021-11-01 + + + blame: + 365 + + 2021-11-01 + + + blame: + 651 + + 2021-11-01 + + + + file: + csharp/ql/lib/semmle/code/csharp/Callable.qll + + blame: + 804 + + 2023-01-09 + + + blame: + 824 + + 2023-01-09 + + + + file: + java/ql/lib/semmle/code/java/security/ExternalAPIs.qll + + blame: + 16 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 111 + + 2022-03-11 + + + blame: + 124 + + 2022-03-11 + + + blame: + 161 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UrlRedirect.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + + file: + python/ql/lib/semmle/python/security/injection/Deserialization.qll + + blame: + 5 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/falcon/Response.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 12 + + 2022-01-19 + + + blame: + 20 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + go/ql/lib/semmle/go/security/ReflectedXssCustomizations.qll + + blame: + 27 + + 2022-06-17 + + + blame: + 33 + + 2022-06-17 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll + + blame: + 35 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PolynomialReDoS.qll + + blame: + 8 + + 2022-03-21 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/RegExpInjectionCustomizations.qll + + blame: + 3 + + 2022-05-25 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll + + blame: + 21 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/frameworks/struts/StrutsXML.qll + + blame: + 9 + + 2022-03-11 + + + blame: + 55 + + 2022-03-11 + + + blame: + 70 + + 2022-03-11 + + + blame: + 80 + + 2022-03-11 + + + blame: + 120 + + 2022-03-11 + + + blame: + 145 + + 2022-03-11 + + + blame: + 196 + + 2022-03-11 + + + blame: + 210 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Expr.qll + + blame: + 19 + + 2022-01-20 + + + blame: + 26 + + 2021-11-09 + + + + file: + go/ql/lib/semmle/go/Util.qll + + blame: + 21 + + 2022-08-24 + + + + file: + java/ql/lib/semmle/code/java/frameworks/UnboundId.qll + + blame: + 33 + + 2022-03-11 + + + blame: + 69 + + 2022-08-24 + + + blame: + 80 + + 2022-08-24 + + + blame: + 107 + + 2022-03-11 + + + blame: + 118 + + 2022-03-11 + + + blame: + 130 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll + + blame: + 34 + + 2022-10-11 + + + blame: + 47 + + 2022-10-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UrlRedirectQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + java/ql/lib/semmle/code/java/security/performance/PolynomialReDoSQuery.qll + + blame: + 3 + + 2022-05-25 + + + + file: + python/ql/lib/semmle/python/security/dataflow/XpathInjectionQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + go/ql/lib/semmle/go/security/RequestForgeryCustomizations.qll + + blame: + 40 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/pointsto/PointsToContext.qll + + blame: + 125 + + 2022-09-06 + + + + file: + java/ql/lib/semmle/code/java/Annotation.qll + + blame: + 61 + + 2022-03-28 + + + blame: + 163 + + 2022-04-02 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll + + blame: + 9 + + 2022-08-18 + + + blame: + 16 + + 2022-08-18 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/RegExpInjectionQuery.qll + + blame: + 23 + + 2022-06-20 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/java/security/Encryption.qll + + blame: + 17 + + 2022-08-18 + + + blame: + 29 + + 2022-03-11 + + + blame: + 36 + + 2022-08-18 + + + blame: + 43 + + 2022-08-18 + + + blame: + 51 + + 2022-08-18 + + + blame: + 59 + + 2022-08-18 + + + blame: + 67 + + 2022-08-18 + + + blame: + 75 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UnsafeDeserialization.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/xml/MavenPom.qll + + blame: + 460 + + 2021-10-15 + + + blame: + 470 + + 2021-10-15 + + + blame: + 488 + + 2021-10-15 + + + + file: + ql/ql/src/codeql_ql/style/MisspellingQuery.qll + + blame: + 68 + + 2022-05-12 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll + + blame: + 74 + + 2022-03-30 + + + blame: + 93 + + 2022-03-30 + + + blame: + 175 + + 2022-03-30 + + + blame: + 190 + + 2022-03-30 + + + blame: + 295 + + 2022-03-30 + + + + file: + javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll + + blame: + 142 + + 2022-03-11 + + + blame: + 146 + + 2022-03-11 + + + blame: + 180 + + 2022-03-11 + + + blame: + 184 + + 2022-03-11 + + + blame: + 286 + + 2022-03-11 + + + blame: + 953 + + 2022-03-11 + + + blame: + 974 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/PrintAST.qll + + blame: + 31 + + 2022-03-11 + + + blame: + 241 + + 2022-03-11 + + + blame: + 284 + + 2022-03-11 + + + blame: + 288 + + 2022-03-11 + + + blame: + 298 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/Chevron.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 16 + + 2022-01-20 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll + + blame: + 367 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/security/ExternalAPIs.qll + + blame: + 20 + + 2022-08-18 + + + blame: + 109 + + 2022-08-18 + + + blame: + 159 + + 2022-08-18 + + + blame: + 171 + + 2022-08-18 + + + blame: + 183 + + 2022-08-18 + + + blame: + 196 + + 2022-08-18 + + + blame: + 234 + + 2022-08-18 + + + + file: + go/ql/lib/semmle/go/security/RequestForgery.qll + + blame: + 46 + + 2022-06-17 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/web/pyramid/View.qll + + blame: + 3 + + 2022-01-19 + + + blame: + 5 + + 2022-01-19 + + + blame: + 7 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/XML.qll + + blame: + 36 + + 2022-08-16 + + + blame: + 99 + + 2022-08-16 + + + blame: + 116 + + 2021-10-14 + + + blame: + 123 + + 2021-10-14 + + + blame: + 138 + + 2022-08-23 + + + blame: + 142 + + 2022-08-16 + + + blame: + 181 + + 2022-08-23 + + + blame: + 239 + + 2022-08-16 + + + blame: + 272 + + 2022-08-16 + + + blame: + 291 + + 2022-08-22 + + + blame: + 304 + + 2022-08-16 + + + blame: + 327 + + 2022-08-16 + + + blame: + 354 + + 2022-08-16 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll + + blame: + 12 + + 2022-03-01 + + + blame: + 15 + + 2022-03-01 + + + blame: + 29 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/security/ClearText.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + + file: + ql/ql/src/queries/style/LibraryAnnotation.ql + + blame: + 17 + + 2022-06-21 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll + + blame: + 80 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ReflectedXssQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + python/ql/src/experimental/semmle/python/Concepts.qll + + blame: + 94 + + 2022-03-11 + + + blame: + 110 + + 2022-03-11 + + + blame: + 129 + + 2022-03-11 + + + blame: + 145 + + 2022-03-11 + + + blame: + 172 + + 2022-08-18 + + + blame: + 177 + + 2022-03-11 + + + blame: + 202 + + 2022-08-18 + + + blame: + 206 + + 2022-03-11 + + + blame: + 225 + + 2022-03-11 + + + blame: + 241 + + 2022-03-11 + + + blame: + 258 + + 2022-03-11 + + + blame: + 272 + + 2022-03-11 + + + blame: + 289 + + 2022-03-11 + + + blame: + 303 + + 2022-03-11 + + + blame: + 454 + + 2022-03-11 + + + blame: + 485 + + 2022-03-11 + + + blame: + 529 + + 2022-03-11 + + + blame: + 570 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/frameworks/Rails.qll + + blame: + 60 + + 2022-10-14 + + + + file: + java/ql/lib/semmle/code/java/dataflow/FlowSources.qll + + blame: + 240 + + 2022-08-24 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll + + blame: + 95 + + 2021-10-14 + + + blame: + 104 + + 2021-10-14 + + + + file: + python/ql/src/experimental/semmle/python/templates/TRender.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 16 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LdapInjection.qll + + blame: + 10 + + 2022-03-21 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + java/ql/src/experimental/Security/CWE/CWE-611/XXELib.qll + + blame: + 193 + + 2022-03-11 + + + blame: + 211 + + 2022-03-11 + + + blame: + 241 + + 2022-03-11 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedStmt.qll + + blame: + 30 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Micro.qll + + blame: + 65 + + 2022-03-30 + + + blame: + 73 + + 2022-03-30 + + + + file: + python/ql/lib/semmle/python/web/django/Model.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 13 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + blame: + 41 + + 2022-01-19 + + + blame: + 58 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll + + blame: + 425 + + 2022-03-11 + + + blame: + 995 + + 2022-03-11 + + + blame: + 1007 + + 2022-03-11 + + + blame: + 1120 + + 2022-03-11 + + + blame: + 1139 + + 2022-09-09 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll + + blame: + 202 + + 2022-03-11 + + + blame: + 263 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-17 + + + blame: + 106 + + 2022-10-20 + + + blame: + 358 + + 2022-06-17 + + + blame: + 365 + + 2022-10-20 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll + + blame: + 50 + + 2022-03-11 + + + blame: + 78 + + 2022-03-11 + + + blame: + 84 + + 2022-03-11 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll + + blame: + 22 + + 2022-03-11 + + + blame: + 58 + + 2022-03-11 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/SafeExternalAPIFunction.qll + + blame: + 14 + + 2022-03-11 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll + + blame: + 27 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll + + blame: + 214 + + 2022-03-11 + + + blame: + 468 + + 2022-03-11 + + + + file: + java/ql/src/experimental/semmle/code/xml/StrutsXML.qll + + blame: + 14 + + 2022-03-11 + + + blame: + 29 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LogInjectionCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Next.qll + + blame: + 244 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll + + blame: + 7 + + 2022-01-20 + + + blame: + 15 + + 2022-01-20 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll + + blame: + 72 + + 2022-03-30 + + + blame: + 83 + + 2022-03-30 + + + blame: + 210 + + 2022-03-30 + + + blame: + 223 + + 2022-03-30 + + + blame: + 272 + + 2022-03-30 + + + blame: + 285 + + 2022-03-30 + + + blame: + 317 + + 2022-03-30 + + + blame: + 351 + + 2021-11-01 + + + blame: + 376 + + 2021-11-01 + + + blame: + 414 + + 2022-03-30 + + + blame: + 425 + + 2022-03-30 + + + blame: + 697 + + 2022-09-09 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-09-09 + + + blame: + 126 + + 2022-09-09 + + + blame: + 136 + + 2022-09-09 + + + blame: + 140 + + 2022-09-09 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll + + blame: + 74 + + 2022-03-11 + + + blame: + 109 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll + + blame: + 33 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll + + blame: + 727 + + 2021-10-14 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + ql/ql/src/queries/bugs/InconsistentDeprecation.ql + + blame: + 21 + + 2022-03-16 + + + blame: + 22 + + 2022-03-16 + + + blame: + 23 + + 2022-03-16 + + + blame: + 24 + + 2022-03-16 + + + + file: + ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll + + blame: + 29 + + 2022-10-04 + + + blame: + 34 + + 2022-10-04 + + + blame: + 95 + + 2022-10-18 + + + + file: + python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll + + blame: + 667 + + 2022-03-07 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Express.qll + + blame: + 62 + + 2022-03-30 + + + blame: + 74 + + 2019-04-03 + + + blame: + 155 + + 2022-04-28 + + + blame: + 181 + + 2022-03-30 + + + blame: + 192 + + 2022-03-30 + + + blame: + 302 + + 2022-03-30 + + + blame: + 308 + + 2022-03-30 + + + blame: + 311 + + 2022-03-30 + + + blame: + 314 + + 2022-03-30 + + + blame: + 317 + + 2022-03-30 + + + blame: + 322 + + 2022-03-30 + + + blame: + 330 + + 2022-03-30 + + + blame: + 335 + + 2022-03-30 + + + blame: + 588 + + 2022-03-30 + + + blame: + 603 + + 2022-03-30 + + + + file: + java/ql/lib/semmle/code/java/JDKAnnotations.qll + + blame: + 27 + + 2022-03-28 + + + blame: + 46 + + 2022-03-28 + + + blame: + 70 + + 2022-04-01 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll + + blame: + 8 + + 2022-08-18 + + + blame: + 15 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/web/stdlib/Request.qll + + blame: + 12 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + blame: + 43 + + 2022-01-19 + + + blame: + 66 + + 2022-01-19 + + + blame: + 73 + + 2022-01-19 + + + blame: + 118 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/security/XmlParsers.qll + + blame: + 338 + + 2022-08-18 + + + blame: + 372 + + 2022-03-11 + + + blame: + 394 + + 2022-03-11 + + + blame: + 424 + + 2022-03-11 + + + blame: + 442 + + 2022-03-11 + + + blame: + 458 + + 2022-03-11 + + + blame: + 466 + + 2022-03-11 + + + blame: + 486 + + 2022-03-11 + + + blame: + 500 + + 2022-03-11 + + + blame: + 536 + + 2022-03-11 + + + blame: + 583 + + 2022-03-11 + + + blame: + 594 + + 2022-03-11 + + + blame: + 614 + + 2022-03-11 + + + blame: + 628 + + 2022-03-11 + + + blame: + 671 + + 2022-03-11 + + + blame: + 680 + + 2022-03-11 + + + blame: + 701 + + 2022-03-11 + + + blame: + 715 + + 2022-03-11 + + + blame: + 739 + + 2022-03-11 + + + blame: + 782 + + 2022-03-11 + + + blame: + 826 + + 2022-03-11 + + + blame: + 839 + + 2022-03-11 + + + blame: + 862 + + 2022-03-11 + + + blame: + 876 + + 2022-03-11 + + + blame: + 895 + + 2022-03-11 + + + blame: + 925 + + 2022-08-18 + + + blame: + 1093 + + 2022-03-11 + + + blame: + 1218 + + 2022-03-11 + + + blame: + 1239 + + 2022-03-11 + + + blame: + 1257 + + 2022-03-11 + + + blame: + 1275 + + 2022-03-11 + + + + file: + cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql + + blame: + 27 + + 2019-10-11 + + + + file: + cpp/ql/test/library-tests/dataflow/fields/ASTConfiguration.qll + + blame: + 35 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll + + blame: + 308 + + 2022-09-07 + + + + file: + python/ql/lib/semmle/python/frameworks/Tornado.qll + + blame: + 68 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LdapInjectionCustomizations.qll + + blame: + 49 + + 2022-06-17 + + + blame: + 56 + + 2022-06-17 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll + + blame: + 124 + + 2022-09-09 + + + blame: + 126 + + 2022-09-09 + + + blame: + 136 + + 2022-09-09 + + + blame: + 140 + + 2022-09-09 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-17 + + + blame: + 126 + + 2022-06-17 + + + blame: + 136 + + 2022-10-20 + + + blame: + 140 + + 2022-10-20 + + + + file: + javascript/ql/src/Security/CWE-020/HostnameRegexpShared.qll + + blame: + 6 + + 2022-12-15 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll + + blame: + 425 + + 2022-03-11 + + + blame: + 995 + + 2022-03-11 + + + blame: + 1007 + + 2022-03-11 + + + blame: + 1120 + + 2022-03-11 + + + blame: + 1139 + + 2022-09-09 + + + + file: + ruby/ql/lib/codeql/ruby/security/PathInjectionCustomizations.qll + + blame: + 36 + + 2022-06-20 + + + + file: + python/ql/src/Imports/DeprecatedModule.ql + + blame: + 19 + + 2018-11-19 + + + blame: + 62 + + 2020-07-07 + + + blame: + 64 + + 2020-07-07 + + + blame: + 70 + + 2020-07-07 + + + blame: + 80 + + 2020-07-07 + + + + file: + csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll + + blame: + 166 + + 2021-12-13 + + + blame: + 169 + + 2021-12-13 + + + + file: + python/ql/lib/semmle/python/xml/XML.qll + + blame: + 36 + + 2022-08-16 + + + blame: + 99 + + 2022-08-16 + + + blame: + 116 + + 2021-10-14 + + + blame: + 123 + + 2021-10-14 + + + blame: + 138 + + 2022-08-23 + + + blame: + 142 + + 2022-08-16 + + + blame: + 181 + + 2022-08-23 + + + blame: + 239 + + 2022-08-16 + + + blame: + 272 + + 2022-08-16 + + + blame: + 291 + + 2022-08-22 + + + blame: + 304 + + 2022-08-16 + + + blame: + 327 + + 2022-08-16 + + + blame: + 354 + + 2022-08-16 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Parameter.qll + + blame: + 78 + + 2021-12-14 + + + blame: + 87 + + 2021-12-14 + + + + file: + python/ql/lib/semmle/python/security/regexp/NfaUtils.qll + + blame: + 12 + + 2022-11-01 + + + + file: + java/ql/lib/semmle/code/java/frameworks/javaee/PersistenceXML.qll + + blame: + 30 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll + + blame: + 138 + + 2022-08-24 + + + blame: + 324 + + 2022-08-18 + + + blame: + 336 + + 2022-08-18 + + + blame: + 361 + + 2022-08-24 + + + blame: + 459 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll + + blame: + 7 + + 2022-01-20 + + + blame: + 17 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/web/twisted/Twisted.qll + + blame: + 4 + + 2022-01-19 + + + blame: + 8 + + 2022-01-19 + + + blame: + 12 + + 2022-01-19 + + + blame: + 16 + + 2022-01-19 + + + blame: + 21 + + 2022-01-19 + + + blame: + 30 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/ApiGraphs.qll + + blame: + 156 + + 2022-05-30 + + + blame: + 159 + + 2022-05-30 + + + blame: + 162 + + 2022-05-30 + + + blame: + 165 + + 2022-05-30 + + + blame: + 411 + + 2022-09-02 + + + blame: + 414 + + 2022-09-02 + + + + file: + javascript/ql/lib/semmle/javascript/PrintAst.qll + + blame: + 395 + + 2022-03-11 + + + blame: + 413 + + 2022-03-11 + + + blame: + 421 + + 2022-03-11 + + + blame: + 439 + + 2022-03-11 + + + blame: + 447 + + 2022-03-11 + + + blame: + 586 + + 2022-03-11 + + + blame: + 659 + + 2022-03-11 + + + blame: + 675 + + 2022-03-11 + + + blame: + 708 + + 2022-03-11 + + + blame: + 712 + + 2022-03-11 + + + blame: + 745 + + 2022-03-11 + + + blame: + 761 + + 2022-03-11 + + + blame: + 789 + + 2022-03-11 + + + blame: + 817 + + 2022-03-11 + + + blame: + 842 + + 2022-03-11 + + + blame: + 867 + + 2022-03-11 + + + blame: + 871 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/SqlInjection.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + blame: + 16 + + 2022-03-21 + + + + file: + csharp/ql/src/experimental/ir/implementation/internal/TInstructionInternal.qll + + blame: + 7 + + 2022-08-18 + + + + file: + java/ql/lib/semmle/code/java/frameworks/Networking.qll + + blame: + 42 + + 2022-03-11 + + + + file: + python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll + + blame: + 37 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/web/django/Db.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 11 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 31 + + 2022-01-19 + + + blame: + 39 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/cherrypy/Response.qll + + blame: + 7 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/dataflow/SSA.qll + + blame: + 933 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstructionInternal.qll + + blame: + 7 + + 2022-08-18 + + + + file: + java/ql/lib/semmle/code/java/regex/RegexTreeView.qll + + blame: + 1201 + + 2022-11-23 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll + + blame: + 94 + + 2022-06-20 + + + blame: + 162 + + 2022-06-20 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll + + blame: + 39 + + 2021-10-14 + + + blame: + 79 + + 2021-10-14 + + + blame: + 190 + + 2021-10-14 + + + blame: + 215 + + 2021-10-14 + + + blame: + 243 + + 2021-10-14 + + + + file: + csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/Owin.qll + + blame: + 128 + + 2022-08-22 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll + + blame: + 51 + + 2022-06-17 + + + + file: + ruby/ql/src/queries/security/cwe-020/HostnameRegexpShared.qll + + blame: + 7 + + 2022-12-15 + + + + file: + python/ql/lib/semmle/python/pointsto/PointsTo.qll + + blame: + 1448 + + 2022-01-13 + + + blame: + 1492 + + 2022-01-13 + + + blame: + 1524 + + 2022-01-13 + + + blame: + 1548 + + 2022-01-13 + + + blame: + 1580 + + 2022-01-13 + + + blame: + 1606 + + 2022-01-13 + + + + file: + python/ql/lib/semmle/python/security/injection/Sql.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + blame: + 42 + + 2022-01-19 + + + blame: + 53 + + 2022-01-19 + + + blame: + 65 + + 2022-01-19 + + + blame: + 71 + + 2022-01-19 + + + + file: + python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql + + blame: + 25 + + 2022-01-20 + + + blame: + 29 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/security/regexp/RegexpMatching.qll + + blame: + 8 + + 2022-11-01 + + + + file: + csharp/ql/lib/semmle/code/dotnet/Element.qll + + blame: + 104 + + 2022-11-07 + + + + file: + python/ql/src/experimental/semmle/python/security/injection/XSLT.qll + + blame: + 22 + + 2022-08-18 + + + blame: + 27 + + 2022-01-20 + + + blame: + 121 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PathInjection.qll + + blame: + 9 + + 2022-03-21 + + + blame: + 14 + + 2022-03-21 + + + blame: + 29 + + 2022-03-21 + + + blame: + 53 + + 2022-03-21 + + + blame: + 65 + + 2022-03-21 + + + blame: + 86 + + 2022-03-21 + + + blame: + 110 + + 2022-03-21 + + + blame: + 129 + + 2022-03-21 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll + + blame: + 98 + + 2023-01-19 + + + blame: + 106 + + 2023-01-19 + + + blame: + 358 + + 2023-01-19 + + + blame: + 365 + + 2023-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/internal/CachedStages.qll + + blame: + 289 + + 2022-03-11 + + + + file: + javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/ATMConfig.qll + + blame: + 171 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/controlflow/internal/Preconditions.qll + + blame: + 14 + + 2022-03-22 + + + blame: + 113 + + 2022-03-31 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + go/ql/lib/semmle/go/security/SqlInjection.qll + + blame: + 35 + + 2022-06-17 + + + + file: + ruby/ql/lib/codeql/ruby/security/BadTagFilterQuery.qll + + blame: + 7 + + 2022-11-01 + + + + file: + ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll + + blame: + 121 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/web/django/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 23 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + blame: + 43 + + 2022-01-19 + + + blame: + 58 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/injection/Command.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 16 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 25 + + 2022-01-19 + + + blame: + 34 + + 2022-01-19 + + + blame: + 46 + + 2022-01-19 + + + blame: + 84 + + 2022-01-19 + + + blame: + 114 + + 2022-01-19 + + + blame: + 130 + + 2022-01-19 + + + blame: + 135 + + 2022-01-19 + + + blame: + 161 + + 2022-01-19 + + + blame: + 190 + + 2022-01-19 + + + blame: + 206 + + 2022-01-19 + + + blame: + 231 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll + + blame: + 452 + + 2022-03-30 + + + blame: + 458 + + 2022-03-30 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll + + blame: + 61 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 169 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll + + blame: + 98 + + 2023-01-06 + + + blame: + 106 + + 2023-01-06 + + + blame: + 358 + + 2023-01-06 + + + blame: + 365 + + 2023-01-06 + + + + file: + java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll + + blame: + 42 + + 2022-03-11 + + + + file: + ql/ql/src/queries/style/ConsistentCasing.ql + + blame: + 19 + + 2022-08-29 + + + + file: + csharp/ql/lib/semmle/code/cil/Instructions.qll + + blame: + 792 + + 2022-09-09 + + + blame: + 858 + + 2022-09-09 + + + + file: + ruby/ql/lib/codeql/ruby/security/StoredXSSQuery.qll + + blame: + 33 + + 2022-06-20 + + + blame: + 44 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/UrlRedirectCustomizations.qll + + blame: + 41 + + 2022-06-20 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll + + blame: + 8 + + 2022-03-11 + + + blame: + 77 + + 2022-03-11 + + + blame: + 105 + + 2022-03-11 + + + blame: + 133 + + 2022-03-11 + + + blame: + 173 + + 2022-03-11 + + + blame: + 206 + + 2022-03-11 + + + blame: + 234 + + 2022-03-11 + + + blame: + 260 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CleartextLogging.qll + + blame: + 12 + + 2022-03-21 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Literal.qll + + blame: + 174 + + 2022-01-20 + + + blame: + 219 + + 2022-01-20 + + + blame: + 266 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/web/tornado/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 33 + + 2022-01-19 + + + blame: + 41 + + 2022-01-19 + + + blame: + 55 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CleartextStorage.qll + + blame: + 12 + + 2022-03-21 + + + + file: + python/ql/lib/semmle/python/frameworks/internal/SubclassFinder.qll + + blame: + 77 + + 2022-07-18 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll + + blame: + 7 + + 2022-08-18 + + + blame: + 10 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/RegExpInjectionQuery.qll + + blame: + 3 + + 2022-05-25 + + + + file: + ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll + + blame: + 7 + + 2021-12-14 + + + + file: + ruby/ql/lib/codeql/ruby/security/CodeInjectionCustomizations.qll + + blame: + 55 + + 2022-06-20 + + + + file: + csharp/ql/lib/semmle/code/csharp/commons/StructuralComparison.qll + + blame: + 215 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/ApiGraphs.qll + + blame: + 159 + + 2022-05-30 + + + blame: + 162 + + 2022-05-30 + + + blame: + 165 + + 2022-05-30 + + + blame: + 168 + + 2022-05-30 + + + + file: + python/ql/lib/semmle/python/web/pyramid/Response.qll + + blame: + 11 + + 2022-01-19 + + + blame: + 24 + + 2022-01-19 + + + + file: + go/ql/lib/semmle/go/frameworks/NoSQL.qll + + blame: + 120 + + 2022-08-18 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll + + blame: + 124 + + 2022-04-20 + + + + file: + csharp/ql/lib/semmle/code/csharp/security/dataflow/ZipSlipQuery.qll + + blame: + 28 + + 2022-06-15 + + + blame: + 40 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/web/bottle/Redirect.qll + + blame: + 12 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/JSON.qll + + blame: + 65 + + 2022-03-11 + + + blame: + 89 + + 2022-03-11 + + + blame: + 105 + + 2022-03-11 + + + blame: + 122 + + 2022-03-11 + + + blame: + 139 + + 2022-03-11 + + + blame: + 155 + + 2022-03-11 + + + blame: + 174 + + 2022-03-11 + + + blame: + 193 + + 2022-03-11 + + + blame: + 205 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll + + blame: + 65 + + 2022-03-11 + + + blame: + 76 + + 2022-03-11 + + + blame: + 107 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/cherrypy/General.qll + + blame: + 4 + + 2022-01-19 + + + blame: + 8 + + 2022-01-19 + + + blame: + 16 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll + + blame: + 12 + + 2022-03-21 + + + blame: + 17 + + 2022-03-21 + + + + file: + swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll + + blame: + 204 + + 2022-06-20 + + + + file: + python/ql/src/experimental/Security/CWE-091/Xslt.ql + + blame: + 24 + + 2022-01-20 + + + blame: + 28 + + 2022-01-20 + + + + file: + go/ql/lib/semmle/go/security/CommandInjectionCustomizations.qll + + blame: + 37 + + 2022-06-17 + + + + file: + java/ql/lib/semmle/code/java/Expr.qll + + blame: + 507 + + 2023-01-10 + + + blame: + 517 + + 2023-01-10 + + + blame: + 527 + + 2023-01-10 + + + blame: + 615 + + 2022-05-16 + + + blame: + 710 + + 2021-10-29 + + + blame: + 797 + + 2023-01-10 + + + blame: + 807 + + 2023-01-10 + + + blame: + 817 + + 2023-01-10 + + + blame: + 1820 + + 2022-03-11 + + + + file: + javascript/ql/test/tutorials/Validating RAML-based APIs/RAML.qll + + blame: + 12 + + 2022-03-11 + + + blame: + 42 + + 2022-03-11 + + + blame: + 62 + + 2022-03-11 + + + + file: + python/ql/src/Security/CWE-020/HostnameRegexpShared.qll + + blame: + 7 + + 2022-12-15 + + + + file: + go/ql/lib/semmle/go/security/LogInjection.qll + + blame: + 29 + + 2022-06-17 + + + + file: + ruby/ql/lib/codeql/ruby/Regexp.qll + + blame: + 20 + + 2022-12-15 + + + blame: + 25 + + 2022-12-15 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Files.qll + + blame: + 254 + + 2022-03-11 + + + blame: + 272 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll + + blame: + 67 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll + + blame: + 67 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/Mako.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 16 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll + + blame: + 330 + + 2022-10-03 + + + + file: + ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll + + blame: + 12 + + 2022-02-15 + + + blame: + 17 + + 2022-02-15 + + + blame: + 22 + + 2022-02-15 + + + blame: + 27 + + 2022-02-15 + + + blame: + 32 + + 2022-02-15 + + + blame: + 37 + + 2022-02-15 + + + blame: + 42 + + 2022-02-15 + + + blame: + 47 + + 2022-02-15 + + + blame: + 52 + + 2022-02-15 + + + blame: + 57 + + 2022-02-15 + + + blame: + 62 + + 2022-02-15 + + + blame: + 67 + + 2022-02-15 + + + blame: + 72 + + 2022-02-15 + + + blame: + 77 + + 2022-02-15 + + + blame: + 82 + + 2022-02-15 + + + blame: + 87 + + 2022-02-15 + + + blame: + 92 + + 2022-02-15 + + + blame: + 97 + + 2022-02-15 + + + + file: + csharp/ql/lib/semmle/code/cil/Types.qll + + blame: + 64 + + 2022-01-14 + + + + file: + go/ql/lib/semmle/go/security/StringBreakCustomizations.qll + + blame: + 47 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/Stmt.qll + + blame: + 299 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll + + blame: + 13 + + 2022-04-04 + + + blame: + 22 + + 2022-04-04 + + + + file: + python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll + + blame: + 49 + + 2022-03-11 + + + blame: + 107 + + 2022-03-11 + + + blame: + 119 + + 2022-03-11 + + + blame: + 132 + + 2022-03-11 + + + blame: + 187 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryQuery.qll + + blame: + 31 + + 2022-06-20 + + + + file: + cpp/ql/lib/semmle/code/cpp/PODType03.qll + + blame: + 108 + + 2022-08-24 + + + blame: + 131 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/SSA.qll + + blame: + 752 + + 2022-09-09 + + + + file: + go/ql/lib/semmle/go/security/StoredXss.qll + + blame: + 34 + + 2022-06-17 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/RegExpInjectionCustomizations.qll + + blame: + 35 + + 2022-06-20 + + + + file: + javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll + + blame: + 12 + + 2022-11-01 + + + + file: + go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll + + blame: + 55 + + 2022-06-17 + + + + file: + go/ql/lib/semmle/go/security/UnsafeUnzipSymlinkCustomizations.qll + + blame: + 47 + + 2022-06-17 + + + blame: + 67 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/RegexInjectionCustomizations.qll + + blame: + 47 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll + + blame: + 253 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/PolynomialReDoSCustomizations.qll + + blame: + 3 + + 2022-05-25 + + + + file: + java/ql/lib/semmle/code/java/frameworks/camel/CamelJavaDSL.qll + + blame: + 47 + + 2022-08-18 + + + blame: + 51 + + 2022-08-24 + + + blame: + 78 + + 2022-08-24 + + + blame: + 108 + + 2022-08-24 + + + blame: + 143 + + 2022-08-24 + + + + file: + python/ql/src/experimental/semmle/python/templates/Genshi.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 13 + + 2022-01-20 + + + blame: + 23 + + 2022-01-20 + + + blame: + 42 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/web/tornado/Response.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 11 + + 2022-01-19 + + + blame: + 21 + + 2022-01-19 + + + blame: + 35 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CommandInjection.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-09-09 + + + blame: + 106 + + 2022-09-09 + + + blame: + 358 + + 2022-09-09 + + + blame: + 365 + + 2022-09-09 + + + + file: + python/ql/lib/semmle/python/security/injection/Marshal.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + go/ql/lib/semmle/go/security/OpenUrlRedirectCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll + + blame: + 427 + + 2022-03-13 + + + blame: + 1248 + + 2022-03-13 + + + + file: + python/ql/src/experimental/semmle/python/templates/Jinja.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 11 + + 2022-01-20 + + + blame: + 19 + + 2022-01-20 + + + blame: + 38 + + 2022-01-20 + + + + file: + ruby/ql/lib/codeql/ruby/security/ReflectedXSSQuery.qll + + blame: + 31 + + 2022-06-20 + + + blame: + 42 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/Files.qll + + blame: + 161 + + 2022-03-07 + + + + file: + javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll + + blame: + 3 + + 2022-11-22 + + + + file: + go/ql/lib/semmle/go/security/Xss.qll + + blame: + 13 + + 2022-09-19 + + + blame: + 42 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/dataflow/new/BarrierGuards.qll + + blame: + 43 + + 2022-06-17 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-09-09 + + + blame: + 126 + + 2022-09-09 + + + blame: + 136 + + 2022-09-09 + + + blame: + 140 + + 2022-09-09 + + + + file: + java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll + + blame: + 34 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll + + blame: + 48 + + 2021-10-07 + + + blame: + 107 + + 2021-10-07 + + + + file: + java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBJarXML.qll + + blame: + 39 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll + + blame: + 20 + + 2022-04-04 + + + blame: + 26 + + 2022-04-04 + + + blame: + 29 + + 2022-04-04 + + + + file: + python/ql/lib/semmle/python/security/injection/Yaml.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/types/Extensions.qll + + blame: + 56 + + 2022-01-20 + + + + file: + ruby/ql/lib/codeql/ruby/security/UrlRedirectQuery.qll + + blame: + 26 + + 2022-06-20 + + + + file: + python/ql/lib/semmle/python/security/injection/Path.qll + + blame: + 9 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + blame: + 33 + + 2022-01-19 + + + blame: + 38 + + 2022-01-19 + + + blame: + 48 + + 2022-01-19 + + + blame: + 62 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Control.qll + + blame: + 388 + + 2021-12-21 + + + blame: + 391 + + 2021-12-21 + + + blame: + 419 + + 2021-12-21 + + + + file: + java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll + + blame: + 60 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/security/LogInjectionCustomizations.qll + + blame: + 33 + + 2022-06-17 + + + + file: + go/ql/lib/semmle/go/security/OpenUrlRedirect.qll + + blame: + 62 + + 2022-06-17 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll + + blame: + 61 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 169 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll + + blame: + 3 + + 2022-11-22 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll + + blame: + 95 + + 2021-10-14 + + + blame: + 104 + + 2021-10-14 + + + + file: + python/ql/lib/semmle/python/web/HttpConstants.qll + + blame: + 2 + + 2022-01-19 + + + blame: + 7 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/django/Response.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 13 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + blame: + 39 + + 2022-01-19 + + + blame: + 56 + + 2022-01-19 + + + blame: + 69 + + 2022-01-19 + + + + file: + cpp/ql/src/Security/CWE/CWE-497/SystemData.qll + + blame: + 59 + + 2022-08-18 + + + blame: + 81 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/web/Http.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 13 + + 2022-01-19 + + + blame: + 46 + + 2022-01-19 + + + blame: + 56 + + 2022-01-19 + + + blame: + 65 + + 2022-01-19 + + + blame: + 74 + + 2022-01-19 + + + blame: + 76 + + 2022-01-19 + + + blame: + 79 + + 2022-01-19 + + + blame: + 83 + + 2022-01-19 + + + blame: + 87 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/TypeScript.qll + + blame: + 15 + + 2021-11-01 + + + blame: + 197 + + 2021-11-01 + + + + file: + python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll + + blame: + 45 + + 2022-03-11 + + + blame: + 57 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll + + blame: + 95 + + 2021-10-14 + + + blame: + 104 + + 2021-10-14 + + + + file: + python/ql/lib/semmle/python/objects/TObject.qll + + blame: + 337 + + 2022-09-06 + + + blame: + 360 + + 2022-09-06 + + + + file: + go/ql/lib/semmle/go/frameworks/Stdlib.qll + + blame: + 269 + + 2022-09-09 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll + + blame: + 25 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/ast/internal/AST.qll + + blame: + 878 + + 2021-12-14 + + + blame: + 884 + + 2021-12-14 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll + + blame: + 423 + + 2022-06-17 + + + blame: + 433 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll + + blame: + 55 + + 2022-06-17 + + + + file: + javascript/ql/src/experimental/semmle/javascript/Actions.qll + + blame: + 2 + + 2022-05-03 + + + + file: + python/ql/lib/semmle/python/web/flask/Redirect.qll + + blame: + 12 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/twisted/Response.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 28 + + 2022-01-19 + + + + file: + go/ql/lib/semmle/go/dataflow/barrierguardutil/UrlCheck.qll + + blame: + 44 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll + + blame: + 61 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 169 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll + + blame: + 819 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll + + blame: + 43 + + 2022-03-11 + + + blame: + 87 + + 2022-03-11 + + + + file: + python/tools/recorded-call-graph-metrics/ql/lib/RecordedCalls.qll + + blame: + 14 + + 2022-08-16 + + + blame: + 23 + + 2022-08-16 + + + blame: + 61 + + 2022-03-11 + + + blame: + 114 + + 2022-03-11 + + + blame: + 120 + + 2022-03-11 + + + blame: + 144 + + 2022-03-11 + + + blame: + 165 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll + + blame: + 79 + + 2022-05-24 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll + + blame: + 124 + + 2022-11-25 + + + blame: + 167 + + 2022-11-25 + + + blame: + 173 + + 2022-11-25 + + + blame: + 184 + + 2022-11-25 + + + blame: + 188 + + 2022-11-25 + + + blame: + 329 + + 2022-11-25 + + + blame: + 358 + + 2022-11-25 + + + blame: + 400 + + 2022-11-25 + + + blame: + 415 + + 2022-11-25 + + + blame: + 546 + + 2022-11-25 + + + blame: + 553 + + 2022-11-25 + + + blame: + 584 + + 2022-11-25 + + + blame: + 593 + + 2022-11-25 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-17 + + + blame: + 106 + + 2022-10-20 + + + blame: + 358 + + 2022-06-17 + + + blame: + 365 + + 2022-10-20 + + + + file: + python/ql/lib/semmle/python/security/strings/Untrusted.qll + + blame: + 8 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + ql/ql/src/queries/bugs/MissingSanitizerGuardCase.ql + + blame: + 27 + + 2022-09-12 + + + + file: + ql/ql/src/codeql_ql/style/AcronymsShouldBeCamelCaseQuery.qll + + blame: + 37 + + 2022-03-03 + + + + file: + java/ql/lib/semmle/code/java/security/performance/SuperlinearBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/IRConstruction.qll + + blame: + 383 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/webob/Request.qll + + blame: + 5 + + 2022-01-19 + + + blame: + 34 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll + + blame: + 7 + + 2022-11-01 + + + + file: + python/ql/src/experimental/semmle/python/frameworks/Django.qll + + blame: + 32 + + 2022-08-24 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedFunction.qll + + blame: + 34 + + 2022-03-11 + + + blame: + 291 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/JSX.qll + + blame: + 34 + + 2022-03-11 + + + blame: + 79 + + 2022-03-11 + + + blame: + 83 + + 2022-03-11 + + + blame: + 107 + + 2022-03-11 + + + blame: + 156 + + 2022-03-11 + + + blame: + 177 + + 2022-03-11 + + + blame: + 203 + + 2022-03-11 + + + blame: + 246 + + 2022-03-11 + + + blame: + 262 + + 2022-03-11 + + + blame: + 283 + + 2022-03-11 + + + blame: + 287 + + 2022-03-11 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedElement.qll + + blame: + 24 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/SSTISink.qll + + blame: + 7 + + 2022-01-20 + + + + file: + python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql + + blame: + 15 + + 2021-03-09 + + + blame: + 29 + + 2021-03-10 + + + + file: + csharp/ql/lib/semmle/code/csharp/security/cryptography/EncryptionKeyDataFlowQuery.qll + + blame: + 9 + + 2022-09-27 + + + + file: + javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoS.qll + + blame: + 7 + + 2022-05-25 + + + + file: + java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll + + blame: + 67 + + 2022-11-01 + + + + file: + java/ql/lib/semmle/code/java/frameworks/gwt/GWT.qll + + blame: + 103 + + 2022-08-18 + + + blame: + 116 + + 2022-08-18 + + + + file: + python/ql/lib/semmle/python/web/falcon/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 31 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/tainttracking3/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll + + blame: + 101 + + 2022-03-11 + + + blame: + 149 + + 2022-04-20 + + + blame: + 157 + + 2022-04-20 + + + blame: + 165 + + 2022-04-20 + + + blame: + 173 + + 2022-04-20 + + + blame: + 181 + + 2022-04-20 + + + + file: + cpp/ql/lib/semmle/code/cpp/commons/NULL.qll + + blame: + 9 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll + + blame: + 43 + + 2022-03-11 + + + blame: + 66 + + 2022-03-11 + + + blame: + 109 + + 2022-03-11 + + + blame: + 121 + + 2022-03-11 + + + blame: + 143 + + 2022-03-11 + + + blame: + 170 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/tornado/Tornado.qll + + blame: + 5 + + 2022-01-19 + + + blame: + 9 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + blame: + 33 + + 2022-01-19 + + + blame: + 37 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/bottle/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 9 + + 2022-01-19 + + + blame: + 24 + + 2022-01-19 + + + blame: + 30 + + 2022-01-19 + + + blame: + 51 + + 2022-01-19 + + + blame: + 63 + + 2022-01-19 + + + blame: + 72 + + 2022-01-19 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CodeInjectionQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LdapInjectionQuery.qll + + blame: + 29 + + 2022-06-17 + + + blame: + 47 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll + + blame: + 46 + + 2021-07-02 + + + + file: + cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll + + blame: + 83 + + 2021-10-14 + + + + file: + python/ql/src/experimental/semmle/python/frameworks/LDAP.qll + + blame: + 129 + + 2022-08-22 + + + blame: + 224 + + 2022-08-22 + + + + file: + python/ql/lib/semmle/python/web/django/Shared.qll + + blame: + 4 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + blame: + 50 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll + + blame: + 81 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/client/StdLib.qll + + blame: + 4 + + 2022-01-19 + + + blame: + 21 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll + + blame: + 67 + + 2022-11-01 + + + + file: + java/ql/lib/semmle/code/java/deadcode/SpringEntryPoints.qll + + blame: + 118 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/XML.qll + + blame: + 36 + + 2022-08-16 + + + blame: + 99 + + 2022-08-16 + + + blame: + 116 + + 2021-10-14 + + + blame: + 123 + + 2021-10-14 + + + blame: + 138 + + 2022-08-23 + + + blame: + 142 + + 2022-08-16 + + + blame: + 181 + + 2022-08-23 + + + blame: + 239 + + 2022-08-16 + + + blame: + 272 + + 2022-08-16 + + + blame: + 291 + + 2022-08-22 + + + blame: + 304 + + 2022-08-16 + + + blame: + 327 + + 2022-08-16 + + + blame: + 354 + + 2022-08-16 + + + + file: + csharp/ql/src/experimental/ir/implementation/internal/TOperand.qll + + blame: + 63 + + 2022-03-11 + + + blame: + 73 + + 2022-03-11 + + + blame: + 161 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Koa.qll + + blame: + 52 + + 2022-03-30 + + + blame: + 69 + + 2022-03-30 + + + blame: + 86 + + 2022-03-30 + + + blame: + 280 + + 2022-03-30 + + + blame: + 286 + + 2022-03-30 + + + blame: + 307 + + 2022-03-30 + + + blame: + 322 + + 2022-03-30 + + + + file: + ruby/ql/lib/codeql/ruby/ast/Constant.qll + + blame: + 84 + + 2022-03-24 + + + blame: + 87 + + 2022-03-24 + + + blame: + 406 + + 2021-12-22 + + + + file: + go/ql/lib/semmle/go/security/SqlInjectionCustomizations.qll + + blame: + 33 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll + + blame: + 1153 + + 2022-06-16 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll + + blame: + 50 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/web/django/Redirect.qll + + blame: + 16 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + + file: + java/ql/src/Telemetry/ExternalApi.qll + + blame: + 99 + + 2022-03-29 + + + + file: + java/ql/src/semmle/code/xml/MyBatisMapperXML.qll + + blame: + 18 + + 2022-03-11 + + + blame: + 40 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/concepts/HTTP.qll + + blame: + 351 + + 2022-09-09 + + + + file: + python/ql/lib/semmle/python/web/pyramid/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 14 + + 2022-01-19 + + + + file: + python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql + + blame: + 33 + + 2019-02-26 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll + + blame: + 139 + + 2022-03-11 + + + blame: + 578 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll + + blame: + 242 + + 2022-03-11 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll + + blame: + 33 + + 2022-06-20 + + + + file: + ruby/ql/lib/codeql/ruby/security/XSS.qll + + blame: + 44 + + 2022-06-20 + + + blame: + 246 + + 2022-03-11 + + + blame: + 269 + + 2022-06-20 + + + blame: + 277 + + 2022-03-11 + + + blame: + 288 + + 2022-03-11 + + + blame: + 326 + + 2022-06-20 + + + blame: + 334 + + 2022-03-11 + + + blame: + 351 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/xml/WebXML.qll + + blame: + 9 + + 2022-03-11 + + + blame: + 35 + + 2022-03-11 + + + blame: + 50 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ReflectedXSS.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + blame: + 16 + + 2022-03-21 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll + + blame: + 627 + + 2022-03-30 + + + blame: + 633 + + 2022-03-30 + + + blame: + 636 + + 2022-03-30 + + + blame: + 639 + + 2022-03-30 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll + + blame: + 56 + + 2022-03-11 + + + blame: + 214 + + 2022-03-11 + + + blame: + 321 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/BadTagFilterQuery.qll + + blame: + 7 + + 2022-11-22 + + + + file: + python/ql/src/experimental/semmle/python/security/InsecureRandomnessCustomizations.qll + + blame: + 37 + + 2022-06-17 + + + + file: + csharp/ql/lib/semmle/code/csharp/exprs/BitwiseOperation.qll + + blame: + 51 + + 2023-01-06 + + + blame: + 63 + + 2023-01-06 + + + + file: + javascript/ql/src/LanguageFeatures/ExpressionClosures.ql + + blame: + 21 + + 2022-03-11 + + + blame: + 42 + + 2018-08-02 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/ir/SafeExternalAPIFunction.qll + + blame: + 14 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/Regexp.qll + + blame: + 1009 + + 2022-12-15 + + + blame: + 1014 + + 2022-12-15 + + + blame: + 1023 + + 2022-08-24 + + + blame: + 1026 + + 2022-08-24 + + + + file: + java/ql/lib/semmle/code/java/frameworks/Servlets.qll + + blame: + 132 + + 2022-03-11 + + + blame: + 146 + + 2022-08-18 + + + blame: + 343 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll + + blame: + 9 + + 2022-08-18 + + + blame: + 16 + + 2022-08-18 + + + + file: + java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll + + blame: + 61 + + 2022-08-24 + + + blame: + 83 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + blame: + 81 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/BadTagFilterQuery.qll + + blame: + 7 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/security/strings/Common.qll + + blame: + 4 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/flask/General.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 9 + + 2022-01-19 + + + blame: + 11 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + blame: + 38 + + 2022-01-19 + + + blame: + 54 + + 2022-01-19 + + + blame: + 61 + + 2022-01-19 + + + blame: + 71 + + 2022-01-19 + + + blame: + 76 + + 2022-01-19 + + + blame: + 94 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/injection/Pickle.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + blame: + 25 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/tools/recorded-call-graph-metrics/ql/lib/BytecodeExpr.qll + + blame: + 6 + + 2022-03-11 + + + blame: + 15 + + 2022-03-11 + + + blame: + 24 + + 2022-03-11 + + + blame: + 35 + + 2022-03-11 + + + blame: + 46 + + 2022-03-11 + + + blame: + 57 + + 2022-03-11 + + + blame: + 68 + + 2022-03-11 + + + blame: + 77 + + 2022-03-11 + + + blame: + 86 + + 2022-03-11 + + + blame: + 97 + + 2022-03-11 + + + blame: + 106 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/JsonStringifiers.qll + + blame: + 63 + + 2022-08-24 + + + blame: + 82 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + csharp/ql/lib/semmle/code/csharp/exprs/Access.qll + + blame: + 177 + + 2022-10-12 + + + blame: + 205 + + 2022-10-12 + + + blame: + 247 + + 2022-10-12 + + + blame: + 302 + + 2022-10-12 + + + blame: + 447 + + 2022-10-12 + + + blame: + 588 + + 2022-10-12 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Restify.qll + + blame: + 79 + + 2022-03-30 + + + blame: + 94 + + 2022-03-30 + + + + file: + java/ql/lib/semmle/code/java/security/performance/ExponentialBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + java/ql/src/Advisory/Deprecated Code/AvoidDeprecatedCallableAccess.ql + + blame: + 18 + + 2018-08-30 + + + blame: + 25 + + 2018-08-30 + + + blame: + 27 + + 2018-10-10 + + + + file: + go/ql/lib/semmle/go/security/StoredXssCustomizations.qll + + blame: + 24 + + 2022-06-17 + + + blame: + 30 + + 2022-06-17 + + + + file: + cpp/ql/lib/semmle/code/cpp/controlflow/SSA.qll + + blame: + 18 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/security/CommandInjection.qll + + blame: + 37 + + 2022-06-17 + + + blame: + 100 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/XpathInjection.qll + + blame: + 8 + + 2022-03-21 + + + + file: + go/ql/lib/semmle/go/security/AllocationSizeOverflowCustomizations.qll + + blame: + 32 + + 2022-06-17 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll + + blame: + 61 + + 2022-03-11 + + + blame: + 99 + + 2022-03-11 + + + blame: + 169 + + 2022-03-11 + + + + file: + swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/java/frameworks/spring/SpringCamel.qll + + blame: + 17 + + 2022-03-11 + + + blame: + 29 + + 2022-03-11 + + + blame: + 42 + + 2022-03-11 + + + blame: + 62 + + 2022-03-11 + + + blame: + 75 + + 2022-03-11 + + + blame: + 102 + + 2022-03-11 + + + blame: + 120 + + 2022-08-18 + + + blame: + 124 + + 2022-03-11 + + + blame: + 152 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll + + blame: + 50 + + 2022-03-11 + + + blame: + 78 + + 2022-03-11 + + + blame: + 84 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/ExponentialBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll + + blame: + 71 + + 2022-03-11 + + + blame: + 466 + + 2022-03-11 + + + blame: + 501 + + 2022-03-11 + + + blame: + 541 + + 2022-03-11 + + + blame: + 579 + + 2022-03-11 + + + blame: + 650 + + 2022-03-11 + + + blame: + 698 + + 2022-03-11 + + + blame: + 785 + + 2022-03-11 + + + blame: + 811 + + 2022-03-11 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll + + blame: + 1415 + + 2022-09-09 + + + + file: + javascript/ql/lib/semmle/javascript/security/regexp/RegexpMatching.qll + + blame: + 8 + + 2022-11-22 + + + + file: + ql/ql/src/codeql_ql/style/DeadCodeQuery.qll + + blame: + 191 + + 2022-03-11 + + + blame: + 192 + + 2022-03-11 + + + blame: + 194 + + 2022-03-11 + + + blame: + 196 + + 2022-03-11 + + + blame: + 198 + + 2022-03-11 + + + blame: + 235 + + 2022-03-13 + + + blame: + 271 + + 2022-03-13 + + + + file: + python/ql/lib/semmle/python/web/twisted/Request.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 24 + + 2022-01-19 + + + + file: + ql/ql/src/codeql_ql/style/TypoDatabase.qll + + blame: + 4 + + 2022-09-08 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll + + blame: + 214 + + 2022-03-11 + + + blame: + 468 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/bottle/General.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 9 + + 2022-01-19 + + + blame: + 15 + + 2022-01-19 + + + blame: + 27 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/GWT.qll + + blame: + 15 + + 2022-08-24 + + + blame: + 36 + + 2022-08-24 + + + blame: + 40 + + 2022-08-24 + + + blame: + 50 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll + + blame: + 655 + + 2022-06-23 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + csharp/ql/lib/experimental/code/csharp/Cryptography/NonCryptographicHashes.qll + + blame: + 43 + + 2022-08-24 + + + + file: + ql/ql/src/codeql_ql/ast/Ast.qll + + blame: + 2585 + + 2022-08-24 + + + blame: + 2597 + + 2022-03-11 + + + blame: + 2627 + + 2022-03-11 + + + blame: + 2666 + + 2022-03-11 + + + blame: + 2683 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/Crypto.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 11 + + 2022-01-19 + + + blame: + 61 + + 2022-01-19 + + + blame: + 131 + + 2022-01-19 + + + + file: + cpp/ql/src/Microsoft/SAL.qll + + blame: + 26 + + 2022-08-24 + + + blame: + 54 + + 2022-08-24 + + + blame: + 67 + + 2022-08-24 + + + blame: + 93 + + 2022-08-24 + + + blame: + 109 + + 2022-08-24 + + + blame: + 128 + + 2022-08-24 + + + blame: + 203 + + 2022-08-24 + + + + file: + javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll + + blame: + 3 + + 2022-11-22 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll + + blame: + 889 + + 2022-06-16 + + + + file: + javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll + + blame: + 1159 + + 2022-03-30 + + + blame: + 1175 + + 2022-03-30 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-09-09 + + + blame: + 106 + + 2022-09-09 + + + blame: + 358 + + 2022-09-09 + + + blame: + 365 + + 2022-09-09 + + + + file: + cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll + + blame: + 45 + + 2022-03-11 + + + blame: + 62 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/turbogears/Request.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 15 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Testing.qll + + blame: + 41 + + 2022-08-24 + + + + file: + csharp/ql/lib/semmle/code/csharp/Assignable.qll + + blame: + 128 + + 2022-10-12 + + + blame: + 499 + + 2022-10-12 + + + + file: + java/ql/lib/semmle/code/java/frameworks/spring/SpringComponentScan.qll + + blame: + 27 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/security/regexp/SuperlinearBackTracking.qll + + blame: + 40 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/security/strings/External.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 33 + + 2022-01-19 + + + blame: + 41 + + 2022-01-19 + + + blame: + 64 + + 2022-01-19 + + + blame: + 72 + + 2022-01-19 + + + blame: + 77 + + 2022-01-19 + + + blame: + 100 + + 2022-01-19 + + + blame: + 124 + + 2022-01-19 + + + blame: + 132 + + 2022-01-19 + + + blame: + 137 + + 2022-01-19 + + + blame: + 156 + + 2022-01-19 + + + blame: + 175 + + 2022-01-19 + + + blame: + 186 + + 2020-07-07 + + + blame: + 201 + + 2022-01-19 + + + blame: + 212 + + 2020-07-07 + + + blame: + 228 + + 2022-01-19 + + + blame: + 256 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/frameworks/ActionView.qll + + blame: + 17 + + 2022-10-04 + + + blame: + 22 + + 2022-10-04 + + + blame: + 27 + + 2022-10-04 + + + blame: + 32 + + 2022-10-04 + + + + file: + python/ql/src/experimental/semmle/python/templates/Bottle.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 18 + + 2022-01-20 + + + blame: + 37 + + 2022-01-20 + + + + file: + csharp/ql/lib/semmle/code/asp/WebConfig.qll + + blame: + 15 + + 2022-03-11 + + + blame: + 23 + + 2022-03-11 + + + blame: + 34 + + 2022-03-11 + + + blame: + 49 + + 2022-03-11 + + + blame: + 64 + + 2022-03-11 + + + blame: + 75 + + 2022-03-11 + + + blame: + 86 + + 2022-03-11 + + + blame: + 102 + + 2022-08-22 + + + blame: + 110 + + 2022-08-22 + + + blame: + 137 + + 2022-08-22 + + + blame: + 150 + + 2022-08-22 + + + + file: + java/ql/lib/semmle/code/java/NumberFormatException.qll + + blame: + 38 + + 2022-08-24 + + + blame: + 59 + + 2022-08-24 + + + blame: + 77 + + 2022-08-24 + + + blame: + 85 + + 2022-08-24 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ChainedConfigs12.qll + + blame: + 37 + + 2022-01-31 + + + blame: + 76 + + 2022-01-31 + + + blame: + 89 + + 2022-01-31 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll + + blame: + 486 + + 2022-03-11 + + + + file: + cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll + + blame: + 98 + + 2022-09-09 + + + blame: + 106 + + 2022-09-09 + + + blame: + 358 + + 2022-09-09 + + + blame: + 365 + + 2022-09-09 + + + + file: + ruby/ql/lib/codeql/ruby/Concepts.qll + + blame: + 688 + + 2022-08-18 + + + blame: + 697 + + 2022-08-18 + + + blame: + 722 + + 2022-03-22 + + + blame: + 731 + + 2022-08-18 + + + blame: + 747 + + 2022-09-09 + + + blame: + 914 + + 2022-08-18 + + + blame: + 934 + + 2022-08-18 + + + blame: + 1042 + + 2022-05-23 + + + blame: + 1056 + + 2022-05-23 + + + + file: + java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll + + blame: + 25 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/AST.qll + + blame: + 188 + + 2022-03-11 + + + blame: + 343 + + 2022-03-11 + + + + file: + csharp/ql/lib/semmle/code/csharp/security/dataflow/UrlRedirectQuery.qll + + blame: + 33 + + 2022-06-15 + + + blame: + 47 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/web/flask/Request.qll + + blame: + 6 + + 2022-01-19 + + + blame: + 9 + + 2022-01-19 + + + blame: + 15 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + blame: + 42 + + 2022-01-19 + + + blame: + 60 + + 2022-01-19 + + + blame: + 75 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll + + blame: + 44 + + 2022-03-11 + + + blame: + 104 + + 2021-09-13 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll + + blame: + 94 + + 2022-03-30 + + + blame: + 109 + + 2022-03-30 + + + blame: + 258 + + 2022-03-30 + + + + file: + python/ql/lib/semmle/python/security/regexp/SuperlinearBackTracking.qll + + blame: + 40 + + 2022-11-01 + + + + file: + javascript/ql/src/Declarations/Definitions.qll + + blame: + 7 + + 2022-03-13 + + + + file: + shared/ssa/codeql/ssa/Ssa.qll + + blame: + 737 + + 2022-11-01 + + + blame: + 744 + + 2022-11-01 + + + blame: + 766 + + 2022-11-01 + + + blame: + 833 + + 2022-11-01 + + + blame: + 846 + + 2022-11-01 + + + blame: + 909 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/web/django/General.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + blame: + 39 + + 2022-01-19 + + + blame: + 47 + + 2022-01-19 + + + blame: + 60 + + 2022-01-19 + + + blame: + 73 + + 2022-01-19 + + + blame: + 77 + + 2022-01-19 + + + blame: + 112 + + 2022-01-19 + + + + file: + go/ql/lib/semmle/go/security/AllocationSizeOverflow.qll + + blame: + 26 + + 2022-06-17 + + + blame: + 67 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll + + blame: + 37 + + 2022-06-17 + + + blame: + 68 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/web/pyramid/Redirect.qll + + blame: + 12 + + 2022-01-19 + + + blame: + 23 + + 2022-01-19 + + + + file: + go/ql/lib/semmle/go/security/ZipSlipCustomizations.qll + + blame: + 35 + + 2022-06-17 + + + + file: + python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll + + blame: + 33 + + 2022-03-11 + + + blame: + 40 + + 2022-03-11 + + + blame: + 47 + + 2022-03-11 + + + blame: + 60 + + 2022-03-11 + + + blame: + 77 + + 2022-03-11 + + + blame: + 93 + + 2022-03-11 + + + blame: + 107 + + 2022-03-11 + + + blame: + 130 + + 2022-03-11 + + + + file: + cpp/ql/test/library-tests/dataflow/fields/Nodes.qll + + blame: + 17 + + 2022-03-11 + + + blame: + 32 + + 2022-03-11 + + + blame: + 38 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/bottle/Response.qll + + blame: + 12 + + 2022-01-19 + + + blame: + 16 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 29 + + 2022-01-19 + + + blame: + 42 + + 2022-01-19 + + + + file: + csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll + + blame: + 95 + + 2021-10-14 + + + blame: + 104 + + 2021-10-14 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/frameworks/Django.qll + + blame: + 538 + + 2022-03-11 + + + blame: + 556 + + 2022-03-11 + + + blame: + 575 + + 2022-03-11 + + + blame: + 823 + + 2022-03-11 + + + blame: + 863 + + 2022-03-11 + + + blame: + 1103 + + 2022-03-11 + + + blame: + 1127 + + 2022-03-11 + + + blame: + 1132 + + 2022-03-11 + + + blame: + 1159 + + 2022-09-09 + + + blame: + 1170 + + 2022-03-11 + + + blame: + 1332 + + 2022-03-11 + + + blame: + 2185 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/security/ZipSlip.qll + + blame: + 29 + + 2022-06-17 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + python/ql/src/experimental/semmle/python/templates/Airspeed.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 16 + + 2022-01-20 + + + + file: + ql/ql/src/queries/style/docs/ClassDocs.ql + + blame: + 26 + + 2022-08-15 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll + + blame: + 687 + + 2022-06-20 + + + + file: + ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll + + blame: + 7 + + 2022-11-01 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/PolynomialReDoSQuery.qll + + blame: + 3 + + 2022-05-25 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Vue.qll + + blame: + 194 + + 2022-05-23 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll + + blame: + 12 + + 2022-11-25 + + + blame: + 14 + + 2022-11-25 + + + blame: + 16 + + 2022-11-25 + + + blame: + 19 + + 2022-11-25 + + + blame: + 21 + + 2022-11-25 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/pointsto/Base.qll + + blame: + 16 + + 2022-09-06 + + + blame: + 30 + + 2022-09-06 + + + blame: + 36 + + 2022-09-06 + + + blame: + 48 + + 2022-09-06 + + + blame: + 62 + + 2022-09-06 + + + blame: + 72 + + 2022-09-06 + + + blame: + 82 + + 2022-09-06 + + + blame: + 92 + + 2022-09-06 + + + blame: + 105 + + 2022-09-06 + + + blame: + 116 + + 2022-09-06 + + + blame: + 125 + + 2022-09-06 + + + blame: + 163 + + 2022-09-06 + + + blame: + 175 + + 2022-09-06 + + + blame: + 191 + + 2022-09-06 + + + blame: + 213 + + 2022-09-06 + + + blame: + 229 + + 2022-09-06 + + + blame: + 254 + + 2022-09-06 + + + blame: + 260 + + 2022-09-06 + + + blame: + 274 + + 2022-09-06 + + + blame: + 336 + + 2022-09-06 + + + blame: + 354 + + 2022-09-06 + + + blame: + 366 + + 2022-09-06 + + + blame: + 372 + + 2022-09-06 + + + + file: + python/ql/lib/semmle/python/security/dataflow/RegexInjection.qll + + blame: + 8 + + 2022-03-21 + + + + file: + python/ql/src/Functions/DeprecatedSliceMethod.ql + + blame: + 24 + + 2022-10-07 + + + + file: + javascript/ql/lib/semmle/javascript/YAML.qll + + blame: + 93 + + 2022-08-24 + + + blame: + 111 + + 2022-08-24 + + + blame: + 160 + + 2022-08-24 + + + blame: + 182 + + 2022-08-24 + + + blame: + 204 + + 2022-08-24 + + + blame: + 225 + + 2022-08-24 + + + blame: + 246 + + 2022-08-24 + + + blame: + 262 + + 2022-08-24 + + + blame: + 278 + + 2022-08-24 + + + blame: + 295 + + 2022-08-24 + + + blame: + 327 + + 2022-08-24 + + + blame: + 351 + + 2022-08-24 + + + blame: + 408 + + 2022-08-24 + + + blame: + 436 + + 2022-08-24 + + + blame: + 462 + + 2022-08-24 + + + blame: + 480 + + 2022-08-24 + + + blame: + 494 + + 2022-08-24 + + + blame: + 568 + + 2022-08-24 + + + + file: + java/ql/lib/semmle/code/java/frameworks/Camel.qll + + blame: + 21 + + 2022-08-18 + + + blame: + 58 + + 2022-08-18 + + + + file: + javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll + + blame: + 3 + + 2022-11-22 + + + + file: + ruby/ql/lib/codeql/ruby/security/performance/SuperlinearBackTracking.qll + + blame: + 3 + + 2022-05-25 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll + + blame: + 74 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/tornado/Redirect.qll + + blame: + 16 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/frameworks/RestFramework.qll + + blame: + 360 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/falcon/General.qll + + blame: + 5 + + 2022-01-19 + + + blame: + 8 + + 2022-01-19 + + + blame: + 17 + + 2022-01-19 + + + blame: + 21 + + 2022-01-19 + + + blame: + 36 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/web/flask/Response.qll + + blame: + 10 + + 2022-01-19 + + + blame: + 23 + + 2022-01-19 + + + blame: + 40 + + 2022-01-19 + + + blame: + 44 + + 2022-01-19 + + + + file: + go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll + + blame: + 31 + + 2022-06-17 + + + blame: + 62 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/security/injection/Xml.qll + + blame: + 14 + + 2022-01-19 + + + blame: + 18 + + 2022-01-19 + + + blame: + 20 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + blame: + 24 + + 2022-01-19 + + + blame: + 28 + + 2022-01-19 + + + blame: + 32 + + 2022-01-19 + + + blame: + 40 + + 2022-01-19 + + + blame: + 51 + + 2022-01-19 + + + blame: + 59 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/flow/AnyCall.qll + + blame: + 5 + + 2022-01-19 + + + + file: + ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll + + blame: + 330 + + 2022-10-03 + + + + file: + python/ql/lib/semmle/python/security/Paths.qll + + blame: + 3 + + 2022-01-19 + + + blame: + 14 + + 2022-01-19 + + + + file: + python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll + + blame: + 6 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/frameworks/j2objc/J2ObjC.qll + + blame: + 20 + + 2022-08-18 + + + blame: + 44 + + 2022-08-18 + + + blame: + 59 + + 2022-08-18 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll + + blame: + 635 + + 2022-03-11 + + + blame: + 818 + + 2022-03-11 + + + + file: + ql/ql/src/codeql_ql/ast/internal/AstNodes.qll + + blame: + 97 + + 2022-03-11 + + + + file: + go/ql/lib/semmle/go/security/ReflectedXss.qll + + blame: + 34 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll + + blame: + 149 + + 2022-03-11 + + + blame: + 166 + + 2022-03-11 + + + + file: + java/ql/src/Security/CWE/CWE-1104/MavenPomDependsOnBintray.ql + + blame: + 23 + + 2022-04-06 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + python/ql/lib/semmle/python/security/dataflow/StackTraceExposureQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/web/turbogears/Response.qll + + blame: + 7 + + 2022-01-19 + + + blame: + 20 + + 2022-01-19 + + + + file: + cpp/ql/lib/semmle/code/cpp/commons/Strcat.qll + + blame: + 9 + + 2022-09-26 + + + + file: + cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll + + blame: + 83 + + 2021-10-14 + + + + file: + python/ql/lib/semmle/python/frameworks/Stdlib.qll + + blame: + 134 + + 2022-03-11 + + + blame: + 1790 + + 2022-03-11 + + + blame: + 1803 + + 2022-03-11 + + + blame: + 1807 + + 2022-03-11 + + + blame: + 1816 + + 2022-03-11 + + + blame: + 1829 + + 2022-03-11 + + + blame: + 1833 + + 2022-03-11 + + + blame: + 1842 + + 2022-03-11 + + + blame: + 1855 + + 2022-08-18 + + + blame: + 1859 + + 2022-08-18 + + + blame: + 1888 + + 2022-03-11 + + + blame: + 1901 + + 2022-03-11 + + + blame: + 1914 + + 2022-08-18 + + + blame: + 1947 + + 2022-03-11 + + + blame: + 2104 + + 2022-08-24 + + + blame: + 2315 + + 2022-03-11 + + + blame: + 2386 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/LogInjectionQuery.qll + + blame: + 26 + + 2022-06-17 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll + + blame: + 21 + + 2022-03-11 + + + + file: + csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll + + blame: + 22 + + 2022-09-09 + + + + file: + javascript/ql/lib/semmle/javascript/frameworks/Connect.qll + + blame: + 95 + + 2022-03-30 + + + blame: + 121 + + 2022-03-30 + + + + file: + swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/java/frameworks/JAXB.qll + + blame: + 13 + + 2022-08-24 + + + blame: + 23 + + 2022-08-24 + + + + file: + go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll + + blame: + 235 + + 2022-06-17 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + java/ql/lib/semmle/code/java/security/performance/ReDoSUtil.qll + + blame: + 3 + + 2022-05-25 + + + + file: + ruby/ql/lib/codeql/ruby/security/regexp/SuperlinearBackTracking.qll + + blame: + 40 + + 2022-11-01 + + + + file: + python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll + + blame: + 98 + + 2022-06-15 + + + blame: + 106 + + 2022-06-15 + + + blame: + 358 + + 2022-06-15 + + + blame: + 365 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll + + blame: + 148 + + 2022-03-11 + + + blame: + 490 + + 2022-03-11 + + + blame: + 640 + + 2022-03-11 + + + blame: + 827 + + 2022-03-11 + + + blame: + 956 + + 2022-03-11 + + + + file: + ql/ql/src/queries/style/NonDocBlock.ql + + blame: + 85 + + 2022-03-08 + + + + file: + javascript/ql/lib/Expressions/DOMProperties.qll + + blame: + 8 + + 2022-03-11 + + + blame: + 19 + + 2022-03-11 + + + + file: + cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll + + blame: + 47 + + 2021-10-14 + + + blame: + 93 + + 2021-10-14 + + + blame: + 132 + + 2021-10-14 + + + blame: + 405 + + 2021-10-14 + + + blame: + 444 + + 2021-10-14 + + + blame: + 469 + + 2021-10-14 + + + blame: + 517 + + 2021-10-14 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/Operand.qll + + blame: + 95 + + 2021-10-14 + + + blame: + 104 + + 2021-10-14 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll + + blame: + 23 + + 2022-10-07 + + + blame: + 132 + + 2022-10-07 + + + blame: + 259 + + 2022-03-11 + + + blame: + 320 + + 2022-10-07 + + + blame: + 431 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/xml/XML.qll + + blame: + 36 + + 2022-08-16 + + + blame: + 99 + + 2022-08-16 + + + blame: + 116 + + 2021-10-14 + + + blame: + 123 + + 2021-10-14 + + + blame: + 138 + + 2022-08-23 + + + blame: + 142 + + 2022-08-16 + + + blame: + 181 + + 2022-08-23 + + + blame: + 239 + + 2022-08-16 + + + blame: + 272 + + 2022-08-16 + + + blame: + 291 + + 2022-08-22 + + + blame: + 304 + + 2022-08-16 + + + blame: + 327 + + 2022-08-16 + + + blame: + 354 + + 2022-08-16 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CodeInjection.qll + + blame: + 8 + + 2022-03-21 + + + blame: + 13 + + 2022-03-21 + + + + file: + python/ql/lib/semmle/python/web/stdlib/Response.qll + + blame: + 9 + + 2022-01-19 + + + blame: + 22 + + 2022-01-19 + + + blame: + 34 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll + + blame: + 91 + + 2022-08-24 + + + blame: + 141 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/web/cherrypy/Request.qll + + blame: + 8 + + 2022-01-19 + + + blame: + 23 + + 2022-01-19 + + + blame: + 37 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll + + blame: + 338 + + 2022-06-15 + + + + file: + cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TOperand.qll + + blame: + 78 + + 2022-03-11 + + + blame: + 88 + + 2022-03-11 + + + blame: + 171 + + 2022-03-11 + + + blame: + 222 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/CodeInjectionCustomizations.qll + + blame: + 39 + + 2022-06-17 + + + + file: + csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedElement.qll + + blame: + 370 + + 2022-03-11 + + + + file: + csharp/ql/lib/semmle/code/csharp/security/dataflow/LDAPInjectionQuery.qll + + blame: + 125 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/frameworks/spring/SpringFlex.qll + + blame: + 61 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll + + blame: + 54 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/dataflow/new/Regexp.qll + + blame: + 12 + + 2022-12-15 + + + blame: + 17 + + 2022-12-15 + + + + file: + go/ql/lib/semmle/go/security/StoredCommand.qll + + blame: + 38 + + 2022-06-17 + + + + file: + python/ql/lib/semmle/python/frameworks/FastApi.qll + + blame: + 41 + + 2022-03-11 + + + + file: + python/ql/lib/semmle/python/security/dataflow/XpathInjectionCustomizations.qll + + blame: + 37 + + 2022-06-17 + + + + file: + python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll + + blame: + 57 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/DefUse.qll + + blame: + 252 + + 2022-03-14 + + + blame: + 269 + + 2022-03-13 + + + blame: + 280 + + 2022-03-13 + + + blame: + 288 + + 2022-03-14 + + + blame: + 304 + + 2022-03-13 + + + + file: + javascript/ql/test/tutorials/Validating RAML-based APIs/Osprey.qll + + blame: + 34 + + 2022-03-11 + + + blame: + 44 + + 2022-03-11 + + + blame: + 57 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll + + blame: + 55 + + 2022-03-11 + + + blame: + 65 + + 2022-03-11 + + + blame: + 131 + + 2022-03-11 + + + + file: + java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll + + blame: + 124 + + 2022-06-15 + + + blame: + 126 + + 2022-06-15 + + + blame: + 136 + + 2022-06-15 + + + blame: + 140 + + 2022-06-15 + + + + file: + javascript/ql/test/library-tests/frameworks/ReactJS/ReactName.qll + + blame: + 20 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/SourceMaps.qll + + blame: + 28 + + 2022-03-11 + + + + file: + python/ql/src/experimental/semmle/python/templates/Chameleon.qll + + blame: + 8 + + 2022-01-20 + + + blame: + 18 + + 2022-01-20 + + + + file: + python/ql/lib/semmle/python/security/injection/Exec.qll + + blame: + 17 + + 2022-01-19 + + + + file: + java/ql/lib/semmle/code/java/frameworks/javaee/jsf/JSFFacesContextXML.qll + + blame: + 20 + + 2022-03-11 + + + blame: + 35 + + 2022-03-11 + + + + file: + csharp/ql/lib/semmle/code/csharp/Type.qll + + blame: + 786 + + 2022-01-17 + + + + file: + ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll + + blame: + 98 + + 2022-09-06 + + + blame: + 106 + + 2022-09-06 + + + blame: + 358 + + 2022-09-06 + + + blame: + 365 + + 2022-09-06 + + + + file: + cpp/ql/lib/semmle/code/cpp/MemberFunction.qll + + blame: + 224 + + 2020-11-26 + + + + file: + python/ql/lib/semmle/python/web/client/Requests.qll + + blame: + 9 + + 2022-01-19 + + + + file: + javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll + + blame: + 39 + + 2022-03-11 + + + + file: + javascript/ql/lib/semmle/javascript/Functions.qll + + blame: + 90 + + 2021-11-01 + + + + diff --git a/ql/buramu/tree-sitter-blame/grammar.js b/ql/buramu/tree-sitter-blame/grammar.js new file mode 100644 index 00000000000..7941c0edab3 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/grammar.js @@ -0,0 +1,30 @@ +module.exports = grammar({ + name: "blame", + + extras: $ => [/\s/], + + rules: { + blame_info: $ => seq($._today, repeat(field('file_entry', $.file_entry))), + + _today: $ => seq("today:", field('today', $.date)), + + file_entry: $ => seq( + "file: ", + field('file_name', $.filename), + "\n", + repeat(field('blame_entry', $.blame_entry)) + ), + + blame_entry: $ => seq( + "last_modified:", + field('date', $.date), + repeat(field('line', $.number)), + ), + + date: $ => /\d{4}-\d{2}-\d{2}/, + + filename: $ => /[a-zA-Z0-9_\-\.\/ ]+/, + + number: $ => /\d+/, + } +}); diff --git a/ql/buramu/tree-sitter-blame/package.json b/ql/buramu/tree-sitter-blame/package.json new file mode 100644 index 00000000000..f9517c74da5 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/package.json @@ -0,0 +1,19 @@ +{ + "name": "tree-sitter-blame", + "version": "0.0.1", + "description": "blame grammar for tree-sitter", + "main": "bindings/node", + "keywords": [ + "parsing", + "incremental" + ], + "dependencies": { + "nan": "^2.12.1" + }, + "devDependencies": { + "tree-sitter-cli": "^0.20.7" + }, + "scripts": { + "test": "tree-sitter test" + } +} diff --git a/ql/buramu/tree-sitter-blame/src/grammar.json b/ql/buramu/tree-sitter-blame/src/grammar.json new file mode 100644 index 00000000000..9001554fd16 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/src/grammar.json @@ -0,0 +1,126 @@ +{ + "name": "blame", + "rules": { + "blame_info": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_today" + }, + { + "type": "REPEAT", + "content": { + "type": "FIELD", + "name": "file_entry", + "content": { + "type": "SYMBOL", + "name": "file_entry" + } + } + } + ] + }, + "_today": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "today:" + }, + { + "type": "FIELD", + "name": "today", + "content": { + "type": "SYMBOL", + "name": "date" + } + } + ] + }, + "file_entry": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "file: " + }, + { + "type": "FIELD", + "name": "file_name", + "content": { + "type": "SYMBOL", + "name": "filename" + } + }, + { + "type": "STRING", + "value": "\n" + }, + { + "type": "REPEAT", + "content": { + "type": "FIELD", + "name": "blame_entry", + "content": { + "type": "SYMBOL", + "name": "blame_entry" + } + } + } + ] + }, + "blame_entry": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "last_modified:" + }, + { + "type": "FIELD", + "name": "date", + "content": { + "type": "SYMBOL", + "name": "date" + } + }, + { + "type": "REPEAT", + "content": { + "type": "FIELD", + "name": "line", + "content": { + "type": "SYMBOL", + "name": "number" + } + } + } + ] + }, + "date": { + "type": "PATTERN", + "value": "\\d{4}-\\d{2}-\\d{2}" + }, + "filename": { + "type": "PATTERN", + "value": "[a-zA-Z0-9_\\-\\.\\/ ]+" + }, + "number": { + "type": "PATTERN", + "value": "\\d+" + } + }, + "extras": [ + { + "type": "PATTERN", + "value": "\\s" + } + ], + "conflicts": [], + "precedences": [], + "externals": [], + "inline": [], + "supertypes": [] +} + diff --git a/ql/buramu/tree-sitter-blame/src/node-types.json b/ql/buramu/tree-sitter-blame/src/node-types.json new file mode 100644 index 00000000000..b1ee2ad7224 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/src/node-types.json @@ -0,0 +1,108 @@ +[ + { + "type": "blame_entry", + "named": true, + "fields": { + "date": { + "multiple": false, + "required": true, + "types": [ + { + "type": "date", + "named": true + } + ] + }, + "line": { + "multiple": true, + "required": false, + "types": [ + { + "type": "number", + "named": true + } + ] + } + } + }, + { + "type": "blame_info", + "named": true, + "fields": { + "file_entry": { + "multiple": true, + "required": false, + "types": [ + { + "type": "file_entry", + "named": true + } + ] + }, + "today": { + "multiple": false, + "required": true, + "types": [ + { + "type": "date", + "named": true + } + ] + } + } + }, + { + "type": "file_entry", + "named": true, + "fields": { + "blame_entry": { + "multiple": true, + "required": false, + "types": [ + { + "type": "blame_entry", + "named": true + } + ] + }, + "file_name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "filename", + "named": true + } + ] + } + } + }, + { + "type": "\n", + "named": false + }, + { + "type": "date", + "named": true + }, + { + "type": "file: ", + "named": false + }, + { + "type": "filename", + "named": true + }, + { + "type": "last_modified:", + "named": false + }, + { + "type": "number", + "named": true + }, + { + "type": "today:", + "named": false + } +] \ No newline at end of file diff --git a/ql/buramu/tree-sitter-blame/src/parser.c b/ql/buramu/tree-sitter-blame/src/parser.c new file mode 100644 index 00000000000..4803597f566 --- /dev/null +++ b/ql/buramu/tree-sitter-blame/src/parser.c @@ -0,0 +1,691 @@ +#include + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#define LANGUAGE_VERSION 14 +#define STATE_COUNT 20 +#define LARGE_STATE_COUNT 2 +#define SYMBOL_COUNT 15 +#define ALIAS_COUNT 0 +#define TOKEN_COUNT 8 +#define EXTERNAL_TOKEN_COUNT 0 +#define FIELD_COUNT 6 +#define MAX_ALIAS_SEQUENCE_LENGTH 4 +#define PRODUCTION_ID_COUNT 14 + +enum { + anon_sym_today_COLON = 1, + anon_sym_file_COLON = 2, + anon_sym_LF = 3, + anon_sym_last_modified_COLON = 4, + sym_date = 5, + sym_filename = 6, + sym_number = 7, + sym_blame_info = 8, + sym__today = 9, + sym_file_entry = 10, + sym_blame_entry = 11, + aux_sym_blame_info_repeat1 = 12, + aux_sym_file_entry_repeat1 = 13, + aux_sym_blame_entry_repeat1 = 14, +}; + +static const char * const ts_symbol_names[] = { + [ts_builtin_sym_end] = "end", + [anon_sym_today_COLON] = "today:", + [anon_sym_file_COLON] = "file: ", + [anon_sym_LF] = "\n", + [anon_sym_last_modified_COLON] = "last_modified:", + [sym_date] = "date", + [sym_filename] = "filename", + [sym_number] = "number", + [sym_blame_info] = "blame_info", + [sym__today] = "_today", + [sym_file_entry] = "file_entry", + [sym_blame_entry] = "blame_entry", + [aux_sym_blame_info_repeat1] = "blame_info_repeat1", + [aux_sym_file_entry_repeat1] = "file_entry_repeat1", + [aux_sym_blame_entry_repeat1] = "blame_entry_repeat1", +}; + +static const TSSymbol ts_symbol_map[] = { + [ts_builtin_sym_end] = ts_builtin_sym_end, + [anon_sym_today_COLON] = anon_sym_today_COLON, + [anon_sym_file_COLON] = anon_sym_file_COLON, + [anon_sym_LF] = anon_sym_LF, + [anon_sym_last_modified_COLON] = anon_sym_last_modified_COLON, + [sym_date] = sym_date, + [sym_filename] = sym_filename, + [sym_number] = sym_number, + [sym_blame_info] = sym_blame_info, + [sym__today] = sym__today, + [sym_file_entry] = sym_file_entry, + [sym_blame_entry] = sym_blame_entry, + [aux_sym_blame_info_repeat1] = aux_sym_blame_info_repeat1, + [aux_sym_file_entry_repeat1] = aux_sym_file_entry_repeat1, + [aux_sym_blame_entry_repeat1] = aux_sym_blame_entry_repeat1, +}; + +static const TSSymbolMetadata ts_symbol_metadata[] = { + [ts_builtin_sym_end] = { + .visible = false, + .named = true, + }, + [anon_sym_today_COLON] = { + .visible = true, + .named = false, + }, + [anon_sym_file_COLON] = { + .visible = true, + .named = false, + }, + [anon_sym_LF] = { + .visible = true, + .named = false, + }, + [anon_sym_last_modified_COLON] = { + .visible = true, + .named = false, + }, + [sym_date] = { + .visible = true, + .named = true, + }, + [sym_filename] = { + .visible = true, + .named = true, + }, + [sym_number] = { + .visible = true, + .named = true, + }, + [sym_blame_info] = { + .visible = true, + .named = true, + }, + [sym__today] = { + .visible = false, + .named = true, + }, + [sym_file_entry] = { + .visible = true, + .named = true, + }, + [sym_blame_entry] = { + .visible = true, + .named = true, + }, + [aux_sym_blame_info_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_file_entry_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_blame_entry_repeat1] = { + .visible = false, + .named = false, + }, +}; + +enum { + field_blame_entry = 1, + field_date = 2, + field_file_entry = 3, + field_file_name = 4, + field_line = 5, + field_today = 6, +}; + +static const char * const ts_field_names[] = { + [0] = NULL, + [field_blame_entry] = "blame_entry", + [field_date] = "date", + [field_file_entry] = "file_entry", + [field_file_name] = "file_name", + [field_line] = "line", + [field_today] = "today", +}; + +static const TSFieldMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = { + [1] = {.index = 0, .length = 1}, + [2] = {.index = 1, .length = 1}, + [3] = {.index = 2, .length = 1}, + [4] = {.index = 3, .length = 2}, + [5] = {.index = 5, .length = 2}, + [6] = {.index = 7, .length = 1}, + [7] = {.index = 8, .length = 1}, + [8] = {.index = 9, .length = 2}, + [9] = {.index = 11, .length = 1}, + [10] = {.index = 12, .length = 2}, + [11] = {.index = 14, .length = 1}, + [12] = {.index = 15, .length = 2}, + [13] = {.index = 17, .length = 2}, +}; + +static const TSFieldMapEntry ts_field_map_entries[] = { + [0] = + {field_today, 0, .inherited = true}, + [1] = + {field_today, 1}, + [2] = + {field_file_entry, 0}, + [3] = + {field_file_entry, 1, .inherited = true}, + {field_today, 0, .inherited = true}, + [5] = + {field_file_entry, 0, .inherited = true}, + {field_file_entry, 1, .inherited = true}, + [7] = + {field_file_name, 1}, + [8] = + {field_blame_entry, 0}, + [9] = + {field_blame_entry, 3, .inherited = true}, + {field_file_name, 1}, + [11] = + {field_date, 1}, + [12] = + {field_blame_entry, 0, .inherited = true}, + {field_blame_entry, 1, .inherited = true}, + [14] = + {field_line, 0}, + [15] = + {field_date, 1}, + {field_line, 2, .inherited = true}, + [17] = + {field_line, 0, .inherited = true}, + {field_line, 1, .inherited = true}, +}; + +static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { + [0] = {0}, +}; + +static const uint16_t ts_non_terminal_alias_map[] = { + 0, +}; + +static const TSStateId ts_primary_state_ids[STATE_COUNT] = { + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = 4, + [5] = 5, + [6] = 6, + [7] = 7, + [8] = 8, + [9] = 9, + [10] = 10, + [11] = 11, + [12] = 12, + [13] = 13, + [14] = 14, + [15] = 15, + [16] = 16, + [17] = 17, + [18] = 18, + [19] = 19, +}; + +static bool ts_lex(TSLexer *lexer, TSStateId state) { + START_LEXER(); + eof = lexer->eof(lexer); + switch (state) { + case 0: + if (eof) ADVANCE(37); + if (lookahead == 'f') ADVANCE(18); + if (lookahead == 'l') ADVANCE(10); + if (lookahead == 't') ADVANCE(23); + if (lookahead == '\t' || + lookahead == '\n' || + lookahead == '\r' || + lookahead == ' ') SKIP(0) + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(48); + END_STATE(); + case 1: + if (lookahead == '\n') ADVANCE(40); + if (lookahead == '\t' || + lookahead == '\r' || + lookahead == ' ') SKIP(1) + END_STATE(); + case 2: + if (lookahead == ' ') ADVANCE(39); + END_STATE(); + case 3: + if (lookahead == ' ') ADVANCE(43); + if (lookahead == '\t' || + lookahead == '\n' || + lookahead == '\r') SKIP(3) + if (('-' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(44); + END_STATE(); + case 4: + if (lookahead == '-') ADVANCE(31); + END_STATE(); + case 5: + if (lookahead == '-') ADVANCE(32); + END_STATE(); + case 6: + if (lookahead == ':') ADVANCE(2); + END_STATE(); + case 7: + if (lookahead == ':') ADVANCE(38); + END_STATE(); + case 8: + if (lookahead == ':') ADVANCE(41); + END_STATE(); + case 9: + if (lookahead == '_') ADVANCE(22); + END_STATE(); + case 10: + if (lookahead == 'a') ADVANCE(25); + END_STATE(); + case 11: + if (lookahead == 'a') ADVANCE(27); + END_STATE(); + case 12: + if (lookahead == 'd') ADVANCE(19); + END_STATE(); + case 13: + if (lookahead == 'd') ADVANCE(11); + END_STATE(); + case 14: + if (lookahead == 'd') ADVANCE(8); + END_STATE(); + case 15: + if (lookahead == 'e') ADVANCE(6); + END_STATE(); + case 16: + if (lookahead == 'e') ADVANCE(14); + END_STATE(); + case 17: + if (lookahead == 'f') ADVANCE(20); + END_STATE(); + case 18: + if (lookahead == 'i') ADVANCE(21); + END_STATE(); + case 19: + if (lookahead == 'i') ADVANCE(17); + END_STATE(); + case 20: + if (lookahead == 'i') ADVANCE(16); + END_STATE(); + case 21: + if (lookahead == 'l') ADVANCE(15); + END_STATE(); + case 22: + if (lookahead == 'm') ADVANCE(24); + END_STATE(); + case 23: + if (lookahead == 'o') ADVANCE(13); + END_STATE(); + case 24: + if (lookahead == 'o') ADVANCE(12); + END_STATE(); + case 25: + if (lookahead == 's') ADVANCE(26); + END_STATE(); + case 26: + if (lookahead == 't') ADVANCE(9); + END_STATE(); + case 27: + if (lookahead == 'y') ADVANCE(7); + END_STATE(); + case 28: + if (lookahead == '\t' || + lookahead == '\n' || + lookahead == '\r' || + lookahead == ' ') SKIP(28) + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(35); + END_STATE(); + case 29: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(5); + END_STATE(); + case 30: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(42); + END_STATE(); + case 31: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(29); + END_STATE(); + case 32: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(30); + END_STATE(); + case 33: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(4); + END_STATE(); + case 34: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(33); + END_STATE(); + case 35: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(34); + END_STATE(); + case 36: + if (eof) ADVANCE(37); + if (lookahead == 'f') ADVANCE(18); + if (lookahead == 'l') ADVANCE(10); + if (lookahead == '\t' || + lookahead == '\n' || + lookahead == '\r' || + lookahead == ' ') SKIP(36) + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(49); + END_STATE(); + case 37: + ACCEPT_TOKEN(ts_builtin_sym_end); + END_STATE(); + case 38: + ACCEPT_TOKEN(anon_sym_today_COLON); + END_STATE(); + case 39: + ACCEPT_TOKEN(anon_sym_file_COLON); + END_STATE(); + case 40: + ACCEPT_TOKEN(anon_sym_LF); + if (lookahead == '\n') ADVANCE(40); + END_STATE(); + case 41: + ACCEPT_TOKEN(anon_sym_last_modified_COLON); + END_STATE(); + case 42: + ACCEPT_TOKEN(sym_date); + END_STATE(); + case 43: + ACCEPT_TOKEN(sym_filename); + if (lookahead == ' ') ADVANCE(43); + if (('-' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(44); + END_STATE(); + case 44: + ACCEPT_TOKEN(sym_filename); + if (lookahead == ' ' || + ('-' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(44); + END_STATE(); + case 45: + ACCEPT_TOKEN(sym_number); + if (lookahead == '-') ADVANCE(31); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(49); + END_STATE(); + case 46: + ACCEPT_TOKEN(sym_number); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(45); + END_STATE(); + case 47: + ACCEPT_TOKEN(sym_number); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(46); + END_STATE(); + case 48: + ACCEPT_TOKEN(sym_number); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(47); + END_STATE(); + case 49: + ACCEPT_TOKEN(sym_number); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(49); + END_STATE(); + default: + return false; + } +} + +static const TSLexMode ts_lex_modes[STATE_COUNT] = { + [0] = {.lex_state = 0}, + [1] = {.lex_state = 0}, + [2] = {.lex_state = 0}, + [3] = {.lex_state = 0}, + [4] = {.lex_state = 36}, + [5] = {.lex_state = 0}, + [6] = {.lex_state = 36}, + [7] = {.lex_state = 36}, + [8] = {.lex_state = 0}, + [9] = {.lex_state = 0}, + [10] = {.lex_state = 0}, + [11] = {.lex_state = 36}, + [12] = {.lex_state = 0}, + [13] = {.lex_state = 0}, + [14] = {.lex_state = 0}, + [15] = {.lex_state = 28}, + [16] = {.lex_state = 0}, + [17] = {.lex_state = 3}, + [18] = {.lex_state = 1}, + [19] = {.lex_state = 28}, +}; + +static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { + [0] = { + [ts_builtin_sym_end] = ACTIONS(1), + [anon_sym_today_COLON] = ACTIONS(1), + [anon_sym_file_COLON] = ACTIONS(1), + [anon_sym_last_modified_COLON] = ACTIONS(1), + [sym_date] = ACTIONS(1), + [sym_number] = ACTIONS(1), + }, + [1] = { + [sym_blame_info] = STATE(16), + [sym__today] = STATE(8), + [anon_sym_today_COLON] = ACTIONS(3), + }, +}; + +static const uint16_t ts_small_parse_table[] = { + [0] = 4, + ACTIONS(7), 1, + anon_sym_last_modified_COLON, + STATE(3), 1, + aux_sym_file_entry_repeat1, + STATE(12), 1, + sym_blame_entry, + ACTIONS(5), 2, + ts_builtin_sym_end, + anon_sym_file_COLON, + [14] = 4, + ACTIONS(7), 1, + anon_sym_last_modified_COLON, + STATE(5), 1, + aux_sym_file_entry_repeat1, + STATE(12), 1, + sym_blame_entry, + ACTIONS(9), 2, + ts_builtin_sym_end, + anon_sym_file_COLON, + [28] = 3, + ACTIONS(13), 1, + sym_number, + STATE(6), 1, + aux_sym_blame_entry_repeat1, + ACTIONS(11), 3, + ts_builtin_sym_end, + anon_sym_file_COLON, + anon_sym_last_modified_COLON, + [40] = 4, + ACTIONS(17), 1, + anon_sym_last_modified_COLON, + STATE(5), 1, + aux_sym_file_entry_repeat1, + STATE(12), 1, + sym_blame_entry, + ACTIONS(15), 2, + ts_builtin_sym_end, + anon_sym_file_COLON, + [54] = 3, + ACTIONS(13), 1, + sym_number, + STATE(7), 1, + aux_sym_blame_entry_repeat1, + ACTIONS(20), 3, + ts_builtin_sym_end, + anon_sym_file_COLON, + anon_sym_last_modified_COLON, + [66] = 3, + ACTIONS(24), 1, + sym_number, + STATE(7), 1, + aux_sym_blame_entry_repeat1, + ACTIONS(22), 3, + ts_builtin_sym_end, + anon_sym_file_COLON, + anon_sym_last_modified_COLON, + [78] = 4, + ACTIONS(27), 1, + ts_builtin_sym_end, + ACTIONS(29), 1, + anon_sym_file_COLON, + STATE(9), 1, + aux_sym_blame_info_repeat1, + STATE(14), 1, + sym_file_entry, + [91] = 4, + ACTIONS(29), 1, + anon_sym_file_COLON, + ACTIONS(31), 1, + ts_builtin_sym_end, + STATE(10), 1, + aux_sym_blame_info_repeat1, + STATE(14), 1, + sym_file_entry, + [104] = 4, + ACTIONS(33), 1, + ts_builtin_sym_end, + ACTIONS(35), 1, + anon_sym_file_COLON, + STATE(10), 1, + aux_sym_blame_info_repeat1, + STATE(14), 1, + sym_file_entry, + [117] = 1, + ACTIONS(38), 4, + ts_builtin_sym_end, + anon_sym_file_COLON, + anon_sym_last_modified_COLON, + sym_number, + [124] = 1, + ACTIONS(40), 3, + ts_builtin_sym_end, + anon_sym_file_COLON, + anon_sym_last_modified_COLON, + [130] = 1, + ACTIONS(42), 2, + ts_builtin_sym_end, + anon_sym_file_COLON, + [135] = 1, + ACTIONS(44), 2, + ts_builtin_sym_end, + anon_sym_file_COLON, + [140] = 1, + ACTIONS(46), 1, + sym_date, + [144] = 1, + ACTIONS(48), 1, + ts_builtin_sym_end, + [148] = 1, + ACTIONS(50), 1, + sym_filename, + [152] = 1, + ACTIONS(52), 1, + anon_sym_LF, + [156] = 1, + ACTIONS(54), 1, + sym_date, +}; + +static const uint32_t ts_small_parse_table_map[] = { + [SMALL_STATE(2)] = 0, + [SMALL_STATE(3)] = 14, + [SMALL_STATE(4)] = 28, + [SMALL_STATE(5)] = 40, + [SMALL_STATE(6)] = 54, + [SMALL_STATE(7)] = 66, + [SMALL_STATE(8)] = 78, + [SMALL_STATE(9)] = 91, + [SMALL_STATE(10)] = 104, + [SMALL_STATE(11)] = 117, + [SMALL_STATE(12)] = 124, + [SMALL_STATE(13)] = 130, + [SMALL_STATE(14)] = 135, + [SMALL_STATE(15)] = 140, + [SMALL_STATE(16)] = 144, + [SMALL_STATE(17)] = 148, + [SMALL_STATE(18)] = 152, + [SMALL_STATE(19)] = 156, +}; + +static const TSParseActionEntry ts_parse_actions[] = { + [0] = {.entry = {.count = 0, .reusable = false}}, + [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), + [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(15), + [5] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_file_entry, 3, .production_id = 6), + [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), + [9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_file_entry, 4, .production_id = 8), + [11] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_blame_entry, 2, .production_id = 9), + [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), + [15] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_file_entry_repeat1, 2, .production_id = 10), + [17] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_file_entry_repeat1, 2, .production_id = 10), SHIFT_REPEAT(19), + [20] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_blame_entry, 3, .production_id = 12), + [22] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_blame_entry_repeat1, 2, .production_id = 13), + [24] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_blame_entry_repeat1, 2, .production_id = 13), SHIFT_REPEAT(11), + [27] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_blame_info, 1, .production_id = 1), + [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), + [31] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_blame_info, 2, .production_id = 4), + [33] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_blame_info_repeat1, 2, .production_id = 5), + [35] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_blame_info_repeat1, 2, .production_id = 5), SHIFT_REPEAT(17), + [38] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_blame_entry_repeat1, 1, .production_id = 11), + [40] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_file_entry_repeat1, 1, .production_id = 7), + [42] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__today, 2, .production_id = 2), + [44] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_blame_info_repeat1, 1, .production_id = 3), + [46] = {.entry = {.count = 1, .reusable = true}}, SHIFT(13), + [48] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), + [50] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), + [52] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), + [54] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4), +}; + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef _WIN32 +#define extern __declspec(dllexport) +#endif + +extern const TSLanguage *tree_sitter_blame(void) { + static const TSLanguage language = { + .version = LANGUAGE_VERSION, + .symbol_count = SYMBOL_COUNT, + .alias_count = ALIAS_COUNT, + .token_count = TOKEN_COUNT, + .external_token_count = EXTERNAL_TOKEN_COUNT, + .state_count = STATE_COUNT, + .large_state_count = LARGE_STATE_COUNT, + .production_id_count = PRODUCTION_ID_COUNT, + .field_count = FIELD_COUNT, + .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, + .parse_table = &ts_parse_table[0][0], + .small_parse_table = ts_small_parse_table, + .small_parse_table_map = ts_small_parse_table_map, + .parse_actions = ts_parse_actions, + .symbol_names = ts_symbol_names, + .field_names = ts_field_names, + .field_map_slices = ts_field_map_slices, + .field_map_entries = ts_field_map_entries, + .symbol_metadata = ts_symbol_metadata, + .public_symbol_map = ts_symbol_map, + .alias_map = ts_non_terminal_alias_map, + .alias_sequences = &ts_alias_sequences[0][0], + .lex_modes = ts_lex_modes, + .lex_fn = ts_lex, + .primary_state_ids = ts_primary_state_ids, + }; + return &language; +} +#ifdef __cplusplus +} +#endif diff --git a/ql/buramu/tree-sitter-blame/src/tree_sitter/parser.h b/ql/buramu/tree-sitter-blame/src/tree_sitter/parser.h new file mode 100644 index 00000000000..2b14ac1046b --- /dev/null +++ b/ql/buramu/tree-sitter-blame/src/tree_sitter/parser.h @@ -0,0 +1,224 @@ +#ifndef TREE_SITTER_PARSER_H_ +#define TREE_SITTER_PARSER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define ts_builtin_sym_error ((TSSymbol)-1) +#define ts_builtin_sym_end 0 +#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 + +typedef uint16_t TSStateId; + +#ifndef TREE_SITTER_API_H_ +typedef uint16_t TSSymbol; +typedef uint16_t TSFieldId; +typedef struct TSLanguage TSLanguage; +#endif + +typedef struct { + TSFieldId field_id; + uint8_t child_index; + bool inherited; +} TSFieldMapEntry; + +typedef struct { + uint16_t index; + uint16_t length; +} TSFieldMapSlice; + +typedef struct { + bool visible; + bool named; + bool supertype; +} TSSymbolMetadata; + +typedef struct TSLexer TSLexer; + +struct TSLexer { + int32_t lookahead; + TSSymbol result_symbol; + void (*advance)(TSLexer *, bool); + void (*mark_end)(TSLexer *); + uint32_t (*get_column)(TSLexer *); + bool (*is_at_included_range_start)(const TSLexer *); + bool (*eof)(const TSLexer *); +}; + +typedef enum { + TSParseActionTypeShift, + TSParseActionTypeReduce, + TSParseActionTypeAccept, + TSParseActionTypeRecover, +} TSParseActionType; + +typedef union { + struct { + uint8_t type; + TSStateId state; + bool extra; + bool repetition; + } shift; + struct { + uint8_t type; + uint8_t child_count; + TSSymbol symbol; + int16_t dynamic_precedence; + uint16_t production_id; + } reduce; + uint8_t type; +} TSParseAction; + +typedef struct { + uint16_t lex_state; + uint16_t external_lex_state; +} TSLexMode; + +typedef union { + TSParseAction action; + struct { + uint8_t count; + bool reusable; + } entry; +} TSParseActionEntry; + +struct TSLanguage { + uint32_t version; + uint32_t symbol_count; + uint32_t alias_count; + uint32_t token_count; + uint32_t external_token_count; + uint32_t state_count; + uint32_t large_state_count; + uint32_t production_id_count; + uint32_t field_count; + uint16_t max_alias_sequence_length; + const uint16_t *parse_table; + const uint16_t *small_parse_table; + const uint32_t *small_parse_table_map; + const TSParseActionEntry *parse_actions; + const char * const *symbol_names; + const char * const *field_names; + const TSFieldMapSlice *field_map_slices; + const TSFieldMapEntry *field_map_entries; + const TSSymbolMetadata *symbol_metadata; + const TSSymbol *public_symbol_map; + const uint16_t *alias_map; + const TSSymbol *alias_sequences; + const TSLexMode *lex_modes; + bool (*lex_fn)(TSLexer *, TSStateId); + bool (*keyword_lex_fn)(TSLexer *, TSStateId); + TSSymbol keyword_capture_token; + struct { + const bool *states; + const TSSymbol *symbol_map; + void *(*create)(void); + void (*destroy)(void *); + bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); + unsigned (*serialize)(void *, char *); + void (*deserialize)(void *, const char *, unsigned); + } external_scanner; + const TSStateId *primary_state_ids; +}; + +/* + * Lexer Macros + */ + +#define START_LEXER() \ + bool result = false; \ + bool skip = false; \ + bool eof = false; \ + int32_t lookahead; \ + goto start; \ + next_state: \ + lexer->advance(lexer, skip); \ + start: \ + skip = false; \ + lookahead = lexer->lookahead; + +#define ADVANCE(state_value) \ + { \ + state = state_value; \ + goto next_state; \ + } + +#define SKIP(state_value) \ + { \ + skip = true; \ + state = state_value; \ + goto next_state; \ + } + +#define ACCEPT_TOKEN(symbol_value) \ + result = true; \ + lexer->result_symbol = symbol_value; \ + lexer->mark_end(lexer); + +#define END_STATE() return result; + +/* + * Parse Table Macros + */ + +#define SMALL_STATE(id) id - LARGE_STATE_COUNT + +#define STATE(id) id + +#define ACTIONS(id) id + +#define SHIFT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = state_value \ + } \ + }} + +#define SHIFT_REPEAT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = state_value, \ + .repetition = true \ + } \ + }} + +#define SHIFT_EXTRA() \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .extra = true \ + } \ + }} + +#define REDUCE(symbol_val, child_count_val, ...) \ + {{ \ + .reduce = { \ + .type = TSParseActionTypeReduce, \ + .symbol = symbol_val, \ + .child_count = child_count_val, \ + __VA_ARGS__ \ + }, \ + }} + +#define RECOVER() \ + {{ \ + .type = TSParseActionTypeRecover \ + }} + +#define ACCEPT_INPUT() \ + {{ \ + .type = TSParseActionTypeAccept \ + }} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_PARSER_H_ diff --git a/ql/buramu/tree-sitter-blame/test.blame b/ql/buramu/tree-sitter-blame/test.blame new file mode 100644 index 00000000000..a77d99fd51c --- /dev/null +++ b/ql/buramu/tree-sitter-blame/test.blame @@ -0,0 +1,24 @@ +today: 2023-02-16 +file: go/ql/lib/semmle/go/security/FlowSources.qll + blame: 33 2022-12-19 +file: python/ql/lib/semmle/python/security/BadTagFilterQuery.qll + blame: 7 2022-11-01 +file: csharp/ql/lib/semmle/code/csharp/Assignable.qll + blame: 128 2022-10-12 + blame: 499 2022-10-12 +file: python/ql/lib/semmle/python/frameworks/Starlette.qll + blame: 164 2022-09-09 +file: ql/ql/src/queries/style/docs/PredicateDocs.ql + blame: 21 2022-08-15 +file: java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll + blame: 308 2022-09-07 +file: javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll + blame: 627 2022-03-30 + blame: 633 2022-03-30 + blame: 636 2022-03-30 + blame: 639 2022-03-30 +file: javascript/ql/lib/semmle/javascript/frameworks/Testing.qll + blame: 41 2022-08-24 +file: javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll + blame: 145 2022-03-30 + blame: 1821 2022-03-13 diff --git a/ql/extractor/Cargo.toml b/ql/extractor/Cargo.toml index a3c899609e2..1a187625d22 100644 --- a/ql/extractor/Cargo.toml +++ b/ql/extractor/Cargo.toml @@ -13,6 +13,8 @@ tree-sitter = ">= 0.20, < 0.21" tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql.git", rev = "d08db734f8dc52f6bc04db53a966603122bc6985"} tree-sitter-ql-dbscheme = { git = "https://github.com/erik-krogh/tree-sitter-ql-dbscheme.git", rev = "63e1344353f63931e88bfbc2faa2e78e1421b213"} tree-sitter-ql-yaml = {git = "https://github.com/erik-krogh/tree-sitter-ql.git", rev = "cf704bf3671e1ae148e173464fb65a4d2bbf5f99"} +tree-sitter-blame = {path = "../buramu/tree-sitter-blame"} +tree-sitter-json = {git = "https://github.com/tausbn/tree-sitter-json.git", rev = "745663ee997f1576fe1e7187e6347e0db36ec7a9"} clap = "2.33" tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } diff --git a/ql/extractor/src/main.rs b/ql/extractor/src/main.rs index 45cce6acdd1..da7f263e7ef 100644 --- a/ql/extractor/src/main.rs +++ b/ql/extractor/src/main.rs @@ -87,10 +87,14 @@ fn main() -> std::io::Result<()> { let language = tree_sitter_ql::language(); let dbscheme = tree_sitter_ql_dbscheme::language(); let yaml = tree_sitter_ql_yaml::language(); + let blame = tree_sitter_blame::language(); + let json = tree_sitter_json::language(); let schema = node_types::read_node_types_str("ql", tree_sitter_ql::NODE_TYPES)?; let dbscheme_schema = node_types::read_node_types_str("dbscheme", tree_sitter_ql_dbscheme::NODE_TYPES)?; let yaml_schema = node_types::read_node_types_str("yaml", tree_sitter_ql_yaml::NODE_TYPES)?; + let blame_schema = node_types::read_node_types_str("blame", tree_sitter_blame::NODE_TYPES)?; + let json_schema = node_types::read_node_types_str("json", tree_sitter_json::NODE_TYPES)?; let lines: std::io::Result> = std::io::BufReader::new(file_list).lines().collect(); let lines = lines?; @@ -103,6 +107,10 @@ fn main() -> std::io::Result<()> { && !line.ends_with(".qll") && !line.ends_with(".dbscheme") && !line.ends_with("qlpack.yml") + && !line.ends_with(".blame") + && !line.ends_with(".json") + && !line.ends_with(".jsonl") + && !line.ends_with(".jsonc") { return Ok(()); } @@ -131,6 +139,29 @@ fn main() -> std::io::Result<()> { &source, &code_ranges, )? + } else if line.ends_with(".json") + || line.ends_with(".jsonl") + || line.ends_with(".jsonc") + { + extractor::extract( + json, + "json", + &json_schema, + &mut trap_writer, + &path, + &source, + &code_ranges, + )? + } else if line.ends_with(".blame") { + extractor::extract( + blame, + "blame", + &blame_schema, + &mut trap_writer, + &path, + &source, + &code_ranges, + )? } else { extractor::extract( language, diff --git a/ql/generator/Cargo.toml b/ql/generator/Cargo.toml index 95ae810088a..4fcc98be310 100644 --- a/ql/generator/Cargo.toml +++ b/ql/generator/Cargo.toml @@ -13,4 +13,6 @@ tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql.git", rev = "d08db734f8dc52f6bc04db53a966603122bc6985"} tree-sitter-ql-dbscheme = { git = "https://github.com/erik-krogh/tree-sitter-ql-dbscheme.git", rev = "63e1344353f63931e88bfbc2faa2e78e1421b213"} -tree-sitter-ql-yaml = {git = "https://github.com/erik-krogh/tree-sitter-ql.git", rev = "cf704bf3671e1ae148e173464fb65a4d2bbf5f99"} \ No newline at end of file +tree-sitter-ql-yaml = {git = "https://github.com/erik-krogh/tree-sitter-ql.git", rev = "cf704bf3671e1ae148e173464fb65a4d2bbf5f99"} +tree-sitter-blame = {path = "../buramu/tree-sitter-blame"} +tree-sitter-json = { git = "https://github.com/tausbn/tree-sitter-json.git", rev = "745663ee997f1576fe1e7187e6347e0db36ec7a9"} diff --git a/ql/generator/src/main.rs b/ql/generator/src/main.rs index 5fb2cfca53d..8c6bf63d859 100644 --- a/ql/generator/src/main.rs +++ b/ql/generator/src/main.rs @@ -577,6 +577,14 @@ fn main() -> std::io::Result<()> { name: "Yaml".to_owned(), node_types: tree_sitter_ql_yaml::NODE_TYPES, }, + Language { + name: "Blame".to_owned(), + node_types: tree_sitter_blame::NODE_TYPES, + }, + Language { + name: "JSON".to_owned(), + node_types: tree_sitter_json::NODE_TYPES, + }, ]; let mut dbscheme_writer = LineWriter::new(File::create(dbscheme_path)?); write!( diff --git a/ql/ql/src/codeql_ql/StructuredLogs.qll b/ql/ql/src/codeql_ql/StructuredLogs.qll new file mode 100644 index 00000000000..f2e6939f7e6 --- /dev/null +++ b/ql/ql/src/codeql_ql/StructuredLogs.qll @@ -0,0 +1,541 @@ +private import ql +private import codeql_ql.ast.internal.TreeSitter +private import experimental.RA + +/** Gets a timestamp corresponding to the number of seconds since the date Semmle was founded. */ +bindingset[d, h, m, s, ms] +private float getTimestamp(date d, int h, int m, int s, int ms) { + result = (("2006-12-28".toDate().daysTo(d) * 24 + h) * 60 + m) * 60 + s + ms / 1000.0 +} + +bindingset[str] +private float stringToTimestamp(string str) { + exists(string r, date d, int h, int m, int s, int ms | + r = "(\\d{4}-\\d{2}-\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{3})Z" + | + d = str.regexpCapture(r, 1).toDate() and + h = str.regexpCapture(r, 2).toInt() and + m = str.regexpCapture(r, 3).toInt() and + s = str.regexpCapture(r, 4).toInt() and + ms = str.regexpCapture(r, 5).toInt() and + result = getTimestamp(d, h, m, s, ms) + ) +} + +bindingset[s] +private Predicate getPredicateFromPosition(string s) { + exists(string r, string filepath, int startline | r = "(.*):(\\d+),(\\d+)-(\\d+),(\\d+)" | + filepath = s.regexpCapture(r, 1) and + startline = s.regexpCapture(r, 2).toInt() and + result.hasLocationInfo(filepath, startline, _, _, _) + ) +} + +class Object extends JSON::Object { + JSON::Value getValue(string key) { + exists(JSON::Pair p | p = this.getChild(_) | + key = p.getKey().(JSON::String).getChild().getValue() and + result = p.getValue() + ) + } + + string getString(string key) { result = this.getValue(key).(JSON::String).getChild().getValue() } + + int getNumber(string key) { result = this.getValue(key).(JSON::Number).getValue().toInt() } + + float getFloat(string key) { result = this.getValue(key).(JSON::Number).getValue().toFloat() } + + Array getArray(string key) { result = this.getValue(key) } + + Object getObject(string key) { result = this.getValue(key) } + + string getType() { result = this.getString("type") } + + int getEventId() { result = this.getNumber("event_id") } + + string getTime() { result = this.getString("time") } + + float getTimestamp() { result = stringToTimestamp(this.getTime()) } +} + +class Array extends JSON::Array { + Object getObject(int i) { result = this.getChild(i) } + + string getString(int i) { result = this.getChild(i).(JSON::String).getChild().getValue() } + + int getNumber(int i) { result = this.getChild(i).(JSON::Number).getValue().toInt() } + + float getFloat(int i) { result = this.getChild(i).(JSON::Number).getValue().toFloat() } + + Array getArray(int i) { result = this.getChild(i) } + + int getLength() { result = count(this.getChild(_)) } +} + +/** + * Gets the i'th non-negative number in `a`. + * + * This is needed because the evaluator log is padded with -1s in some cases. + */ +pragma[nomagic] +private float getRankedFloat(Array a, int i) { + result = rank[i + 1](int j, float f | f = a.getFloat(j) and f >= 0 | f order by j) +} + +private string getRankedLine(Array a, int i) { + result = rank[i + 1](int j, string s | s = a.getString(j) and s != "" | s order by j) +} + +module EvaluatorLog { + class Entry extends Object { } + + class LogHeader extends Entry { + LogHeader() { this.getType() = "LOG_HEADER" } + + string getCodeQLVersion() { result = this.getString("codeqlVersion") } + + string getLogVersion() { result = this.getString("logVersion") } + } + + class QueryStarted extends Entry { + QueryStarted() { this.getType() = "QUERY_STARTED" } + + string getQueryName() { result = this.getString("queryName") } + + int getStage(int i) { result = this.getArray("stage").getNumber(i) } + } + + class PredicateStarted extends Entry { + PredicateStarted() { this.getType() = "PREDICATE_STARTED" } + + string getPredicateName() { result = this.getString("predicateName") } + + string getPosition() { result = this.getString("position") } + + string getPredicateType() { result = this.getString("predicateType") } + + int getQueryCausingWork() { result = this.getNumber("queryCausingWork") } + + string getRAHash() { result = this.getString("raHash") } + + Object getRA() { result = this.getValue("ra") } + + string getDependency(string key) { result = this.getObject("dependencies").getString(key) } + } + + class PipelineStarted extends Entry { + PipelineStarted() { this.getType() = "PIPELINE_STARTED" } + + int getPredicateStartEvent() { result = this.getNumber("predicateStartEvent") } + + string getRAReference() { result = this.getString("raReference") } + } + + class PipelineCompleted extends Entry { + PipelineCompleted() { this.getType() = "PIPELINE_COMPLETED" } + + int getStartEvent() { result = this.getNumber("startEvent") } + + string getRAReference() { result = this.getString("raReference") } + + float getCount(int i) { result = getRankedFloat(this.getArray("counts"), i) } + + float getDuplicationPercentage(int i) { + result = getRankedFloat(this.getArray("duplicationPercentages"), i) + } + + float getResultSize() { result = this.getFloat("resultSize") } + } + + class PredicateCompleted extends Entry { + PredicateCompleted() { this.getType() = "PREDICATE_COMPLETED" } + + int getStartEvent() { result = this.getNumber("startEvent") } + + float getResultSize() { result = this.getFloat("resultSize") } + } + + class QueryCompleted extends Entry { + QueryCompleted() { this.getType() = "QUERY_COMPLETED" } + + int getStartEvent() { result = this.getNumber("startEvent") } + + string getTerminationType() { result = this.getString("terminationType") } + } + + class LogFooter extends Entry { + LogFooter() { this.getType() = "LOG_FOOTER" } + } + + class CacheLookup extends Entry { + CacheLookup() { this.getType() = "CACHE_LOOKUP" } + + float getRelationSize() { result = this.getFloat("relationSize") } + } + + class SentinelEmpty extends Entry { + SentinelEmpty() { this.getType() = "SENTINEL_EMPTY" } + } +} + +module KindPredicatesLog { + class SummaryHeader extends Object { + SummaryHeader() { exists(this.getString("summaryLogVersion")) } + + string getSummaryLogVersion() { result = this.getString("summaryLogVersion") } + + string getCodeqlVersion() { result = this.getString("codeqlVersion") } + + private string getStartTimeString() { result = this.getString("startTime") } + + predicate hasStartTime( + int year, string month, int day, int hours, int minute, int second, int millisecond + ) { + exists(string s, string r | + s = this.getStartTimeString() and + r = "(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{3})Z" + | + year = s.regexpCapture(r, 1).toInt() and + month = s.regexpCapture(r, 2) and + day = s.regexpCapture(r, 3).toInt() and + hours = s.regexpCapture(r, 4).toInt() and + minute = s.regexpCapture(r, 5).toInt() and + second = s.regexpCapture(r, 6).toInt() and + millisecond = s.regexpCapture(r, 7).toInt() + ) + } + } + + class AppearsAs extends Object { + SummaryEvent event; + + AppearsAs() { event.getObject("appearsAs") = this } + + SummaryEvent getSummaryEvent() { result = event } + + PredicateName getAPredicateName() { result.getAppearsAs() = this } + } + + class PredicateName extends Object { + AppearsAs appearsAs; + + PredicateName() { pragma[only_bind_out](appearsAs.getObject(_)) = this } + + AppearsAs getAppearsAs() { result = appearsAs } + + Query getAQuery() { result.getPredicateName() = this } + } + + class Query extends Array { + PredicateName predicateName; + + Query() { this = predicateName.getArray(_) } + + PredicateName getPredicateName() { result = predicateName } + } + + class SummaryEvent extends Object { + string evaluationStrategy; + + SummaryEvent() { evaluationStrategy = this.getString("evaluationStrategy") } + + string getEvaluationStrategy() { result = evaluationStrategy } + + string getRAHash() { result = this.getString("raHash") } + + string getPredicateName() { result = this.getString("predicateName") } + + string getCompletionTimeString() { result = this.getString("completionTime") } + + AppearsAs getAppearsAs() { result = this.getObject("appearsAs") } + + int getMillis() { result = this.getNumber("millis") } + + PipeLineRuns getPipelineRuns() { result = this.getArray("pipelineRuns") } + + pragma[nomagic] + float getDeltaSize(int i) { result = getRankedFloat(this.getArray("deltaSizes"), i) } + + predicate hasCompletionTime( + int year, string month, int day, int hours, int minute, int second, int millisecond + ) { + exists(string s, string r | + s = this.getCompletionTimeString() and + r = "(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{3})Z" + | + year = s.regexpCapture(r, 1).toInt() and + month = s.regexpCapture(r, 2) and + day = s.regexpCapture(r, 3).toInt() and + hours = s.regexpCapture(r, 4).toInt() and + minute = s.regexpCapture(r, 5).toInt() and + second = s.regexpCapture(r, 6).toInt() and + millisecond = s.regexpCapture(r, 7).toInt() + ) + } + + float getCompletionTime() { result = stringToTimestamp(this.getCompletionTimeString()) } + + float getResultSize() { result = this.getFloat("resultSize") } + + string getAnOrdering() { exists(this.getRA().getPipeLine(result)) } + + override string toString() { + if exists(this.getPredicateName()) + then result = this.getPredicateName() + else result = "" + } + + RA getRA() { result = this.getObject("ra") } + } + + class PipeLine extends Array { + RA ra; + string raReference; + + RA getRA() { result = ra } + + string getRAReference() { result = raReference } + + PipeLine() { this = ra.getArray(raReference) } + + string getLineOfRA(int n) { result = getRankedLine(this, n) } + + RAExpr getExpr(int n) { result.getPredicate() = this and result.getLine() = n } + } + + class RA extends Object { + SummaryEvent evt; + + SummaryEvent getEvent() { result = evt } + + RA() { evt.getObject("ra") = this } + + PipeLine getPipeLine(string name) { result = this.getArray(name) } + + PipeLine getPipeLine() { result = this.getPipeLine("pipeline") } + } + + class SentinelEmpty extends SummaryEvent { + SentinelEmpty() { evaluationStrategy = "SENTINEL_EMPTY" } + } + + class PipeLineRun extends Object { + PipeLineRuns runs; + + PipeLineRun() { runs.getObject(_) = this } + + PipeLineRuns getArray() { result = runs } + + string getRAReference() { result = this.getString("raReference") } + + PipeLine getPipeLine() { + exists(SummaryEvent evt | runs.getEvent() = evt | + result = evt.getRA().getPipeLine(pragma[only_bind_into](this.getRAReference())) + ) + } + + float getCount(int i, string raLine) { + result = this.getCount(i) and + raLine = this.getPipeLine().getLineOfRA(pragma[only_bind_into](i)) + } + + float getCountAndExpr(int i, RAExpr raExpr) { + result = this.getCount(i) and + raExpr.getPredicate() = this.getPipeLine() and + raExpr.getLine() = i + } + + Array getCounts() { result = this.getArray("counts") } + + float getCount(int i) { result = getRankedFloat(this.getArray("counts"), i) } + + Array getDuplicationPercentage() { result = this.getArray("duplicationPercentages") } + + float getDuplicationPercentage(int i) { + result = getRankedFloat(this.getArray("duplicationPercentages"), i) + } + } + + class PipeLineRuns extends Array { + SummaryEvent event; + + PipeLineRuns() { event.getArray("pipelineRuns") = this } + + SummaryEvent getEvent() { result = event } + + PipeLineRun getRun(int i) { result = this.getObject(i) } + } + + class Depencencies extends Object { + SummaryEvent event; + + Depencencies() { event.getObject("dependencies") = this } + + SummaryEvent getEvent() { result = event } + + predicate hasEntry(string name, string hash) { this.getString(name) = hash } + + SummaryEvent getADependency() { this.getString(_) = result.getRAHash() } + } + + class ComputeSimple extends SummaryEvent { + ComputeSimple() { evaluationStrategy = "COMPUTE_SIMPLE" } + + Depencencies getDependencies() { result = this.getObject("dependencies") } + + PipeLineRun getPipelineRun() { result.getArray() = this.getArray("pipelineRuns") } + + string getPosition() { result = this.getString("position") } + + Predicate getPredicate() { result = getPredicateFromPosition(this.getPosition()) } + + /** + * Gets the RA for this event. Unlike recursive predicates, a COMPUTE_SIMPLE + * event only has one pipeline ordering (and it's named "pipeline"). + */ + PipeLine getPipeLine() { result = this.getObject("ra").getArray("pipeline") } + } + + /** Gets the `index`'th event that's evaluated by `recursive`. */ + private SummaryEvent layerEventRank(ComputeRecursive recursive, int index) { + result = + rank[index + 1](SummaryEvent cand, int startline, string filepath | + ( + cand = recursive + or + cand.(InLayer).getComputeRecursiveEvent() = recursive + ) and + cand.hasLocationInfo(filepath, startline, _, _, _) + | + cand order by filepath, startline + ) + } + + /** + * Gets the first predicate that's evaluated in an iteration + * of the SCC computation rooted at `recursive`. + */ + SummaryEvent firstPredicate(ComputeRecursive recursive) { result = layerEventRank(recursive, 0) } + + /** + * Gets the last predicate that's evaluated in an iteration + * of the SCC computation rooted at `recursive`. + */ + SummaryEvent lastPredicate(ComputeRecursive recursive) { + exists(int n | + result = layerEventRank(recursive, n) and + not exists(layerEventRank(recursive, n + 1)) + ) + } + + /** + * Holds if the predicate represented by `next` was evaluated after the + * predicate represented by `prev` in the SCC computation rooted at `recursive`. + */ + predicate successor(ComputeRecursive recursive, SummaryEvent prev, InLayer next) { + exists(int index | + layerEventRank(recursive, index) = prev and + layerEventRank(recursive, index + 1) = next + ) + } + + bindingset[this] + signature class ResultSig; + + /** + * A signature for generically traversing a SCC computation. + */ + signature module Fold { + /** + * Gets the base case for the fold. That is, the initial value that + * is produced from the first evaluation of the first IN_LAYER event + * in the recursive evaluation. + */ + bindingset[run] + R base(PipeLineRun run); + + /** + * Gets the recursive case for the fold. That is, `r` is the accumulation + * of the previous evaluations, and `run` is the pipeline of the next IN_LAYER + * event that is evaluated. + */ + bindingset[run, r] + R fold(PipeLineRun run, R r); + } + + module Iterate F> { + private R iterate(ComputeRecursive recursive, int iteration, InLayer pred) { + // Case: The first iteration + iteration = 0 and + ( + // Subcase: The first predicate in the first iteration + pred = firstPredicate(recursive) and + result = F::base(pred.getPipelineRuns().getRun(0)) + or + // Subcase: The predicate has a predecessor + exists(InLayer pred0, R r | + successor(recursive, pred0, pred) and + r = iterate(recursive, 0, pred0) and + result = F::fold(pred.getPipelineRuns().getRun(0), r) + ) + ) + or + // Case: Not the first iteration + iteration > 0 and + ( + // Subcase: The first predicate in the iteration + pred = firstPredicate(recursive) and + exists(InLayer last, R r | + last = lastPredicate(recursive) and + r = iterate(recursive, iteration - 1, last) and + result = F::fold(pred.getPipelineRuns().getRun(iteration), r) + ) + or + // Subcase: The predicate has a predecessor in the same iteration + exists(InLayer pred0, R r | + successor(recursive, pred0, pred) and + r = iterate(recursive, iteration, pred0) and + result = F::fold(pred.getPipelineRuns().getRun(iteration), r) + ) + ) + } + + R iterate(ComputeRecursive recursive) { + exists(int iteration, InLayer pred | + pred = lastPredicate(recursive) and + result = iterate(recursive, iteration, pred) and + not exists(iterate(recursive, iteration + 1, pred)) + ) + } + } + + class ComputeRecursive extends SummaryEvent { + ComputeRecursive() { evaluationStrategy = "COMPUTE_RECURSIVE" } + + Depencencies getDependencies() { result = this.getObject("dependencies") } + } + + class InLayer extends SummaryEvent { + InLayer() { evaluationStrategy = "IN_LAYER" } + + string getMainHash() { result = this.getString("mainHash") } + + ComputeRecursive getComputeRecursiveEvent() { result.getRAHash() = this.getMainHash() } + + Array getPredicateIterationMillis() { result = this.getArray("predicateIterationMillis") } + + float getPredicateIterationMillis(int i) { + result = getRankedFloat(this.getArray("predicateIterationMillis"), i) + } + } + + class ComputedExtensional extends SummaryEvent { + ComputedExtensional() { evaluationStrategy = "COMPUTED_EXTENSIONAL" } + } + + class Extensional extends SummaryEvent { + Extensional() { evaluationStrategy = "EXTENSIONAL" } + } + + class RAExpr = RAParser::RAExpr; +} diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 6b3cf3a8d7b..4264cdf24db 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -1808,7 +1808,7 @@ class FullAggregate extends TFullAggregate, Aggregate { /** * Gets the kind of aggregate. - * E.g. for `min(int i | foo(i))` the result is "foo". + * E.g. for `min(int i | foo(i))` the result is "min". */ override string getKind() { result = kind } diff --git a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll index ae5e2acfcf8..1e7bfa71352 100644 --- a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll +++ b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll @@ -1743,3 +1743,269 @@ module Yaml { final override AstNode getAFieldOrChild() { yaml_yaml_child(this, _, result) } } } + +module Blame { + /** The base class for all AST nodes */ + class AstNode extends @blame_ast_node { + /** Gets a string representation of this element. */ + string toString() { result = this.getAPrimaryQlClass() } + + /** Gets the location of this element. */ + final L::Location getLocation() { blame_ast_node_info(this, _, _, result) } + + /** Gets the parent of this element. */ + final AstNode getParent() { blame_ast_node_info(this, result, _, _) } + + /** Gets the index of this node among the children of its parent. */ + final int getParentIndex() { blame_ast_node_info(this, _, result, _) } + + /** Gets a field or child node of this node. */ + AstNode getAFieldOrChild() { none() } + + /** Gets the name of the primary QL class for this element. */ + string getAPrimaryQlClass() { result = "???" } + + /** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ + string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } + } + + /** A token. */ + class Token extends @blame_token, AstNode { + /** Gets the value of this token. */ + final string getValue() { blame_tokeninfo(this, _, result) } + + /** Gets a string representation of this element. */ + final override string toString() { result = this.getValue() } + + /** Gets the name of the primary QL class for this element. */ + override string getAPrimaryQlClass() { result = "Token" } + } + + /** A reserved word. */ + class ReservedWord extends @blame_reserved_word, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ReservedWord" } + } + + /** A class representing `blame_entry` nodes. */ + class BlameEntry extends @blame_blame_entry, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BlameEntry" } + + /** Gets the node corresponding to the field `date`. */ + final Date getDate() { blame_blame_entry_def(this, result) } + + /** Gets the node corresponding to the field `line`. */ + final Number getLine(int i) { blame_blame_entry_line(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + blame_blame_entry_def(this, result) or blame_blame_entry_line(this, _, result) + } + } + + /** A class representing `blame_info` nodes. */ + class BlameInfo extends @blame_blame_info, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BlameInfo" } + + /** Gets the node corresponding to the field `file_entry`. */ + final FileEntry getFileEntry(int i) { blame_blame_info_file_entry(this, i, result) } + + /** Gets the node corresponding to the field `today`. */ + final Date getToday() { blame_blame_info_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + blame_blame_info_file_entry(this, _, result) or blame_blame_info_def(this, result) + } + } + + /** A class representing `date` tokens. */ + class Date extends @blame_token_date, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Date" } + } + + /** A class representing `file_entry` nodes. */ + class FileEntry extends @blame_file_entry, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "FileEntry" } + + /** Gets the node corresponding to the field `blame_entry`. */ + final BlameEntry getBlameEntry(int i) { blame_file_entry_blame_entry(this, i, result) } + + /** Gets the node corresponding to the field `file_name`. */ + final Filename getFileName() { blame_file_entry_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + blame_file_entry_blame_entry(this, _, result) or blame_file_entry_def(this, result) + } + } + + /** A class representing `filename` tokens. */ + class Filename extends @blame_token_filename, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Filename" } + } + + /** A class representing `number` tokens. */ + class Number extends @blame_token_number, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Number" } + } +} + +module JSON { + /** The base class for all AST nodes */ + class AstNode extends @json_ast_node { + /** Gets a string representation of this element. */ + string toString() { result = this.getAPrimaryQlClass() } + + /** Gets the location of this element. */ + final L::Location getLocation() { json_ast_node_info(this, _, _, result) } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the parent of this element. */ + final AstNode getParent() { json_ast_node_info(this, result, _, _) } + + /** Gets the index of this node among the children of its parent. */ + final int getParentIndex() { json_ast_node_info(this, _, result, _) } + + /** Gets a field or child node of this node. */ + AstNode getAFieldOrChild() { none() } + + /** Gets the name of the primary QL class for this element. */ + string getAPrimaryQlClass() { result = "???" } + + /** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ + string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } + } + + /** A token. */ + class Token extends @json_token, AstNode { + /** Gets the value of this token. */ + final string getValue() { json_tokeninfo(this, _, result) } + + /** Gets a string representation of this element. */ + final override string toString() { result = this.getValue() } + + /** Gets the name of the primary QL class for this element. */ + override string getAPrimaryQlClass() { result = "Token" } + } + + /** A reserved word. */ + class ReservedWord extends @json_reserved_word, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ReservedWord" } + } + + /** A class representing `array` nodes. */ + class Array extends @json_array, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Array" } + + /** Gets the `i`th child of this node. */ + final Value getChild(int i) { json_array_child(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { json_array_child(this, _, result) } + } + + /** A class representing `comment` tokens. */ + class Comment extends @json_token_comment, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Comment" } + } + + /** A class representing `document` nodes. */ + class Document extends @json_document, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Document" } + + /** Gets the `i`th child of this node. */ + final Value getChild(int i) { json_document_child(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { json_document_child(this, _, result) } + } + + /** A class representing `false` tokens. */ + class False extends @json_token_false, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "False" } + } + + /** A class representing `null` tokens. */ + class Null extends @json_token_null, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Null" } + } + + /** A class representing `number` tokens. */ + class Number extends @json_token_number, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Number" } + } + + /** A class representing `object` nodes. */ + class Object extends @json_object, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Object" } + + /** Gets the `i`th child of this node. */ + final Pair getChild(int i) { json_object_child(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { json_object_child(this, _, result) } + } + + /** A class representing `pair` nodes. */ + class Pair extends @json_pair, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Pair" } + + /** Gets the node corresponding to the field `key`. */ + final AstNode getKey() { json_pair_def(this, result, _) } + + /** Gets the node corresponding to the field `value`. */ + final Value getValue() { json_pair_def(this, _, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + json_pair_def(this, result, _) or json_pair_def(this, _, result) + } + } + + /** A class representing `string` nodes. */ + class String extends @json_string__, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "String" } + + /** Gets the child of this node. */ + final StringContent getChild() { json_string_child(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { json_string_child(this, result) } + } + + /** A class representing `string_content` tokens. */ + class StringContent extends @json_token_string_content, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "StringContent" } + } + + /** A class representing `true` tokens. */ + class True extends @json_token_true, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "True" } + } + + class Value extends @json_value, AstNode { } +} diff --git a/ql/ql/src/experimental/RA.qll b/ql/ql/src/experimental/RA.qll new file mode 100644 index 00000000000..7187ebfc8c7 --- /dev/null +++ b/ql/ql/src/experimental/RA.qll @@ -0,0 +1,285 @@ +/** + * Parses RA expressions. + */ + +/** + * A predicate that contains RA. + */ +signature class RApredicate { + string getLineOfRA(int n); +} + +/** + * Parses strings of RA provided by an RA predicate, and represented the + */ +module RAParser { + private string parseRaExpr(Predicate p, int line, int arity, int lhs) { + exists(string str | str = p.getLineOfRA(line).trim() | + arity = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 1).toInt() and + lhs = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 2).toInt() and + result = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 3) + ) + } + + bindingset[str] + private int parseReturn(string str) { + result = str.trim().regexpCapture("return r([0-9]+)", 1).toInt() + } + + bindingset[str] + private predicate parseScan(string str, int arity, int lhs, string rhs) { + exists(string r, string trimmed | + r = "\\{(\\d+)\\}\\s+r(\\d+)\\s+=\\s+SCAN\\s+([0-9a-zA-Z:#_]+)\\s.*" and + trimmed = str.trim() + | + arity = trimmed.regexpCapture(r, 1).toInt() and + lhs = trimmed.regexpCapture(r, 2).toInt() and + rhs = trimmed.regexpCapture(r, 3) + ) + } + + bindingset[str] + private predicate parseJoin(string str, int arity, int lhs, string left, string right) { + exists(string r, string trimmed | + r = + "\\{(\\d+)\\}\\s+r(\\d+)\\s+=\\s+JOIN\\s+([0-9a-zA-Z:#_]+)\\s+WITH\\s+([0-9a-zA-Z:#_]+)\\s.*" and + trimmed = str.trim() + | + arity = trimmed.regexpCapture(r, 1).toInt() and + lhs = trimmed.regexpCapture(r, 2).toInt() and + left = trimmed.regexpCapture(r, 3) and + right = trimmed.regexpCapture(r, 4) + ) + } + + bindingset[str] + private predicate parseSelect(string str, int arity, int lhs, string rhs) { + exists(string r, string trimmed | + r = "\\{(\\d+)\\}\\s+r(\\d+)\\s+=\\s+SELECT\\s+([0-9a-zA-Z:#_]+).*" and + trimmed = str.trim() + | + arity = trimmed.regexpCapture(r, 1).toInt() and + lhs = trimmed.regexpCapture(r, 2).toInt() and + rhs = trimmed.regexpCapture(r, 3) + ) + } + + bindingset[str] + private predicate parseAntiJoin(string str, int arity, int lhs, string left, string right) { + exists(string r, string trimmed | + r = "\\{(\\d+)\\}\\s+r(\\d+)\\s+=\\s+([0-9a-zA-Z:#_]+)\\s+AND\\s+NOT\\s+([0-9a-zA-Z:#_]+).*" and + trimmed = str.trim() + | + arity = trimmed.regexpCapture(r, 1).toInt() and + lhs = trimmed.regexpCapture(r, 2).toInt() and + left = trimmed.regexpCapture(r, 3) and + right = trimmed.regexpCapture(r, 4) + ) + } + + private newtype TRA = + TReturn(Predicate p, int line, int v) { v = parseReturn(p.getLineOfRA(line)) } or + TScan(Predicate p, int line, int arity, int lhs, string rhs) { + parseScan(p.getLineOfRA(line), arity, lhs, rhs) + } or + TJoin(Predicate p, int line, int arity, int lhs, string left, string right) { + parseJoin(p.getLineOfRA(line), arity, lhs, left, right) + } or + TSelect(Predicate p, int line, int arity, int lhs, string rhs) { + parseSelect(p.getLineOfRA(line), arity, lhs, rhs) + } or + TAntiJoin(Predicate p, int line, int arity, int lhs, string left, string right) { + parseAntiJoin(p.getLineOfRA(line), arity, lhs, left, right) + } or + TUnknown(Predicate p, int line, int lhs, int arity, string rhs) { + rhs = parseRaExpr(p, line, arity, lhs) + } + + /** An RA Expression. */ + abstract class RAExpr extends TRA { + /** Gets the predicate this RA expression belongs to. */ + abstract Predicate getPredicate(); + + /** Gets the line index of this RA expression. */ + abstract int getLine(); + + /** Gets the LHS of the expression of the form `rNN = ...` */ + abstract int getLhs(); + + /** Gets a variable of the form `rNN` in the RHS of the RA expression. */ + abstract int getARhsVariable(); + + /** Gets the given arity of the RA expression. */ + abstract int getArity(); + + /** Gets a predicate name referenced in the RHS of an RA expression. */ + abstract string getARhsPredicate(); + + final string toString() { result = this.getPredicate().getLineOfRA(this.getLine()) } + + /** Gets a child of this RA expression - not by index yet. */ + RAExpr getAChild() { + result.getPredicate() = this.getPredicate() and result.getLhs() = this.getARhsVariable() + } + } + + /** + * A generic RA expression - where we haven't precisely parsed the RA expression type. + * For Hackathon purposes, we probably don't need more than this. + */ + class RAUnknownExpr extends RAExpr, TUnknown { + Predicate p; + int line; + string rhs; + int arity; + int lhs; + + RAUnknownExpr() { this = TUnknown(p, line, lhs, arity, rhs) } + + override int getLine() { result = line } + + override Predicate getPredicate() { result = p } + + override int getLhs() { result = lhs } + + override int getARhsVariable() { + result = rhs.splitAt(" ").regexpCapture("r([0-9]+)", 1).toInt() + } + + // This is a dumb regex to find a predicate name - they always contain a `#` (TODO...) + override string getARhsPredicate() { result = rhs.splitAt(" ") and result.indexOf("#") > 0 } + + override int getArity() { result = arity } + } + + class RAReturnExpr extends RAExpr, TReturn { + Predicate p; + int line; + int res; + + RAReturnExpr() { this = TReturn(p, line, res) } + + override Predicate getPredicate() { result = p } + + override int getLine() { result = line } + + override int getLhs() { none() } + + override int getARhsVariable() { result = res } + + override int getArity() { none() } + + override string getARhsPredicate() { none() } + } + + class RAScanExpr extends RAExpr, TScan { + Predicate p; + int line; + int arity; + int lhs; + string rhs; + + RAScanExpr() { this = TScan(p, line, arity, lhs, rhs) } + + override Predicate getPredicate() { result = p } + + override int getLine() { result = line } + + override int getLhs() { result = lhs } + + override int getArity() { result = arity } + + override int getARhsVariable() { isVariable(rhs, result) } + + override string getARhsPredicate() { + result = rhs and + not isVariable(result, _) + } + } + + bindingset[s] + private predicate isVariable(string s, int n) { n = s.regexpCapture("r(\\d+)", 1).toInt() } + + class RAJoinExpr extends RAExpr, TJoin { + Predicate p; + int line; + int arity; + int lhs; + string left; + string right; + + RAJoinExpr() { this = TJoin(p, line, arity, lhs, left, right) } + + override Predicate getPredicate() { result = p } + + override int getLine() { result = line } + + override int getLhs() { result = lhs } + + override int getArity() { result = arity } + + // Note: We could return reasonable values here sometimes. + override int getARhsVariable() { isVariable([left, right], result) } + + // Note: We could return reasonable values here sometimes. + override string getARhsPredicate() { + result = [left, right] and + not isVariable(result, _) + } + } + + class RaSelectExpr extends RAExpr, TSelect { + Predicate p; + int line; + int arity; + int lhs; + string rhs; + + RaSelectExpr() { this = TSelect(p, line, arity, lhs, rhs) } + + override Predicate getPredicate() { result = p } + + override int getLine() { result = line } + + override int getLhs() { result = lhs } + + override int getArity() { result = arity } + + // Note: We could return reasonable values here sometimes. + override int getARhsVariable() { isVariable(rhs, result) } + + // Note: We could return reasonable values here sometimes. + override string getARhsPredicate() { + result = rhs and + not isVariable(result, _) + } + } + + class RaAntiJoinExpr extends RAExpr, TAntiJoin { + Predicate p; + int line; + int arity; + int lhs; + string left; + string right; + + RaAntiJoinExpr() { this = TAntiJoin(p, line, arity, lhs, left, right) } + + override Predicate getPredicate() { result = p } + + override int getLine() { result = line } + + override int getLhs() { result = lhs } + + override int getArity() { result = arity } + + // Note: We could return reasonable values here sometimes. + override int getARhsVariable() { isVariable([left, right], result) } + + // Note: We could return reasonable values here sometimes. + override string getARhsPredicate() { + result = [left, right] and + not isVariable(result, _) + } + } +} diff --git a/ql/ql/src/experimental/queries/PredicateSummaries.ql b/ql/ql/src/experimental/queries/PredicateSummaries.ql new file mode 100644 index 00000000000..da71cb9617e --- /dev/null +++ b/ql/ql/src/experimental/queries/PredicateSummaries.ql @@ -0,0 +1,18 @@ +/** + * Finds evaluations with very large tuple counts somewhere + */ + +import ql +import codeql_ql.StructuredLogs + +float maxTupleCount(KindPredicatesLog::SummaryEvent evt) { + result = max(KindPredicatesLog::PipeLineRuns r | r.getEvent() = evt | r.getRun(_).getCount(_)) +} + +int maxPipeLineLength(KindPredicatesLog::SummaryEvent evt) { + result = max(evt.getRA().getPipeLine(_).getLength()) +} + +from KindPredicatesLog::SummaryEvent evt +select evt, evt.getResultSize(), evt.getMillis() as ms, maxTupleCount(evt) as mc, + maxPipeLineLength(evt) as len order by mc desc diff --git a/ql/ql/src/experimental/queries/SlowPredicates.ql b/ql/ql/src/experimental/queries/SlowPredicates.ql new file mode 100644 index 00000000000..e716e94852f --- /dev/null +++ b/ql/ql/src/experimental/queries/SlowPredicates.ql @@ -0,0 +1,15 @@ +/** + * Shows a list of the "slow" predicates by wallclock time. + */ + +import ql +import codeql_ql.StructuredLogs + +int predicateRank(KindPredicatesLog::SummaryEvent evt) { + evt = + rank[result](KindPredicatesLog::SummaryEvent y, int m | m = y.getMillis() | y order by m desc) +} + +from KindPredicatesLog::SummaryEvent evt +where predicateRank(evt) < 50 +select evt, evt.getMillis() as time order by time desc diff --git a/ql/ql/src/ql.dbscheme b/ql/ql/src/ql.dbscheme index 6ac7bbc82b8..2f4f6f7d26f 100644 --- a/ql/ql/src/ql.dbscheme +++ b/ql/ql/src/ql.dbscheme @@ -1187,3 +1187,146 @@ yaml_ast_node_info( int loc: @location ref ); +#keyset[blame_blame_entry, index] +blame_blame_entry_line( + int blame_blame_entry: @blame_blame_entry ref, + int index: int ref, + unique int line: @blame_token_number ref +); + +blame_blame_entry_def( + unique int id: @blame_blame_entry, + int date__: @blame_token_date ref +); + +#keyset[blame_blame_info, index] +blame_blame_info_file_entry( + int blame_blame_info: @blame_blame_info ref, + int index: int ref, + unique int file_entry: @blame_file_entry ref +); + +blame_blame_info_def( + unique int id: @blame_blame_info, + int today: @blame_token_date ref +); + +#keyset[blame_file_entry, index] +blame_file_entry_blame_entry( + int blame_file_entry: @blame_file_entry ref, + int index: int ref, + unique int blame_entry: @blame_blame_entry ref +); + +blame_file_entry_def( + unique int id: @blame_file_entry, + int file_name: @blame_token_filename ref +); + +blame_tokeninfo( + unique int id: @blame_token, + int kind: int ref, + string value: string ref +); + +case @blame_token.kind of + 0 = @blame_reserved_word +| 1 = @blame_token_date +| 2 = @blame_token_filename +| 3 = @blame_token_number +; + + +@blame_ast_node = @blame_blame_entry | @blame_blame_info | @blame_file_entry | @blame_token + +@blame_ast_node_parent = @blame_ast_node | @file + +#keyset[parent, parent_index] +blame_ast_node_info( + unique int node: @blame_ast_node ref, + int parent: @blame_ast_node_parent ref, + int parent_index: int ref, + int loc: @location ref +); + +#keyset[json_array, index] +json_array_child( + int json_array: @json_array ref, + int index: int ref, + unique int child: @json_value ref +); + +json_array_def( + unique int id: @json_array +); + +#keyset[json_document, index] +json_document_child( + int json_document: @json_document ref, + int index: int ref, + unique int child: @json_value ref +); + +json_document_def( + unique int id: @json_document +); + +#keyset[json_object, index] +json_object_child( + int json_object: @json_object ref, + int index: int ref, + unique int child: @json_pair ref +); + +json_object_def( + unique int id: @json_object +); + +@json_pair_key_type = @json_string__ | @json_token_number + +json_pair_def( + unique int id: @json_pair, + int key__: @json_pair_key_type ref, + int value: @json_value ref +); + +json_string_child( + unique int json_string__: @json_string__ ref, + unique int child: @json_token_string_content ref +); + +json_string_def( + unique int id: @json_string__ +); + +@json_value = @json_array | @json_object | @json_string__ | @json_token_false | @json_token_null | @json_token_number | @json_token_true + +json_tokeninfo( + unique int id: @json_token, + int kind: int ref, + string value: string ref +); + +case @json_token.kind of + 0 = @json_reserved_word +| 1 = @json_token_comment +| 2 = @json_token_false +| 3 = @json_token_null +| 4 = @json_token_number +| 5 = @json_token_string_content +| 6 = @json_token_true +; + + +@json_ast_node = @json_array | @json_document | @json_object | @json_pair | @json_string__ | @json_token + +@json_ast_node_parent = @file | @json_ast_node + +#keyset[parent, parent_index] +json_ast_node_info( + unique int node: @json_ast_node ref, + int parent: @json_ast_node_parent ref, + int parent_index: int ref, + int loc: @location ref +); + diff --git a/ql/ql/src/queries/bugs/SumWithoutDomain.ql b/ql/ql/src/queries/bugs/SumWithoutDomain.ql new file mode 100644 index 00000000000..841f2ab3cb0 --- /dev/null +++ b/ql/ql/src/queries/bugs/SumWithoutDomain.ql @@ -0,0 +1,16 @@ +/** + * @name Sum is missing a domain + * @description An aggregate like 'sum' should work over a domain, otherwise duplicate values will not be counted. + * @kind problem + * @problem.severity error + * @id ql/sum-missing-domain + * @tags correctness + * @precision medium + */ + +import ql + +from ExprAggregate agg +where agg.getKind() = ["sum", "strictsum", "avg"] +select agg, + "This " + agg.getKind() + " does not have a domain argument, so may produce surprising results." diff --git a/ql/ql/src/queries/performance/LargeJoinOrder.ql b/ql/ql/src/queries/performance/LargeJoinOrder.ql new file mode 100644 index 00000000000..35bbdd4eb9c --- /dev/null +++ b/ql/ql/src/queries/performance/LargeJoinOrder.ql @@ -0,0 +1,281 @@ +/** + * Shows a list of the non-recursive predicates with the worst join order as determined + * by the join order metric. + */ + +import ql +import codeql_ql.StructuredLogs +import KindPredicatesLog +import experimental.RA + +/** + * Gets the badness of a non-recursive predicate evaluation. + * + * The badness is the maximum number of tuples in the pipeline divided by the + * maximum of two numbers: the size of the result and the size of the largest dependency. + */ +float getNonRecursiveBadness(ComputeSimple simple) { + exists(float maxTupleCount, float resultSize, float largestDependency, float denom | + resultSize = simple.getResultSize() and + maxTupleCount = max(simple.getPipelineRun().getCount(_)) and + largestDependency = max(simple.getDependencies().getADependency().getResultSize()) and + denom = resultSize.maximum(largestDependency) and + denom > 0 and // avoid division by zero (which would create a NaN result). + result = maxTupleCount / denom + ) +} + +predicate hasTupleCount( + ComputeRecursive recursive, string ordering, SummaryEvent inLayer, int iteration, int i, + float tupleCount +) { + inLayer = firstPredicate(recursive) and + exists(PipeLineRun run | + run = inLayer.getPipelineRuns().getRun(iteration) and ordering = run.getRAReference() + | + tupleCount = run.getCount(i) + or + exists(SummaryEvent inLayer0, float tupleCount0 | + successor(recursive, inLayer0, inLayer) and + hasTupleCount(recursive, ordering, inLayer0, pragma[only_bind_into](iteration), i, tupleCount0) and + tupleCount = run.getCount(i) + tupleCount0 + ) + ) +} + +predicate hasTupleCount(ComputeRecursive recursive, string ordering, int i, float tupleCount) { + tupleCount = + strictsum(SummaryEvent inLayer, int iteration, int tc | + inLayer = getInLayerOrRecursive(recursive) and + hasTupleCount(recursive, ordering, inLayer, iteration, i, tc) + | + tc + ) +} + +pragma[nomagic] +predicate hasDuplication( + ComputeRecursive recursive, string ordering, SummaryEvent inLayer, int iteration, int i, + float duplication +) { + exists(PipeLineRun run | + run = inLayer.getPipelineRuns().getRun(iteration) and + ordering = run.getRAReference() + | + inLayer = firstPredicate(recursive) and + duplication = run.getDuplicationPercentage(i) + or + exists(SummaryEvent inLayer0, float duplication0 | + successor(recursive, inLayer0, inLayer) and + hasDuplication(recursive, ordering, inLayer0, pragma[only_bind_into](iteration), i, + duplication0) and + duplication = run.getDuplicationPercentage(i).maximum(duplication0) + ) + ) +} + +predicate hasDuplication(ComputeRecursive recursive, string ordering, int i, float duplication) { + duplication = + max(int iteration, int dup | hasDuplication(recursive, ordering, _, iteration, i, dup) | dup) +} + +/** + * Holds if the ordering `ordering` has `resultSize` resultSize in the `iteration`'th iteration. + */ +private predicate hasResultSize( + ComputeRecursive recursive, string ordering, SummaryEvent inLayer, int iteration, float resultSize +) { + exists(PipeLineRun run | + run = inLayer.getPipelineRuns().getRun(iteration) and + ordering = run.getRAReference() + | + inLayer = firstPredicate(recursive) and + resultSize = inLayer.getDeltaSize(iteration) + or + exists(SummaryEvent inLayer0, int resultSize0 | + successor(recursive, inLayer0, inLayer) and + hasResultSize(recursive, ordering, inLayer0, iteration, resultSize0) and + resultSize = inLayer.getDeltaSize(iteration) + resultSize0 + ) + ) +} + +predicate hasResultSize(ComputeRecursive recursive, string ordering, float resultSize) { + resultSize = + strictsum(int iteration, float r | hasResultSize(recursive, ordering, _, iteration, r) | r) +} + +RAParser::RAExpr getAnRaOperation(SummaryEvent inLayer, string ordering) { + inLayer.getRA().getPipeLine(ordering) = result.getPredicate() +} + +SummaryEvent getInLayerEventWithName(ComputeRecursive recursive, string predicateName) { + result = getInLayerOrRecursive(recursive) and + result.getPredicateName() = predicateName +} + +bindingset[predicateName, iteration] +int getSize(ComputeRecursive recursive, string predicateName, int iteration, TDeltaKind kind) { + exists(int i, SummaryEvent event | + kind = TPrevious() and + i = iteration - 1 + or + kind = TCurrent() and + i = iteration + | + event = getInLayerEventWithName(recursive, predicateName) and + ( + result = event.getDeltaSize(i) + or + not exists(event.getDeltaSize(i)) and + result = 0 + ) + ) +} + +SummaryEvent getDependencyWithName(Depencencies dependency, string predicateName) { + result.getPredicateName() = predicateName and + dependency.getADependency() = result +} + +newtype TDeltaKind = + TCurrent() or + TPrevious() + +bindingset[predicateName] +private predicate isDelta(string predicateName, TDeltaKind kind, string withoutSuffix) { + kind = TPrevious() and + withoutSuffix = predicateName.regexpCapture("(.+)#prev_delta", 1) + or + kind = TCurrent() and + withoutSuffix = predicateName.regexpCapture("(.+)#cur_delta", 1) +} + +bindingset[iteration] +float getRecursiveDependencySize( + ComputeRecursive recursive, string predicateName, int iteration, SummaryEvent inLayer, + string ordering, TDeltaKind kind +) { + result = getSize(recursive, predicateName, iteration, kind) and + isDelta(getAnRaOperation(inLayer, ordering).getARhsPredicate(), kind, predicateName) +} + +bindingset[ordering, iteration] +predicate hasDependentPredicateSizeImpl( + ComputeRecursive recursive, string ordering, float size, string predicateName, int iteration, + SummaryEvent inLayer +) { + // We treat the base case as a non-recursive case + if ordering = "base" + then + size = + [ + getDependencyWithName(recursive.getDependencies(), predicateName).getResultSize(), + getRecursiveDependencySize(recursive, predicateName, iteration, inLayer, ordering, + TCurrent()) + ] + else + size = + getRecursiveDependencySize(recursive, predicateName, iteration, inLayer, ordering, TPrevious()) +} + +pragma[nomagic] +predicate hasDependentPredicateSize( + ComputeRecursive recursive, string ordering, SummaryEvent inLayer, int iteration, + string predicateName, float size +) { + exists(PipeLineRun run | + run = inLayer.getPipelineRuns().getRun(pragma[only_bind_into](iteration)) and + ordering = run.getRAReference() + | + inLayer = firstPredicate(recursive) and + hasDependentPredicateSizeImpl(recursive, ordering, size, predicateName, iteration, inLayer) + or + exists(SummaryEvent inLayer0, float size0, float size1 | + successor(recursive, inLayer0, inLayer) and + hasDependentPredicateSize(recursive, ordering, inLayer0, pragma[only_bind_into](iteration), + predicateName, size0) and + hasDependentPredicateSizeImpl(recursive, ordering, size1, predicateName, iteration, inLayer) and + size = size0 + size1 + ) + ) +} + +SummaryEvent getInLayerOrRecursive(ComputeRecursive recursive) { + result = recursive or result.(InLayer).getComputeRecursiveEvent() = recursive +} + +predicate hasDependentPredicateSize( + ComputeRecursive recursive, string ordering, string predicateName, float size +) { + size = + strictsum(int iteration, float s | + hasDependentPredicateSize(recursive, ordering, _, iteration, predicateName, s) + | + s + ) +} + +/** + * Gets the badness of a recursive predicate evaluation. + * + * The badness is the maximum number of tuples in the pipeline divided by the + * maximum of two numbers: the size of the result and the size of the largest dependency. + * + * A dependency of a recursive predicate is defined as follows: + * - For a "base" ordering, it is identical to the definition of a dependency for a + * non-recursive predicate + * - For a non-"base" ordering, it's defined as any `#prev_delta` or `#cur_delta` predicates + * that appear in the pipeline. + */ +float getRecursiveBadness(ComputeRecursive recursive, string ordering) { + exists(float maxTupleCount, float resultSize, float maxDependentPredicateSize | + maxTupleCount = max(float tc | hasTupleCount(recursive, ordering, _, tc) | tc) and + hasResultSize(recursive, ordering, resultSize) and + maxDependentPredicateSize = + max(float size | hasDependentPredicateSize(recursive, ordering, _, size) | size) and + resultSize.maximum(maxDependentPredicateSize) > 0 and + result = maxTupleCount / resultSize.maximum(maxDependentPredicateSize) + ) +} + +predicate extractSimpleInformation( + ComputeSimple simple, string predicateName, int index, float tupleCount, + float duplicationPercentage, string operation +) { + exists(PipeLineRun run | + run = simple.getPipelineRun() and + tupleCount = run.getCounts().getFloat(pragma[only_bind_into](index)) and + duplicationPercentage = run.getDuplicationPercentage().getFloat(pragma[only_bind_into](index)) and + operation = simple.getRA().getPipeLine().getLineOfRA(pragma[only_bind_into](index)) and + predicateName = simple.getPredicateName() + ) +} + +predicate extractRecursiveInformation( + ComputeRecursive recursive, string predicateName, string ordering, int index, float tupleCount, + float duplicationPercentage, string operation +) { + hasTupleCount(recursive, ordering, index, tupleCount) and + hasDuplication(recursive, ordering, index, duplicationPercentage) and + operation = recursive.getRA().getPipeLine(ordering).getLineOfRA(index) and + predicateName = recursive.getPredicateName() + " (" + ordering + ")" +} + +from + SummaryEvent evt, float badness, float tupleCount, float duplicationPercentage, string operation, + int index, string predicateName +where + badness > 1.5 and + ( + badness = getNonRecursiveBadness(evt) and + extractSimpleInformation(evt, predicateName, index, tupleCount, duplicationPercentage, operation) + or + exists(string ordering | + badness = getRecursiveBadness(evt, ordering) and + extractRecursiveInformation(evt, predicateName, ordering, index, tupleCount, + duplicationPercentage, operation) + ) + ) +select predicateName as predicate_name, badness, index, tupleCount as tuple_count, + duplicationPercentage as duplication_percentage, operation order by badness desc diff --git a/ql/ql/src/queries/performance/LargeTupleSum.ql b/ql/ql/src/queries/performance/LargeTupleSum.ql new file mode 100644 index 00000000000..e5bbed79bbd --- /dev/null +++ b/ql/ql/src/queries/performance/LargeTupleSum.ql @@ -0,0 +1,28 @@ +/** + * Shows a list of the "slow" predicates by tuple sum. + */ + +import ql +import codeql_ql.StructuredLogs +import KindPredicatesLog + +module SumCounts implements Fold { + int base(PipeLineRun run) { result = sum(int i | | run.getCount(i)) } + + bindingset[s] + int fold(PipeLineRun run, int s) { result = sum(int i | | run.getCount(i)) + s } +} + +int sumTuples(SummaryEvent event) { + result = strictsum(int i | | event.(ComputeSimple).getPipelineRun().getCount(i)) + or + result = Iterate::iterate(event) +} + +int predicateRank(SummaryEvent evt) { + evt = rank[result](SummaryEvent y, int s | s = sumTuples(y) | y order by s desc) +} + +from SummaryEvent evt, int s +where predicateRank(evt) < 50 and s = sumTuples(evt) +select evt, s order by s desc diff --git a/ql/ql/src/queries/reports/OutdatedDeprecations.ql b/ql/ql/src/queries/reports/OutdatedDeprecations.ql new file mode 100644 index 00000000000..5d5e92f41ff --- /dev/null +++ b/ql/ql/src/queries/reports/OutdatedDeprecations.ql @@ -0,0 +1,45 @@ +/** + * @name Outdated deprecation + * @description Deprecations that are over a year old should be removed. + * @kind problem + * @problem.severity recommendation + * @id ql/outdated-deprecation + * @tags maintainability + * @precision high + */ + +import ql +import codeql_ql.ast.internal.TreeSitter + +date today() { result = any(Blame::BlameInfo b).getToday().getValue().toDate() } + +pragma[nomagic] +Annotation getADeprecatedAnnotationAt(string filePath, int line) { + result.getLocation().getFile().getRelativePath() = filePath and + result.getLocation().getStartLine() = line and + result.getName() = "deprecated" +} + +class DatedDeprecation extends Annotation { + date lastModified; + + DatedDeprecation() { + this.getName() = "deprecated" and + exists(Blame::FileEntry f, Blame::BlameEntry b | + this = getADeprecatedAnnotationAt(f.getFileName().getValue(), b.getLine(_).getValue().toInt()) and + f.getBlameEntry(_) = b and + lastModified = b.getDate().getValue().toDate() + ) + } + + /** Gets how long ago this deprecation was added, in months. */ + int getMonthsOld() { + exists(float month | + month = 365 / 12 and result = (lastModified.daysTo(today()) / month).floor() + ) + } +} + +from DatedDeprecation d +where d.getMonthsOld() >= 14 +select d, "This deprecation is over 14 months old." diff --git a/ql/ql/test/experimental/raparser.expected b/ql/ql/test/experimental/raparser.expected new file mode 100644 index 00000000000..46e9058c8ce --- /dev/null +++ b/ql/ql/test/experimental/raparser.expected @@ -0,0 +1,26 @@ +children +| return r7 | {4} r7 = r3 UNION r6 | +| {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] | +| {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] | +| {4} r3 = STREAM DEDUP r2 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | +| {4} r3 = STREAM DEDUP r2 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | +| {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] | +| {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] | +| {4} r5 = STREAM DEDUP r4 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | +| {4} r5 = STREAM DEDUP r4 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | +| {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | {4} r5 = STREAM DEDUP r4 | +| {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | {4} r5 = STREAM DEDUP r4 | +| {4} r7 = r3 UNION r6 | {4} r3 = STREAM DEDUP r2 | +| {4} r7 = r3 UNION r6 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | +| {4} r7 = r3 UNION r6 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | +#select +| p1 | 1 | {1} r1 = CONSTANT(unique string)["p1"] | 1 | 1 | 0 | 0 | +| p1 | 3 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | 2 | 4 | 1 | 1 | +| p1 | 3 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | 2 | 4 | 1 | 1 | +| p1 | 5 | {4} r3 = STREAM DEDUP r2 | 3 | 4 | 0 | 1 | +| p1 | 6 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | 4 | 4 | 1 | 1 | +| p1 | 6 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | 4 | 4 | 1 | 1 | +| p1 | 7 | {4} r5 = STREAM DEDUP r4 | 5 | 4 | 0 | 1 | +| p1 | 8 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | 6 | 4 | 1 | 1 | +| p1 | 8 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | 6 | 4 | 1 | 1 | +| p1 | 9 | {4} r7 = r3 UNION r6 | 7 | 4 | 0 | 2 | diff --git a/ql/ql/test/experimental/raparser.ql b/ql/ql/test/experimental/raparser.ql new file mode 100644 index 00000000000..29489e2a968 --- /dev/null +++ b/ql/ql/test/experimental/raparser.ql @@ -0,0 +1,42 @@ +import experimental.RA + +class TestPredicate extends string { + TestPredicate() { this = "p1" } + + string getLineOfRA(int line) { + line = 1 and + result = " {1} r1 = CONSTANT(unique string)[\"p1\"]" + or + line = 2 and result = "" + or + line = 3 and + result = + " {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT \"p1\", toString(\"p1\"), 123, \" r1 = SCAN fubar\\n r1\"" + or + line = 4 and result = "" + or + line = 5 and result = " {4} r3 = STREAM DEDUP r2" + or + line = 6 and + result = + " {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT \"p1\", \"(no string representation)\", 123, \" r1 = SCAN fubar\\n r1\"" + or + line = 7 and result = " {4} r5 = STREAM DEDUP r4" + or + line = 8 and result = " {4} r6 = r5 AND NOT project##select#query#ffff#nullary({})" + or + line = 9 and result = " {4} r7 = r3 UNION r6" + or + line = 10 and result = " return r7" + } +} + +query predicate children( + RAParser::RAExpr parent, RAParser::RAExpr child +) { + child = parent.getAChild() +} + +from RAParser::RAExpr expr +select expr.getPredicate(), expr.getLine(), expr, expr.getLhs(), expr.getArity(), + count(expr.getARhsPredicate()), count(expr.getARhsVariable()) diff --git a/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.expected b/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.expected new file mode 100644 index 00000000000..d34316073ed --- /dev/null +++ b/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.expected @@ -0,0 +1 @@ +| Test.qll:3:12:3:25 | ExprAggregate[sum] | This sum does not have a domain argument, so may produce surprising results. | diff --git a/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.qlref b/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.qlref new file mode 100644 index 00000000000..dc782dfbd0a --- /dev/null +++ b/ql/ql/test/queries/bugs/SumWithoutDomain/SumWithoutDomain.qlref @@ -0,0 +1 @@ +queries/bugs/SumWithoutDomain.ql \ No newline at end of file diff --git a/ql/ql/test/queries/bugs/SumWithoutDomain/Test.qll b/ql/ql/test/queries/bugs/SumWithoutDomain/Test.qll new file mode 100644 index 00000000000..8190aed8101 --- /dev/null +++ b/ql/ql/test/queries/bugs/SumWithoutDomain/Test.qll @@ -0,0 +1,7 @@ +// Result is 3 and not 4 +int foo() { + result = sum([1, 1, 2]) // <- Alert here +} + +// Ok - false negative +predicate bar() { sum(int x | x = [1, 1, 2] | x) = 3 } diff --git a/ql/rust-toolchain.toml b/ql/rust-toolchain.toml index c0ca7a2593a..38ca5da4f14 100644 --- a/ql/rust-toolchain.toml +++ b/ql/rust-toolchain.toml @@ -2,6 +2,6 @@ # extractor. It is set to the lowest version of Rust we want to support. [toolchain] -channel = "1.54" +channel = "1.59" profile = "minimal" components = [ "rustfmt" ] diff --git a/ruby/Cargo.lock b/ruby/Cargo.lock index caf9a572718..e9c69518d2a 100644 Binary files a/ruby/Cargo.lock and b/ruby/Cargo.lock differ diff --git a/ruby/extractor/Cargo.toml b/ruby/extractor/Cargo.toml index 1e72275abc4..9c18d3b4161 100644 --- a/ruby/extractor/Cargo.toml +++ b/ruby/extractor/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" flate2 = "1.0" node-types = { path = "../node-types" } tree-sitter = "0.20" -tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "a13085849cf69e2401ec44e38cffc3d73f22f3df" } +tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "203f7bd3c1bbfbd98fc19add4b8fcb213c059205" } tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "206c7077164372c596ffa8eaadb9435c28941364" } clap = "3.0" tracing = "0.1" diff --git a/ruby/generator/Cargo.toml b/ruby/generator/Cargo.toml index f72099d4142..49745e813a9 100644 --- a/ruby/generator/Cargo.toml +++ b/ruby/generator/Cargo.toml @@ -11,5 +11,5 @@ clap = "3.0" node-types = { path = "../node-types" } tracing = "0.1" tracing-subscriber = { version = "0.3.3", features = ["env-filter"] } -tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "a13085849cf69e2401ec44e38cffc3d73f22f3df" } +tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "203f7bd3c1bbfbd98fc19add4b8fcb213c059205" } tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "206c7077164372c596ffa8eaadb9435c28941364" } diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 9c0a2e31268..3aabcb81fa7 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.5.3 + +### Minor Analysis Improvements + + * Ruby 3.1: one-line pattern matches are now supported. The AST nodes are named `TestPattern` (`expr in pattern`) and `MatchPattern` (`expr => pattern`). + ## 0.5.2 ### Minor Analysis Improvements diff --git a/ruby/ql/lib/change-notes/2023-02-03-applicationcontroller-render.md b/ruby/ql/lib/change-notes/2023-02-03-applicationcontroller-render.md new file mode 100644 index 00000000000..6e5abaec42f --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-02-03-applicationcontroller-render.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Calls to `ApplicationController#render` and `ApplicationController::Renderer#render` are recognized as Rails rendering calls. diff --git a/ruby/ql/lib/change-notes/2023-02-03-twirp.md b/ruby/ql/lib/change-notes/2023-02-03-twirp.md new file mode 100644 index 00000000000..c6f0d48837e --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-02-03-twirp.md @@ -0,0 +1,4 @@ +--- + category: minorAnalysis +--- +* Support for [Twirp framework](https://twitchtv.github.io/twirp/docs/intro.html). diff --git a/ruby/ql/lib/change-notes/2023-02-06-one-line-matches.md b/ruby/ql/lib/change-notes/released/0.5.3.md similarity index 78% rename from ruby/ql/lib/change-notes/2023-02-06-one-line-matches.md rename to ruby/ql/lib/change-notes/released/0.5.3.md index 3eefba83c2d..3535d0a9fa7 100644 --- a/ruby/ql/lib/change-notes/2023-02-06-one-line-matches.md +++ b/ruby/ql/lib/change-notes/released/0.5.3.md @@ -1,4 +1,5 @@ ---- - category: minorAnalysis ---- +## 0.5.3 + +### Minor Analysis Improvements + * Ruby 3.1: one-line pattern matches are now supported. The AST nodes are named `TestPattern` (`expr in pattern`) and `MatchPattern` (`expr => pattern`). diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/ruby/ql/lib/codeql/files/FileSystem.qll b/ruby/ql/lib/codeql/files/FileSystem.qll index 552b85a4673..f6a5f959287 100644 --- a/ruby/ql/lib/codeql/files/FileSystem.qll +++ b/ruby/ql/lib/codeql/files/FileSystem.qll @@ -1,177 +1,37 @@ /** Provides classes for working with files and folders. */ private import codeql.Locations +private import codeql.util.FileSystem -/** A file or folder. */ -abstract class Container extends @container { - /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { this = result.getParentContainer() } +private module Input implements InputSig { + abstract class ContainerBase extends @container { + abstract string getAbsolutePath(); - /** Gets a file in this container. */ - File getAFile() { result = this.getAChildContainer() } + ContainerBase getParentContainer() { containerparent(result, this) } - /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = this.getAChildContainer() } - - /** - * Gets the absolute, canonical path of this container, using forward slashes - * as path separator. - * - * The path starts with a _root prefix_ followed by zero or more _path - * segments_ separated by forward slashes. - * - * The root prefix is of one of the following forms: - * - * 1. A single forward slash `/` (Unix-style) - * 2. An upper-case drive letter followed by a colon and a forward slash, - * such as `C:/` (Windows-style) - * 3. Two forward slashes, a computer name, and then another forward slash, - * such as `//FileServer/` (UNC-style) - * - * Path segments are never empty (that is, absolute paths never contain two - * contiguous slashes, except as part of a UNC-style root prefix). Also, path - * segments never contain forward slashes, and no path segment is of the - * form `.` (one dot) or `..` (two dots). - * - * Note that an absolute path never ends with a forward slash, except if it is - * a bare root prefix, that is, the path has no path segments. A container - * whose absolute path has no segments is always a `Folder`, not a `File`. - */ - abstract string getAbsolutePath(); - - /** - * Gets the base name of this container including extension, that is, the last - * segment of its absolute path, or the empty string if it has no segments. - * - * Here are some examples of absolute paths and the corresponding base names - * (surrounded with quotes to avoid ambiguity): - * - *
    - * - * - * - * - * - * - * - *
    Absolute pathBase name
    "/tmp/tst.go""tst.go"
    "C:/Program Files (x86)""Program Files (x86)"
    "/"""
    "C:/"""
    "D:/"""
    "//FileServer/"""
    - */ - string getBaseName() { - result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + string toString() { result = this.getAbsolutePath() } } - /** - * Gets the extension of this container, that is, the suffix of its base name - * after the last dot character, if any. - * - * In particular, - * - * - if the name does not include a dot, there is no extension, so this - * predicate has no result; - * - if the name ends in a dot, the extension is the empty string; - * - if the name contains multiple dots, the extension follows the last dot. - * - * Here are some examples of absolute paths and the corresponding extensions - * (surrounded with quotes to avoid ambiguity): - * - * - * - * - * - * - * - * - *
    Absolute pathExtension
    "/tmp/tst.go""go"
    "/tmp/.classpath""classpath"
    "/bin/bash"not defined
    "/tmp/tst2."""
    "/tmp/x.tar.gz""gz"
    - */ - string getExtension() { - result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + class FolderBase extends ContainerBase, @folder { + override string getAbsolutePath() { folders(this, result) } } - /** Gets the file in this container that has the given `baseName`, if any. */ - File getFile(string baseName) { - result = this.getAFile() and - result.getBaseName() = baseName + class FileBase extends ContainerBase, @file { + override string getAbsolutePath() { files(this, result) } } - /** Gets the sub-folder in this container that has the given `baseName`, if any. */ - Folder getFolder(string baseName) { - result = this.getAFolder() and - result.getBaseName() = baseName - } - - /** Gets the parent container of this file or folder, if any. */ - Container getParentContainer() { containerparent(result, this) } - - /** - * Gets the relative path of this file or folder from the root folder of the - * analyzed source location. The relative path of the root folder itself is - * the empty string. - * - * This has no result if the container is outside the source root, that is, - * if the root folder is not a reflexive, transitive parent of this container. - */ - string getRelativePath() { - exists(string absPath, string pref | - absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) - | - absPath = pref and result = "" - or - absPath = pref.regexpReplaceAll("/$", "") + "/" + result and - not result.matches("/%") - ) - } - - /** - * Gets the stem of this container, that is, the prefix of its base name up to - * (but not including) the last dot character if there is one, or the entire - * base name if there is not. - * - * Here are some examples of absolute paths and the corresponding stems - * (surrounded with quotes to avoid ambiguity): - * - * - * - * - * - * - * - * - *
    Absolute pathStem
    "/tmp/tst.go""tst"
    "/tmp/.classpath"""
    "/bin/bash""bash"
    "/tmp/tst2.""tst2"
    "/tmp/x.tar.gz""x.tar"
    - */ - string getStem() { - result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } - - /** - * Gets a URL representing the location of this container. - * - * For more information see https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls. - */ - abstract string getURL(); - - /** - * Gets a textual representation of the path of this container. - * - * This is the absolute path of the container. - */ - string toString() { result = this.getAbsolutePath() } + predicate hasSourceLocationPrefix = sourceLocationPrefix/1; } +private module Impl = Make; + +class Container = Impl::Container; + /** A folder. */ -class Folder extends Container, @folder { - override string getAbsolutePath() { folders(this, result) } - - /** Gets the URL of this folder. */ - override string getURL() { result = "folder://" + this.getAbsolutePath() } -} +class Folder extends Container, Impl::Folder { } /** A file. */ -class File extends Container, @file { - override string getAbsolutePath() { files(this, result) } - - /** Gets the URL of this file. */ - override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } - +class File extends Container, Impl::File { /** Holds if this file was extracted from ordinary source code. */ predicate fromSource() { any() } } diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index c03b6427dec..735178388e8 100644 --- a/ruby/ql/lib/codeql/ruby/Frameworks.qll +++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll @@ -27,3 +27,4 @@ private import codeql.ruby.frameworks.ActionDispatch private import codeql.ruby.frameworks.PosixSpawn private import codeql.ruby.frameworks.StringFormatters private import codeql.ruby.frameworks.Json +private import codeql.ruby.frameworks.Twirp diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index ba365af167d..a56f6445d8f 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -364,6 +364,21 @@ private class ActionControllerRenderToCall extends RenderToCallImpl { } } +/** A call to `ActionController::Renderer#render`. */ +private class RendererRenderCall extends RenderCallImpl { + RendererRenderCall() { + this = + [ + // ActionController#render is an alias for ActionController::Renderer#render + any(ActionControllerClass c).getAnImmediateReference().getAMethodCall("render"), + any(ActionControllerClass c) + .getAnImmediateReference() + .getAMethodCall("renderer") + .getAMethodCall("render") + ].asExpr().getExpr() + } +} + /** A call to `html_escape` from within a controller. */ private class ActionControllerHtmlEscapeCall extends HtmlEscapeCallImpl { ActionControllerHtmlEscapeCall() { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Twirp.qll b/ruby/ql/lib/codeql/ruby/frameworks/Twirp.qll new file mode 100644 index 00000000000..30141b76961 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/Twirp.qll @@ -0,0 +1,85 @@ +/** + * Provides classes for modeling the `Twirp` framework. + */ + +private import codeql.ruby.DataFlow +private import codeql.ruby.CFG +private import codeql.ruby.ApiGraphs +private import codeql.ruby.AST as Ast +private import codeql.ruby.security.ServerSideRequestForgeryCustomizations +private import codeql.ruby.Concepts + +/** + * Provides classes for modeling the `Twirp` framework. + */ +module Twirp { + /** + * A Twirp service instantiation + */ + class ServiceInstantiation extends DataFlow::CallNode { + ServiceInstantiation() { + this = + API::getTopLevelMember("Twirp").getMember("Service").getASubclass().getAnInstantiation() + } + + /** + * Gets a local source node for the Service instantiation argument (the service handler). + */ + private DataFlow::LocalSourceNode getHandlerSource() { + result = this.getArgument(0).getALocalSource() + } + + /** + * Gets the API::Node for the service handler's class. + */ + private API::Node getAHandlerClassApiNode() { + result.getAnInstantiation() = this.getHandlerSource() + } + + /** + * Gets the AST module for the service handler's class. + */ + private Ast::Module getAHandlerClassAstNode() { + result = + this.getAHandlerClassApiNode() + .asSource() + .asExpr() + .(CfgNodes::ExprNodes::ConstantReadAccessCfgNode) + .getExpr() + .getModule() + } + + /** + * Gets a handler's method. + */ + Ast::Method getAHandlerMethod() { + result = this.getAHandlerClassAstNode().getAnInstanceMethod() + } + } + + /** + * A Twirp client + */ + class ClientInstantiation extends DataFlow::CallNode { + ClientInstantiation() { + this = API::getTopLevelMember("Twirp").getMember("Client").getASubclass().getAnInstantiation() + } + } + + /** The URL of a Twirp service, considered as a sink. */ + class ServiceUrlAsSsrfSink extends ServerSideRequestForgery::Sink { + ServiceUrlAsSsrfSink() { exists(ClientInstantiation c | c.getArgument(0) = this) } + } + + /** A parameter that will receive parts of the url when handling an incoming request. */ + class UnmarshaledParameter extends Http::Server::RequestInputAccess::Range, + DataFlow::ParameterNode { + UnmarshaledParameter() { + exists(ServiceInstantiation i | i.getAHandlerMethod().getParameter(0) = this.asParameter()) + } + + override string getSourceType() { result = "Twirp Unmarhaled Parameter" } + + override Http::Server::RequestInputKind getKind() { result = Http::Server::bodyInputKind() } + } +} diff --git a/ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll b/ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll index 2f6c8bb8b29..e86b156e204 100644 --- a/ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll +++ b/ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll @@ -45,8 +45,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ BlockMode getBlockMode() { result = super.getBlockMode() } } @@ -69,8 +73,12 @@ module Cryptography { /** * Gets the block mode used to perform this cryptographic operation. - * This may have no result - for example if the `CryptographicAlgorithm` used - * is a stream cipher rather than a block cipher. + * + * This predicate is only expected to have a result if two conditions hold: + * 1. The operation is an encryption operation, i.e. the algorithm used is an `EncryptionAlgorithm`, and + * 2. The algorithm used is a block cipher (not a stream cipher). + * + * If either of these conditions do not hold, then this predicate should have no result. */ abstract BlockMode getBlockMode(); } @@ -81,10 +89,21 @@ module Cryptography { * data of arbitrary length using a block encryption algorithm. */ class BlockMode extends string { - BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] } + BlockMode() { + this = + [ + "ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP", + "XTS", // https://csrc.nist.gov/publications/detail/sp/800-38e/final + "EAX" // https://en.wikipedia.org/wiki/EAX_mode + ] + } /** Holds if this block mode is considered to be insecure. */ predicate isWeak() { this = "ECB" } + + /** Holds if the given string appears to match this block mode. */ + bindingset[s] + predicate matchesString(string s) { s.toUpperCase().matches("%" + this + "%") } } } diff --git a/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll b/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll index 22a2d1c1eb2..79dd19dd972 100644 --- a/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll +++ b/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll @@ -26,6 +26,26 @@ private newtype TCryptographicAlgorithm = isWeakPasswordHashingAlgorithm(name) and isWeak = true } +/** + * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. + * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. + * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. + */ +bindingset[name] +private CryptographicAlgorithm getBestAlgorithmForName(string name) { + result = + max(CryptographicAlgorithm algorithm | + algorithm.getName() = + [ + name.toUpperCase(), // the full name + name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces + name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores + ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces + | + algorithm order by algorithm.getName().length() + ) +} + /** * A cryptographic algorithm. */ @@ -39,15 +59,11 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { abstract string getName(); /** - * Holds if the name of this algorithm matches `name` modulo case, - * white space, dashes, underscores, and anything after a dash in the name - * (to ignore modes of operation, such as CBC or ECB). + * Holds if the name of this algorithm is the most specific match for `name`. + * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. */ bindingset[name] - predicate matchesName(string name) { - [name.toUpperCase(), name.toUpperCase().regexpCapture("^(\\w+)(?:-.*)?$", 1)] - .regexpReplaceAll("[-_ ]", "") = getName() - } + predicate matchesName(string name) { this = getBestAlgorithmForName(name) } /** * Holds if this algorithm is weak. diff --git a/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll b/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll index a234ba2cc1f..8bb63d97876 100644 --- a/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll +++ b/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll @@ -14,8 +14,20 @@ predicate isStrongHashingAlgorithm(string name) { name = [ + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 + // and https://www.blake2.net/ + "BLAKE2", "BLAKE2B", "BLAKE2S", + // see https://github.com/BLAKE3-team/BLAKE3 + "BLAKE3", + // "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512" + "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 + "SHAKE128", "SHAKE256", + // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 + "SM3", + // see https://security.stackexchange.com/a/216297 + "WHIRLPOOL", ] } diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index b5932af8cca..44bce4f5a2c 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.5.3-dev +version: 0.5.4-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index 0d0783ac735..c5329a4db5a 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,14 @@ +## 0.5.3 + +### New Queries + +* Added a new query, `rb/regex/badly-anchored-regexp`, to detect regular expression validators that use `^` and `$` + as anchors and therefore might match only a single line of a multi-line string. + +### Minor Analysis Improvements + +* The `rb/polynomial-redos` query now considers the entrypoints of the API of a gem as sources. + ## 0.5.2 ### New Queries diff --git a/ruby/ql/src/change-notes/2022-10-11-poly-redos-lib.md b/ruby/ql/src/change-notes/2022-10-11-poly-redos-lib.md deleted file mode 100644 index 125f87378af..00000000000 --- a/ruby/ql/src/change-notes/2022-10-11-poly-redos-lib.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The `rb/polynomial-redos` query now considers the entrypoints of the API of a gem as sources. diff --git a/ruby/ql/src/change-notes/2023-01-06-badly-anchored-regex.md b/ruby/ql/src/change-notes/released/0.5.3.md similarity index 55% rename from ruby/ql/src/change-notes/2023-01-06-badly-anchored-regex.md rename to ruby/ql/src/change-notes/released/0.5.3.md index ab694d3106f..e45205dbd41 100644 --- a/ruby/ql/src/change-notes/2023-01-06-badly-anchored-regex.md +++ b/ruby/ql/src/change-notes/released/0.5.3.md @@ -1,5 +1,10 @@ ---- -category: newQuery ---- +## 0.5.3 + +### New Queries + * Added a new query, `rb/regex/badly-anchored-regexp`, to detect regular expression validators that use `^` and `$` as anchors and therefore might match only a single line of a multi-line string. + +### Minor Analysis Improvements + +* The `rb/polynomial-redos` query now considers the entrypoints of the API of a gem as sources. diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 2d9d3f587f8..2164e038a5d 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.2 +lastReleaseVersion: 0.5.3 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index e054a69c412..448cb25519a 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.5.3-dev +version: 0.5.4-dev groups: - ruby - queries diff --git a/ruby/ql/test/library-tests/dataflow/api-graphs/callbacks.rb b/ruby/ql/test/library-tests/dataflow/api-graphs/callbacks.rb index 41383b7a212..34c4d17d212 100644 --- a/ruby/ql/test/library-tests/dataflow/api-graphs/callbacks.rb +++ b/ruby/ql/test/library-tests/dataflow/api-graphs/callbacks.rb @@ -1,30 +1,30 @@ -Something.foo.withCallback do |a, b| #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getReturn() +Something.foo.withCallback do |a, b| #$ use=getMember("Something").getMethod("foo").getReturn() a.something #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getBlock().getParameter(0).getMethod("something").getReturn() b.somethingElse #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getBlock().getParameter(1).getMethod("somethingElse").getReturn() -end +end #$ use=getMember("Something").getMethod("foo").getReturn().getMethod("withCallback").getReturn() -Something.withNamedArg do |a:, b: nil| #$ use=getMember("Something").getMethod("withNamedArg").getReturn() +Something.withNamedArg do |a:, b: nil| #$ use=getMember("Something") a.something #$ use=getMember("Something").getMethod("withNamedArg").getBlock().getKeywordParameter("a").getMethod("something").getReturn() b.somethingElse #$ use=getMember("Something").getMethod("withNamedArg").getBlock().getKeywordParameter("b").getMethod("somethingElse").getReturn() -end +end #$ use=getMember("Something").getMethod("withNamedArg").getReturn() -Something.withLambda ->(a, b) { #$ use=getMember("Something").getMethod("withLambda").getReturn() +Something.withLambda ->(a, b) { #$ use=getMember("Something") a.something #$ use=getMember("Something").getMethod("withLambda").getParameter(0).getParameter(0).getMethod("something").getReturn() b.something #$ use=getMember("Something").getMethod("withLambda").getParameter(0).getParameter(1).getMethod("something").getReturn() -} +} #$ use=getMember("Something").getMethod("withLambda").getReturn() -Something.namedCallback( #$ use=getMember("Something").getMethod("namedCallback").getReturn() +Something.namedCallback( #$ use=getMember("Something") onEvent: ->(a, b) { a.something #$ use=getMember("Something").getMethod("namedCallback").getKeywordParameter("onEvent").getParameter(0).getMethod("something").getReturn() b.something #$ use=getMember("Something").getMethod("namedCallback").getKeywordParameter("onEvent").getParameter(1).getMethod("something").getReturn() } -) +) #$ use=getMember("Something").getMethod("namedCallback").getReturn() -Something.nestedCall1 do |a| #$ use=getMember("Something").getMethod("nestedCall1").getReturn() - a.nestedCall2 do |b:| #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0).getMethod("nestedCall2").getReturn() +Something.nestedCall1 do |a| #$ use=getMember("Something") + a.nestedCall2 do |b:| #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0) b.something #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0).getMethod("nestedCall2").getBlock().getKeywordParameter("b").getMethod("something").getReturn() - end -end + end #$ use=getMember("Something").getMethod("nestedCall1").getBlock().getParameter(0).getMethod("nestedCall2").getReturn() +end #$ use=getMember("Something").getMethod("nestedCall1").getReturn() def getCallback() ->(x) { @@ -33,7 +33,7 @@ def getCallback() end Something.indirectCallback(getCallback()) #$ use=getMember("Something").getMethod("indirectCallback").getReturn() -Something.withMixed do |a, *args, b| #$ use=getMember("Something").getMethod("withMixed").getReturn() +Something.withMixed do |a, *args, b| #$ use=getMember("Something") a.something #$ use=getMember("Something").getMethod("withMixed").getBlock().getParameter(0).getMethod("something").getReturn() # b.something # not currently handled correctly -end +end #$ use=getMember("Something").getMethod("withMixed").getReturn() diff --git a/ruby/ql/test/library-tests/dataflow/api-graphs/test1.rb b/ruby/ql/test/library-tests/dataflow/api-graphs/test1.rb index 34e2aa5f9cb..86b8bce9587 100644 --- a/ruby/ql/test/library-tests/dataflow/api-graphs/test1.rb +++ b/ruby/ql/test/library-tests/dataflow/api-graphs/test1.rb @@ -13,9 +13,9 @@ Unknown.new.run #$ use=getMember("Unknown").getMethod("new").getReturn().getMeth Foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz") Const = [1, 2, 3] #$ use=getMember("Array").getMethod("[]").getReturn() -Const.each do |c| #$ use=getMember("Const").getMethod("each").getReturn() def=getMember("Const").getMethod("each").getBlock() +Const.each do |c| #$ use=getMember("Const") puts c #$ use=getMember("Const").getMethod("each").getBlock().getParameter(0) use=getMember("Const").getContent(element) -end +end #$ use=getMember("Const").getMethod("each").getReturn() def=getMember("Const").getMethod("each").getBlock() foo = Foo #$ use=getMember("Foo") foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz") diff --git a/ruby/ql/test/library-tests/dataflow/api-graphs/use.ql b/ruby/ql/test/library-tests/dataflow/api-graphs/use.ql index 1f2780793ec..9eb450c01ea 100644 --- a/ruby/ql/test/library-tests/dataflow/api-graphs/use.ql +++ b/ruby/ql/test/library-tests/dataflow/api-graphs/use.ql @@ -44,7 +44,7 @@ class ApiUseTest extends InlineExpectationsTest { max(API::Node a2, Location l2, DataFlow::Node n2 | relevantNode(a2, n2, l2, tag) and l2.getFile() = location.getFile() and - l2.getStartLine() = location.getStartLine() + l2.getEndLine() = location.getEndLine() | a2.getPath() order by diff --git a/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.rb b/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.rb index 090791ddb20..4424893a9b5 100644 --- a/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.rb +++ b/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.rb @@ -44,9 +44,9 @@ end def m8 sink(s8 { source "a" }) # $ hasValueFlow=a - sink(s8 do # $hasValueFlow=a + sink(s8 do source "a" - end) + end) # $hasValueFlow=a end def m9 diff --git a/ruby/ql/test/library-tests/frameworks/ActionDispatch.expected b/ruby/ql/test/library-tests/frameworks/ActionDispatch.expected deleted file mode 100644 index f09706f05fe..00000000000 --- a/ruby/ql/test/library-tests/frameworks/ActionDispatch.expected +++ /dev/null @@ -1,139 +0,0 @@ -actionDispatchRoutes -| action_controller/routes.rb:2:5:2:20 | call to resources | delete | users/:id | users | destroy | -| action_controller/routes.rb:2:5:2:20 | call to resources | get | users | users | index | -| action_controller/routes.rb:2:5:2:20 | call to resources | get | users/:id | users | show | -| action_controller/routes.rb:2:5:2:20 | call to resources | get | users/new | users | new | -| action_controller/routes.rb:2:5:2:20 | call to resources | get | users:id/edit | users | edit | -| action_controller/routes.rb:2:5:2:20 | call to resources | patch | users/:id | users | update | -| action_controller/routes.rb:2:5:2:20 | call to resources | post | users | users | create | -| action_controller/routes.rb:2:5:2:20 | call to resources | put | users/:id | users | update | -| action_controller/routes.rb:3:5:5:7 | call to resources | delete | comments/:id | comments | destroy | -| action_controller/routes.rb:3:5:5:7 | call to resources | get | comments | comments | index | -| action_controller/routes.rb:3:5:5:7 | call to resources | get | comments/:id | comments | show | -| action_controller/routes.rb:3:5:5:7 | call to resources | get | comments/new | comments | new | -| action_controller/routes.rb:3:5:5:7 | call to resources | get | comments:id/edit | comments | edit | -| action_controller/routes.rb:3:5:5:7 | call to resources | patch | comments/:id | comments | update | -| action_controller/routes.rb:3:5:5:7 | call to resources | post | comments | comments | create | -| action_controller/routes.rb:3:5:5:7 | call to resources | put | comments/:id | comments | update | -| action_controller/routes.rb:4:9:4:32 | call to get | get | comments/:comment_id/photo | comments | photo | -| action_controller/routes.rb:6:5:6:21 | call to resources | delete | photos/:id | photos | destroy | -| action_controller/routes.rb:6:5:6:21 | call to resources | get | photos | photos | index | -| action_controller/routes.rb:6:5:6:21 | call to resources | get | photos/:id | photos | show | -| action_controller/routes.rb:6:5:6:21 | call to resources | get | photos/new | photos | new | -| action_controller/routes.rb:6:5:6:21 | call to resources | get | photos:id/edit | photos | edit | -| action_controller/routes.rb:6:5:6:21 | call to resources | patch | photos/:id | photos | update | -| action_controller/routes.rb:6:5:6:21 | call to resources | post | photos | photos | create | -| action_controller/routes.rb:6:5:6:21 | call to resources | put | photos/:id | photos | update | -| action_controller/routes.rb:7:5:9:7 | call to resources | delete | posts/:id | posts | destroy | -| action_controller/routes.rb:7:5:9:7 | call to resources | get | posts | posts | index | -| action_controller/routes.rb:7:5:9:7 | call to resources | get | posts/:id | posts | show | -| action_controller/routes.rb:7:5:9:7 | call to resources | get | posts/new | posts | new | -| action_controller/routes.rb:7:5:9:7 | call to resources | get | posts:id/edit | posts | edit | -| action_controller/routes.rb:7:5:9:7 | call to resources | patch | posts/:id | posts | update | -| action_controller/routes.rb:7:5:9:7 | call to resources | post | posts | posts | create | -| action_controller/routes.rb:7:5:9:7 | call to resources | put | posts/:id | posts | update | -| action_controller/routes.rb:8:9:8:34 | call to post | post | posts/:post_id/upvote | posts | upvote | -| action_controller/routes.rb:10:5:10:19 | call to resources | delete | tags/:id | tags | destroy | -| action_controller/routes.rb:10:5:10:19 | call to resources | get | tags | tags | index | -| action_controller/routes.rb:10:5:10:19 | call to resources | get | tags/:id | tags | show | -| action_controller/routes.rb:10:5:10:19 | call to resources | get | tags/new | tags | new | -| action_controller/routes.rb:10:5:10:19 | call to resources | get | tags:id/edit | tags | edit | -| action_controller/routes.rb:10:5:10:19 | call to resources | patch | tags/:id | tags | update | -| action_controller/routes.rb:10:5:10:19 | call to resources | post | tags | tags | create | -| action_controller/routes.rb:10:5:10:19 | call to resources | put | tags/:id | tags | update | -| app/config/routes.rb:2:3:8:5 | call to resources | get | posts | posts | index | -| app/config/routes.rb:2:3:8:5 | call to resources | get | posts/:id | posts | show | -| app/config/routes.rb:3:5:6:7 | call to resources | delete | posts/:post_id/comments/:id | comments | destroy | -| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments | comments | index | -| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments/:id | comments | show | -| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments/new | comments | new | -| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments:id/edit | comments | edit | -| app/config/routes.rb:3:5:6:7 | call to resources | patch | posts/:post_id/comments/:id | comments | update | -| app/config/routes.rb:3:5:6:7 | call to resources | post | posts/:post_id/comments | comments | create | -| app/config/routes.rb:3:5:6:7 | call to resources | put | posts/:post_id/comments/:id | comments | update | -| app/config/routes.rb:4:7:4:41 | call to resources | post | posts/:post_id/comments/:comment_id/replies | replies | create | -| app/config/routes.rb:5:7:5:28 | call to post | post | posts/:post_id/comments/:comment_id/flag | comments | flag | -| app/config/routes.rb:7:5:7:37 | call to post | post | posts/:post_id/upvote | posts | upvote | -| app/config/routes.rb:11:5:11:54 | call to post | post | destroy_all_posts | posts | destroy_alll | -| app/config/routes.rb:15:5:15:46 | call to get | get | numbers/:number | numbers | show | -| app/config/routes.rb:19:5:19:44 | call to get | get | admin/jobs | background_jobs | index | -| app/config/routes.rb:23:5:23:64 | call to get | get | admin/secrets | secrets | view_secrets | -| app/config/routes.rb:24:5:24:42 | call to delete | delete | admin/:user_id | users | destroy | -| app/config/routes.rb:27:3:27:48 | call to match | get | photos/:id | photos | show | -| app/config/routes.rb:28:3:28:50 | call to match | get | photos/:id | photos | show | -| app/config/routes.rb:29:3:29:69 | call to match | get | photos/:id | photos | show | -| app/config/routes.rb:30:3:30:50 | call to match | delete | photos/:id | photos | show | -| app/config/routes.rb:30:3:30:50 | call to match | get | photos/:id | photos | show | -| app/config/routes.rb:30:3:30:50 | call to match | patch | photos/:id | photos | show | -| app/config/routes.rb:30:3:30:50 | call to match | post | photos/:id | photos | show | -| app/config/routes.rb:30:3:30:50 | call to match | put | photos/:id | photos | show | -| app/config/routes.rb:33:5:33:43 | call to post | post | upgrade | users | start_upgrade | -| app/config/routes.rb:37:5:37:31 | call to get | get | current_billing_cycle | billing/enterprise | current_billing_cycle | -| app/config/routes.rb:40:3:40:40 | call to resource | get | global_config | global_config | show | -| app/config/routes.rb:43:5:45:7 | call to resources | get | foo/bar | foo/bar | index | -| app/config/routes.rb:43:5:45:7 | call to resources | get | foo/bar/:id | foo/bar | show | -| app/config/routes.rb:44:7:44:39 | call to get | get | foo/bar/:bar_id/show_debug | foo/bar | show_debug | -| app/config/routes.rb:49:5:49:95 | call to delete | delete | users/:user/notifications | users/notifications | destroy | -| app/config/routes.rb:50:5:50:94 | call to post | post | users/:user/notifications/:notification_id/mark_as_read | users/notifications | mark_as_read | -actionDispatchControllerMethods -| action_controller/routes.rb:2:5:2:20 | call to resources | action_controller/input_access.rb:2:3:49:5 | index | -| action_controller/routes.rb:2:5:2:20 | call to resources | action_controller/logging.rb:2:5:8:7 | index | -| action_controller/routes.rb:3:5:5:7 | call to resources | action_controller/controllers/comments_controller.rb:17:3:51:5 | index | -| action_controller/routes.rb:3:5:5:7 | call to resources | action_controller/controllers/comments_controller.rb:53:3:54:5 | create | -| action_controller/routes.rb:3:5:5:7 | call to resources | action_controller/controllers/comments_controller.rb:56:3:62:5 | show | -| action_controller/routes.rb:3:5:5:7 | call to resources | action_controller/controllers/comments_controller.rb:68:3:70:5 | destroy | -| action_controller/routes.rb:3:5:5:7 | call to resources | app/controllers/comments_controller.rb:2:3:36:5 | index | -| action_controller/routes.rb:3:5:5:7 | call to resources | app/controllers/comments_controller.rb:38:3:39:5 | show | -| action_controller/routes.rb:4:9:4:32 | call to get | action_controller/controllers/comments_controller.rb:64:3:66:5 | photo | -| action_controller/routes.rb:6:5:6:21 | call to resources | action_controller/controllers/photos_controller.rb:3:3:6:5 | show | -| action_controller/routes.rb:6:5:6:21 | call to resources | app/controllers/photos_controller.rb:2:3:3:5 | show | -| action_controller/routes.rb:7:5:9:7 | call to resources | action_controller/controllers/posts_controller.rb:12:3:13:5 | index | -| action_controller/routes.rb:7:5:9:7 | call to resources | action_controller/controllers/posts_controller.rb:15:3:16:5 | show | -| action_controller/routes.rb:7:5:9:7 | call to resources | app/controllers/posts_controller.rb:2:3:3:5 | index | -| action_controller/routes.rb:7:5:9:7 | call to resources | app/controllers/posts_controller.rb:5:3:6:5 | show | -| action_controller/routes.rb:8:9:8:34 | call to post | action_controller/controllers/posts_controller.rb:18:3:19:5 | upvote | -| action_controller/routes.rb:8:9:8:34 | call to post | app/controllers/posts_controller.rb:8:3:9:5 | upvote | -| app/config/routes.rb:2:3:8:5 | call to resources | action_controller/controllers/posts_controller.rb:12:3:13:5 | index | -| app/config/routes.rb:2:3:8:5 | call to resources | action_controller/controllers/posts_controller.rb:15:3:16:5 | show | -| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:2:3:3:5 | index | -| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:5:3:6:5 | show | -| app/config/routes.rb:3:5:6:7 | call to resources | action_controller/controllers/comments_controller.rb:17:3:51:5 | index | -| app/config/routes.rb:3:5:6:7 | call to resources | action_controller/controllers/comments_controller.rb:53:3:54:5 | create | -| app/config/routes.rb:3:5:6:7 | call to resources | action_controller/controllers/comments_controller.rb:56:3:62:5 | show | -| app/config/routes.rb:3:5:6:7 | call to resources | action_controller/controllers/comments_controller.rb:68:3:70:5 | destroy | -| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:36:5 | index | -| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:38:3:39:5 | show | -| app/config/routes.rb:7:5:7:37 | call to post | action_controller/controllers/posts_controller.rb:18:3:19:5 | upvote | -| app/config/routes.rb:7:5:7:37 | call to post | app/controllers/posts_controller.rb:8:3:9:5 | upvote | -| app/config/routes.rb:27:3:27:48 | call to match | action_controller/controllers/photos_controller.rb:3:3:6:5 | show | -| app/config/routes.rb:27:3:27:48 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | -| app/config/routes.rb:28:3:28:50 | call to match | action_controller/controllers/photos_controller.rb:3:3:6:5 | show | -| app/config/routes.rb:28:3:28:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | -| app/config/routes.rb:29:3:29:69 | call to match | action_controller/controllers/photos_controller.rb:3:3:6:5 | show | -| app/config/routes.rb:29:3:29:69 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | -| app/config/routes.rb:30:3:30:50 | call to match | action_controller/controllers/photos_controller.rb:3:3:6:5 | show | -| app/config/routes.rb:30:3:30:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | -| app/config/routes.rb:50:5:50:94 | call to post | action_controller/controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | -| app/config/routes.rb:50:5:50:94 | call to post | app/controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | -underscore -| Foo | foo | -| Foo::Bar | foo/bar | -| Foo::Bar::Baz | foo/bar/baz | -| Foo::Bar::BazQuux | foo/bar/baz_quux | -| FooBar | foo_bar | -| FooBar::Baz | foo_bar/baz | -| HTTPServerRequest | httpserver_request | -| LotsOfCapitalLetters | lots_of_capital_letters | -| invalid | invalid | -mimeTypeInstances -| action_dispatch/mime_type.rb:2:6:2:28 | Use getMember("Mime").getContent(element_text/html) | -| action_dispatch/mime_type.rb:3:6:3:32 | Use getMember("Mime").getMember("Type").getMethod("new").getReturn() | -| action_dispatch/mime_type.rb:4:6:4:35 | Use getMember("Mime").getMember("Type").getMethod("lookup").getReturn() | -| action_dispatch/mime_type.rb:5:6:5:43 | Use getMember("Mime").getMember("Type").getMethod("lookup_by_extension").getReturn() | -| action_dispatch/mime_type.rb:6:6:6:47 | Use getMember("Mime").getMember("Type").getMethod("register").getReturn() | -| action_dispatch/mime_type.rb:7:6:7:64 | Use getMember("Mime").getMember("Type").getMethod("register_alias").getReturn() | -mimeTypeMatchRegExpInterpretations -| action_dispatch/mime_type.rb:11:11:11:19 | "foo/bar" | -| action_dispatch/mime_type.rb:12:7:12:15 | "foo/bar" | -| action_dispatch/mime_type.rb:13:11:13:11 | s | -| action_dispatch/mime_type.rb:14:7:14:7 | s | diff --git a/ruby/ql/test/library-tests/frameworks/ActionView.expected b/ruby/ql/test/library-tests/frameworks/ActionView.expected deleted file mode 100644 index 07fb6264633..00000000000 --- a/ruby/ql/test/library-tests/frameworks/ActionView.expected +++ /dev/null @@ -1,58 +0,0 @@ -rawCalls -| app/views/foo/bars/_widget.html.erb:1:5:1:21 | call to raw | -| app/views/foo/bars/_widget.html.erb:2:5:2:20 | call to raw | -| app/views/foo/bars/_widget.html.erb:3:5:3:29 | call to raw | -| app/views/foo/bars/show.html.erb:1:14:1:29 | call to raw | -| app/views/foo/bars/show.html.erb:2:5:2:21 | call to raw | -| app/views/foo/bars/show.html.erb:3:5:3:20 | call to raw | -| app/views/foo/bars/show.html.erb:4:5:4:29 | call to raw | -| app/views/foo/bars/show.html.erb:5:5:5:21 | call to raw | -| app/views/foo/bars/show.html.erb:7:5:7:19 | call to raw | -renderCalls -| action_controller/controllers/comments_controller.rb:60:21:60:64 | call to render | -| action_controller/controllers/comments_controller.rb:76:5:76:68 | call to render | -| action_controller/controllers/foo/bars_controller.rb:6:5:6:37 | call to render | -| action_controller/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | -| action_controller/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | -| action_controller/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | -| action_controller/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | -| app/controllers/foo/bars_controller.rb:6:5:6:37 | call to render | -| app/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | -| app/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | -| app/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | -| app/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | -| app/views/foo/bars/show.html.erb:31:5:31:89 | call to render | -renderToCalls -| action_controller/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | -| action_controller/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | -| app/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | -| app/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | -linkToCalls -| app/views/foo/bars/show.html.erb:33:5:33:41 | call to link_to | -httpResponses -| action_controller/controllers/comments_controller.rb:26:5:26:17 | call to body= | action_controller/controllers/comments_controller.rb:26:21:26:34 | ... = ... | text/http | -| action_controller/controllers/comments_controller.rb:36:5:36:37 | call to send_file | action_controller/controllers/comments_controller.rb:36:24:36:36 | "my-file.ext" | application/octet-stream | -| action_controller/controllers/comments_controller.rb:65:5:65:20 | call to send_data | action_controller/controllers/comments_controller.rb:65:15:65:20 | @photo | application/octet-stream | -| action_controller/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | action_controller/controllers/foo/bars_controller.rb:15:33:15:47 | "foo/bars/show" | text/html | -| action_controller/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | action_controller/controllers/foo/bars_controller.rb:23:12:23:26 | "foo/bars/show" | text/html | -| action_controller/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | action_controller/controllers/foo/bars_controller.rb:35:18:35:33 | call to [] | application/json | -| action_controller/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | action_controller/controllers/foo/bars_controller.rb:36:29:36:33 | @user | application/json | -| action_controller/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | action_controller/controllers/foo/bars_controller.rb:38:12:38:22 | call to backtrace | text/plain | -| action_controller/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | action_controller/controllers/foo/bars_controller.rb:44:12:44:17 | "show" | text/html | -| app/controllers/comments_controller.rb:11:5:11:17 | call to body= | app/controllers/comments_controller.rb:11:21:11:34 | ... = ... | text/http | -| app/controllers/comments_controller.rb:21:5:21:37 | call to send_file | app/controllers/comments_controller.rb:21:24:21:36 | "my-file.ext" | application/octet-stream | -| app/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | app/controllers/foo/bars_controller.rb:15:33:15:47 | "foo/bars/show" | text/html | -| app/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | app/controllers/foo/bars_controller.rb:23:12:23:26 | "foo/bars/show" | text/html | -| app/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | app/controllers/foo/bars_controller.rb:35:18:35:33 | call to [] | application/json | -| app/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | app/controllers/foo/bars_controller.rb:36:29:36:33 | @user | application/json | -| app/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | app/controllers/foo/bars_controller.rb:38:12:38:22 | call to backtrace | text/plain | -| app/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | app/controllers/foo/bars_controller.rb:44:12:44:17 | "show" | text/html | -rawHelperCalls -| action_view/helpers.erb:4:1:4:36 | call to simple_format | action_view/helpers.erb:4:15:4:15 | call to x | -| action_view/helpers.erb:7:1:7:26 | call to truncate | action_view/helpers.erb:7:10:7:10 | call to x | -| action_view/helpers.erb:10:1:10:29 | call to highlight | action_view/helpers.erb:10:11:10:11 | call to x | -| action_view/helpers.erb:12:1:12:17 | call to javascript_tag | action_view/helpers.erb:12:16:12:16 | call to x | -| action_view/helpers.erb:15:1:15:27 | call to content_tag | action_view/helpers.erb:15:16:15:16 | call to y | -| action_view/helpers.erb:18:1:18:19 | call to tag | action_view/helpers.erb:18:5:18:5 | call to x | -| action_view/helpers.erb:21:1:21:24 | call to h1 | action_view/helpers.erb:21:8:21:8 | call to x | -| action_view/helpers.erb:24:1:24:23 | call to p | action_view/helpers.erb:24:7:24:7 | call to x | diff --git a/ruby/ql/test/library-tests/frameworks/ActionView.ql b/ruby/ql/test/library-tests/frameworks/ActionView.ql deleted file mode 100644 index 124cf0722a1..00000000000 --- a/ruby/ql/test/library-tests/frameworks/ActionView.ql +++ /dev/null @@ -1,21 +0,0 @@ -private import ruby -private import codeql.ruby.AST -private import codeql.ruby.frameworks.ActionView -private import codeql.ruby.frameworks.Rails -private import codeql.ruby.Concepts - -query predicate rawCalls(RawCall c) { any() } - -query predicate renderCalls(Rails::RenderCall c) { any() } - -query predicate renderToCalls(Rails::RenderToCall c) { any() } - -query predicate linkToCalls(LinkToCall c) { any() } - -query predicate httpResponses(Http::Server::HttpResponse r, DataFlow::Node body, string mimeType) { - r.getBody() = body and r.getMimetype() = mimeType -} - -query predicate rawHelperCalls(ActionView::Helpers::RawHelperCall c, Expr arg) { - arg = c.getRawArgument() -} diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/Gemfile b/ruby/ql/test/library-tests/frameworks/Twirp/Gemfile new file mode 100644 index 00000000000..9f49fa5ad78 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "rack" +gem "webrick" +gem "twirp" diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.expected b/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.expected new file mode 100644 index 00000000000..66da43ab78b --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.expected @@ -0,0 +1,6 @@ +sourceTest +| hello_world_server.rb:8:13:8:15 | req | +ssrfSinkTest +| hello_world_client.rb:6:47:6:75 | "http://localhost:8080/twirp" | +serviceInstantiationTest +| hello_world_server.rb:24:11:24:61 | call to new | diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.ql b/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.ql new file mode 100644 index 00000000000..4c0494f9100 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/Twirp.ql @@ -0,0 +1,8 @@ +private import codeql.ruby.frameworks.Twirp +private import codeql.ruby.DataFlow + +query predicate sourceTest(Twirp::UnmarshaledParameter source) { any() } + +query predicate ssrfSinkTest(Twirp::ServiceUrlAsSsrfSink sink) { any() } + +query predicate serviceInstantiationTest(Twirp::ServiceInstantiation si) { any() } diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service.proto b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service.proto new file mode 100644 index 00000000000..f7b4a818e2f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package example.hello_world; + + +service HelloWorld { + rpc Hello(HelloRequest) returns (HelloResponse); +} + +message HelloRequest { + string name = 1; +} + +message HelloResponse { + string message = 1; +} diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_pb.rb b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_pb.rb new file mode 100644 index 00000000000..10de1c1f7e8 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_pb.rb @@ -0,0 +1,22 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: hello_world/service.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("hello_world/service.proto", :syntax => :proto3) do + add_message "example.hello_world.HelloRequest" do + optional :name, :string, 1 + end + add_message "example.hello_world.HelloResponse" do + optional :message, :string, 1 + end + end +end + +module Example + module HelloWorld + HelloRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("example.hello_world.HelloRequest").msgclass + HelloResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("example.hello_world.HelloResponse").msgclass + end +end diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_twirp.rb b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_twirp.rb new file mode 100644 index 00000000000..ff3b9cc4a81 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world/service_twirp.rb @@ -0,0 +1,17 @@ +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. +require 'twirp' +require_relative 'service_pb.rb' + +module Example + module HelloWorld + class HelloWorldService < ::Twirp::Service + package 'example.hello_world' + service 'HelloWorld' + rpc :Hello, HelloRequest, HelloResponse, :ruby_method => :hello + end + + class HelloWorldClient < ::Twirp::Client + client_for HelloWorldService + end + end +end diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_client.rb b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_client.rb new file mode 100644 index 00000000000..68c63796a1e --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_client.rb @@ -0,0 +1,13 @@ +require 'rack' + +require_relative 'hello_world/service_twirp.rb' + +# test: ssrfSink +c = Example::HelloWorld::HelloWorldClient.new("http://localhost:8080/twirp") + +resp = c.hello(name: "World") +if resp.error + puts resp.error +else + puts resp.data.message +end diff --git a/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_server.rb b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_server.rb new file mode 100644 index 00000000000..1aa0b9aa8de --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/Twirp/hello_world_server.rb @@ -0,0 +1,29 @@ +require 'rack' +require 'webrick' + +require_relative 'hello_world/service_twirp.rb' + +class HelloWorldHandler + # test: request + def hello(req, env) + puts ">> Hello #{req.name}" + {message: "Hello #{req.name}"} + end +end + +class FakeHelloWorldHandler + # test: !request + def hello(req, env) + puts ">> Hello #{req.name}" + {message: "Hello #{req.name}"} + end +end + +handler = HelloWorldHandler.new() +# test: serviceInstantiation +service = Example::HelloWorld::HelloWorldService.new(handler) + +path_prefix = "/twirp/" + service.full_name +server = WEBrick::HTTPServer.new(Port: 8080) +server.mount path_prefix, Rack::Handler::WEBrick, service +server.start diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/ActionController.expected b/ruby/ql/test/library-tests/frameworks/action_controller/ActionController.expected index e17f691b149..4e122b5ba21 100644 --- a/ruby/ql/test/library-tests/frameworks/action_controller/ActionController.expected +++ b/ruby/ql/test/library-tests/frameworks/action_controller/ActionController.expected @@ -3,7 +3,7 @@ actionControllerControllerClasses | controllers/comments_controller.rb:1:1:104:3 | CommentsController | | controllers/foo/bars_controller.rb:3:1:46:3 | BarsController | | controllers/photos_controller.rb:1:1:10:3 | PhotosController | -| controllers/posts_controller.rb:1:1:30:3 | PostsController | +| controllers/posts_controller.rb:1:1:32:3 | PostsController | | controllers/tags_controller.rb:1:1:2:3 | TagsController | | controllers/users/notifications_controller.rb:2:3:5:5 | Users::NotificationsController | | input_access.rb:1:1:50:3 | UsersController | @@ -23,9 +23,9 @@ actionControllerActionMethods | controllers/foo/bars_controller.rb:34:3:39:5 | show_2 | | controllers/photos_controller.rb:3:3:6:5 | show | | controllers/photos_controller.rb:8:3:9:5 | foo | -| controllers/posts_controller.rb:12:3:13:5 | index | -| controllers/posts_controller.rb:15:3:16:5 | show | -| controllers/posts_controller.rb:18:3:19:5 | upvote | +| controllers/posts_controller.rb:12:3:15:5 | index | +| controllers/posts_controller.rb:17:3:18:5 | show | +| controllers/posts_controller.rb:20:3:21:5 | upvote | | controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | | input_access.rb:2:3:49:5 | index | | logging.rb:2:5:8:7 | index | @@ -71,7 +71,7 @@ paramsCalls | controllers/foo/bars_controller.rb:14:10:14:15 | call to params | | controllers/foo/bars_controller.rb:21:21:21:26 | call to params | | controllers/foo/bars_controller.rb:22:10:22:15 | call to params | -| controllers/posts_controller.rb:24:23:24:28 | call to params | +| controllers/posts_controller.rb:26:23:26:28 | call to params | | params_flow.rb:3:10:3:15 | call to params | | params_flow.rb:7:10:7:15 | call to params | | params_flow.rb:11:10:11:15 | call to params | @@ -126,7 +126,7 @@ paramsSources | controllers/foo/bars_controller.rb:14:10:14:15 | call to params | | controllers/foo/bars_controller.rb:21:21:21:26 | call to params | | controllers/foo/bars_controller.rb:22:10:22:15 | call to params | -| controllers/posts_controller.rb:24:23:24:28 | call to params | +| controllers/posts_controller.rb:26:23:26:28 | call to params | | params_flow.rb:3:10:3:15 | call to params | | params_flow.rb:7:10:7:15 | call to params | | params_flow.rb:11:10:11:15 | call to params | @@ -191,7 +191,7 @@ httpInputAccesses | controllers/foo/bars_controller.rb:14:10:14:15 | call to params | ActionController::Metal#params | | controllers/foo/bars_controller.rb:21:21:21:26 | call to params | ActionController::Metal#params | | controllers/foo/bars_controller.rb:22:10:22:15 | call to params | ActionController::Metal#params | -| controllers/posts_controller.rb:24:23:24:28 | call to params | ActionController::Metal#params | +| controllers/posts_controller.rb:26:23:26:28 | call to params | ActionController::Metal#params | | input_access.rb:3:5:3:18 | call to params | ActionDispatch::Request#params | | input_access.rb:4:5:4:22 | call to parameters | ActionDispatch::Request#parameters | | input_access.rb:5:5:5:15 | call to GET | ActionDispatch::Request#GET | @@ -297,6 +297,9 @@ renderCalls | controllers/foo/bars_controller.rb:35:5:35:33 | call to render | | controllers/foo/bars_controller.rb:38:5:38:50 | call to render | | controllers/foo/bars_controller.rb:44:5:44:17 | call to render | +| controllers/posts_controller.rb:13:5:13:51 | call to render | +| controllers/posts_controller.rb:14:5:14:127 | call to render | +| controllers/posts_controller.rb:36:5:36:51 | call to render | httpResponses | controllers/comments_controller.rb:26:5:26:17 | call to body= | controllers/comments_controller.rb:26:21:26:34 | ... = ... | | controllers/comments_controller.rb:36:5:36:37 | call to send_file | controllers/comments_controller.rb:36:24:36:36 | "my-file.ext" | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/Filters.expected b/ruby/ql/test/library-tests/frameworks/action_controller/Filters.expected index 260a818fc41..ad000553281 100644 --- a/ruby/ql/test/library-tests/frameworks/action_controller/Filters.expected +++ b/ruby/ql/test/library-tests/frameworks/action_controller/Filters.expected @@ -42,12 +42,12 @@ | controllers/comments_controller.rb:68:3:70:5 | destroy | controllers/comments_controller.rb:102:3:103:5 | bar | controllers/comments_controller.rb:68:3:70:5 | destroy | | controllers/photos_controller.rb:3:3:6:5 | show | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/photos_controller.rb:3:3:6:5 | show | | controllers/photos_controller.rb:3:3:6:5 | show | controllers/photos_controller.rb:3:3:6:5 | show | controllers/photos_controller.rb:8:3:9:5 | foo | -| controllers/posts_controller.rb:12:3:13:5 | index | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:12:3:13:5 | index | -| controllers/posts_controller.rb:12:3:13:5 | index | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/application_controller.rb:6:3:8:5 | set_user | -| controllers/posts_controller.rb:15:3:16:5 | show | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:15:3:16:5 | show | -| controllers/posts_controller.rb:15:3:16:5 | show | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/posts_controller.rb:23:3:25:5 | set_post | -| controllers/posts_controller.rb:15:3:16:5 | show | controllers/posts_controller.rb:23:3:25:5 | set_post | controllers/application_controller.rb:6:3:8:5 | set_user | -| controllers/posts_controller.rb:18:3:19:5 | upvote | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:18:3:19:5 | upvote | -| controllers/posts_controller.rb:18:3:19:5 | upvote | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/posts_controller.rb:23:3:25:5 | set_post | -| controllers/posts_controller.rb:18:3:19:5 | upvote | controllers/posts_controller.rb:18:3:19:5 | upvote | controllers/posts_controller.rb:27:3:29:5 | log_upvote | -| controllers/posts_controller.rb:18:3:19:5 | upvote | controllers/posts_controller.rb:23:3:25:5 | set_post | controllers/application_controller.rb:6:3:8:5 | set_user | +| controllers/posts_controller.rb:12:3:15:5 | index | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:12:3:15:5 | index | +| controllers/posts_controller.rb:12:3:15:5 | index | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/application_controller.rb:6:3:8:5 | set_user | +| controllers/posts_controller.rb:17:3:18:5 | show | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:17:3:18:5 | show | +| controllers/posts_controller.rb:17:3:18:5 | show | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/posts_controller.rb:25:3:27:5 | set_post | +| controllers/posts_controller.rb:17:3:18:5 | show | controllers/posts_controller.rb:25:3:27:5 | set_post | controllers/application_controller.rb:6:3:8:5 | set_user | +| controllers/posts_controller.rb:20:3:21:5 | upvote | controllers/application_controller.rb:6:3:8:5 | set_user | controllers/posts_controller.rb:20:3:21:5 | upvote | +| controllers/posts_controller.rb:20:3:21:5 | upvote | controllers/application_controller.rb:10:3:12:5 | log_request | controllers/posts_controller.rb:25:3:27:5 | set_post | +| controllers/posts_controller.rb:20:3:21:5 | upvote | controllers/posts_controller.rb:20:3:21:5 | upvote | controllers/posts_controller.rb:29:3:31:5 | log_upvote | +| controllers/posts_controller.rb:20:3:21:5 | upvote | controllers/posts_controller.rb:25:3:27:5 | set_post | controllers/application_controller.rb:6:3:8:5 | set_user | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/controllers/posts_controller.rb b/ruby/ql/test/library-tests/frameworks/action_controller/controllers/posts_controller.rb index ed1fa22c2fa..99412d311a1 100644 --- a/ruby/ql/test/library-tests/frameworks/action_controller/controllers/posts_controller.rb +++ b/ruby/ql/test/library-tests/frameworks/action_controller/controllers/posts_controller.rb @@ -10,6 +10,8 @@ class PostsController < ApplicationController before_action :set_user def index + PostsController.render(template: "posts/index") + PostsController.renderer.render(template: "posts/index", locals: { show_full_post: true }, assigns: { @posts => Post.all }) end def show @@ -28,3 +30,10 @@ class PostsController < ApplicationController Rails.logger.info("Post upvoted: #{@post.id}") end end + +class NotAController + def foo + PostsController.render(template: "posts/index") + end +end + diff --git a/ruby/ql/test/library-tests/frameworks/action_dispatch/ActionDispatch.expected b/ruby/ql/test/library-tests/frameworks/action_dispatch/ActionDispatch.expected new file mode 100644 index 00000000000..4524e715d4f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_dispatch/ActionDispatch.expected @@ -0,0 +1,68 @@ +actionDispatchRoutes +| app/config/routes.rb:2:3:8:5 | call to resources | get | posts | posts | index | +| app/config/routes.rb:2:3:8:5 | call to resources | get | posts/:id | posts | show | +| app/config/routes.rb:3:5:6:7 | call to resources | delete | posts/:post_id/comments/:id | comments | destroy | +| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments | comments | index | +| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments/:id | comments | show | +| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments/new | comments | new | +| app/config/routes.rb:3:5:6:7 | call to resources | get | posts/:post_id/comments:id/edit | comments | edit | +| app/config/routes.rb:3:5:6:7 | call to resources | patch | posts/:post_id/comments/:id | comments | update | +| app/config/routes.rb:3:5:6:7 | call to resources | post | posts/:post_id/comments | comments | create | +| app/config/routes.rb:3:5:6:7 | call to resources | put | posts/:post_id/comments/:id | comments | update | +| app/config/routes.rb:4:7:4:41 | call to resources | post | posts/:post_id/comments/:comment_id/replies | replies | create | +| app/config/routes.rb:5:7:5:28 | call to post | post | posts/:post_id/comments/:comment_id/flag | comments | flag | +| app/config/routes.rb:7:5:7:37 | call to post | post | posts/:post_id/upvote | posts | upvote | +| app/config/routes.rb:11:5:11:54 | call to post | post | destroy_all_posts | posts | destroy_alll | +| app/config/routes.rb:15:5:15:46 | call to get | get | numbers/:number | numbers | show | +| app/config/routes.rb:19:5:19:44 | call to get | get | admin/jobs | background_jobs | index | +| app/config/routes.rb:23:5:23:64 | call to get | get | admin/secrets | secrets | view_secrets | +| app/config/routes.rb:24:5:24:42 | call to delete | delete | admin/:user_id | users | destroy | +| app/config/routes.rb:27:3:27:48 | call to match | get | photos/:id | photos | show | +| app/config/routes.rb:28:3:28:50 | call to match | get | photos/:id | photos | show | +| app/config/routes.rb:29:3:29:69 | call to match | get | photos/:id | photos | show | +| app/config/routes.rb:30:3:30:50 | call to match | delete | photos/:id | photos | show | +| app/config/routes.rb:30:3:30:50 | call to match | get | photos/:id | photos | show | +| app/config/routes.rb:30:3:30:50 | call to match | patch | photos/:id | photos | show | +| app/config/routes.rb:30:3:30:50 | call to match | post | photos/:id | photos | show | +| app/config/routes.rb:30:3:30:50 | call to match | put | photos/:id | photos | show | +| app/config/routes.rb:33:5:33:43 | call to post | post | upgrade | users | start_upgrade | +| app/config/routes.rb:37:5:37:31 | call to get | get | current_billing_cycle | billing/enterprise | current_billing_cycle | +| app/config/routes.rb:40:3:40:40 | call to resource | get | global_config | global_config | show | +| app/config/routes.rb:43:5:45:7 | call to resources | get | foo/bar | foo/bar | index | +| app/config/routes.rb:43:5:45:7 | call to resources | get | foo/bar/:id | foo/bar | show | +| app/config/routes.rb:44:7:44:39 | call to get | get | foo/bar/:bar_id/show_debug | foo/bar | show_debug | +| app/config/routes.rb:49:5:49:95 | call to delete | delete | users/:user/notifications | users/notifications | destroy | +| app/config/routes.rb:50:5:50:94 | call to post | post | users/:user/notifications/:notification_id/mark_as_read | users/notifications | mark_as_read | +actionDispatchControllerMethods +| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:2:3:3:5 | index | +| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:5:3:6:5 | show | +| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:36:5 | index | +| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:38:3:39:5 | show | +| app/config/routes.rb:7:5:7:37 | call to post | app/controllers/posts_controller.rb:8:3:9:5 | upvote | +| app/config/routes.rb:27:3:27:48 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | +| app/config/routes.rb:28:3:28:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | +| app/config/routes.rb:29:3:29:69 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | +| app/config/routes.rb:30:3:30:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show | +| app/config/routes.rb:50:5:50:94 | call to post | app/controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | +underscore +| Foo | foo | +| Foo::Bar | foo/bar | +| Foo::Bar::Baz | foo/bar/baz | +| Foo::Bar::BazQuux | foo/bar/baz_quux | +| FooBar | foo_bar | +| FooBar::Baz | foo_bar/baz | +| HTTPServerRequest | httpserver_request | +| LotsOfCapitalLetters | lots_of_capital_letters | +| invalid | invalid | +mimeTypeInstances +| mime_type.rb:2:6:2:28 | Use getMember("Mime").getContent(element_text/html) | +| mime_type.rb:3:6:3:32 | Use getMember("Mime").getMember("Type").getMethod("new").getReturn() | +| mime_type.rb:4:6:4:35 | Use getMember("Mime").getMember("Type").getMethod("lookup").getReturn() | +| mime_type.rb:5:6:5:43 | Use getMember("Mime").getMember("Type").getMethod("lookup_by_extension").getReturn() | +| mime_type.rb:6:6:6:47 | Use getMember("Mime").getMember("Type").getMethod("register").getReturn() | +| mime_type.rb:7:6:7:64 | Use getMember("Mime").getMember("Type").getMethod("register_alias").getReturn() | +mimeTypeMatchRegExpInterpretations +| mime_type.rb:11:11:11:19 | "foo/bar" | +| mime_type.rb:12:7:12:15 | "foo/bar" | +| mime_type.rb:13:11:13:11 | s | +| mime_type.rb:14:7:14:7 | s | diff --git a/ruby/ql/test/library-tests/frameworks/ActionDispatch.ql b/ruby/ql/test/library-tests/frameworks/action_dispatch/ActionDispatch.ql similarity index 100% rename from ruby/ql/test/library-tests/frameworks/ActionDispatch.ql rename to ruby/ql/test/library-tests/frameworks/action_dispatch/ActionDispatch.ql diff --git a/ruby/ql/test/library-tests/frameworks/app/config/routes.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/config/routes.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/config/routes.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/config/routes.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/comments_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/comments_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/comments_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/comments_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/foo/bars_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/foo/bars_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/foo/bars_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/foo/bars_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/photos_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/photos_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/photos_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/photos_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/posts_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/posts_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/posts_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/posts_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/tags_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/tags_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/tags_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/tags_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/controllers/users/notifications_controller.rb b/ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/users/notifications_controller.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/controllers/users/notifications_controller.rb rename to ruby/ql/test/library-tests/frameworks/action_dispatch/app/controllers/users/notifications_controller.rb diff --git a/ruby/ql/test/library-tests/frameworks/action_view/ActionView.expected b/ruby/ql/test/library-tests/frameworks/action_view/ActionView.expected index 6b228de4219..b0512da2e84 100644 --- a/ruby/ql/test/library-tests/frameworks/action_view/ActionView.expected +++ b/ruby/ql/test/library-tests/frameworks/action_view/ActionView.expected @@ -1 +1,44 @@ +fileSystemResolverAccesses | ActionView.rb:5:39:5:92 | call to new | ActionView.rb:5:74:5:82 | view_path | +| app/controllers/comments_controller.rb:21:5:21:37 | call to send_file | app/controllers/comments_controller.rb:21:24:21:36 | "my-file.ext" | +| app/controllers/foo/bars_controller.rb:1:1:1:14 | call to require | app/controllers/foo/bars_controller.rb:1:9:1:14 | "json" | +rawCalls +| app/views/foo/bars/_widget.html.erb:1:5:1:21 | call to raw | +| app/views/foo/bars/_widget.html.erb:2:5:2:20 | call to raw | +| app/views/foo/bars/_widget.html.erb:3:5:3:29 | call to raw | +| app/views/foo/bars/show.html.erb:1:14:1:29 | call to raw | +| app/views/foo/bars/show.html.erb:2:5:2:21 | call to raw | +| app/views/foo/bars/show.html.erb:3:5:3:20 | call to raw | +| app/views/foo/bars/show.html.erb:4:5:4:29 | call to raw | +| app/views/foo/bars/show.html.erb:5:5:5:21 | call to raw | +| app/views/foo/bars/show.html.erb:7:5:7:19 | call to raw | +renderCalls +| app/controllers/foo/bars_controller.rb:6:5:6:37 | call to render | +| app/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | +| app/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | +| app/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | +| app/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | +| app/views/foo/bars/show.html.erb:31:5:31:89 | call to render | +renderToCalls +| app/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | +| app/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | +linkToCalls +| app/views/foo/bars/show.html.erb:33:5:33:41 | call to link_to | +httpResponses +| app/controllers/comments_controller.rb:11:5:11:17 | call to body= | app/controllers/comments_controller.rb:11:21:11:34 | ... = ... | text/http | +| app/controllers/comments_controller.rb:21:5:21:37 | call to send_file | app/controllers/comments_controller.rb:21:24:21:36 | "my-file.ext" | application/octet-stream | +| app/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string | app/controllers/foo/bars_controller.rb:15:33:15:47 | "foo/bars/show" | text/html | +| app/controllers/foo/bars_controller.rb:23:5:23:76 | call to render | app/controllers/foo/bars_controller.rb:23:12:23:26 | "foo/bars/show" | text/html | +| app/controllers/foo/bars_controller.rb:35:5:35:33 | call to render | app/controllers/foo/bars_controller.rb:35:18:35:33 | call to [] | application/json | +| app/controllers/foo/bars_controller.rb:36:12:36:67 | call to render_to_string | app/controllers/foo/bars_controller.rb:36:29:36:33 | @user | application/json | +| app/controllers/foo/bars_controller.rb:38:5:38:50 | call to render | app/controllers/foo/bars_controller.rb:38:12:38:22 | call to backtrace | text/plain | +| app/controllers/foo/bars_controller.rb:44:5:44:17 | call to render | app/controllers/foo/bars_controller.rb:44:12:44:17 | "show" | text/html | +rawHelperCalls +| helpers.erb:4:1:4:36 | call to simple_format | helpers.erb:4:15:4:15 | call to x | +| helpers.erb:7:1:7:26 | call to truncate | helpers.erb:7:10:7:10 | call to x | +| helpers.erb:10:1:10:29 | call to highlight | helpers.erb:10:11:10:11 | call to x | +| helpers.erb:12:1:12:17 | call to javascript_tag | helpers.erb:12:16:12:16 | call to x | +| helpers.erb:15:1:15:27 | call to content_tag | helpers.erb:15:16:15:16 | call to y | +| helpers.erb:18:1:18:19 | call to tag | helpers.erb:18:5:18:5 | call to x | +| helpers.erb:21:1:21:24 | call to h1 | helpers.erb:21:8:21:8 | call to x | +| helpers.erb:24:1:24:23 | call to p | helpers.erb:24:7:24:7 | call to x | diff --git a/ruby/ql/test/library-tests/frameworks/action_view/ActionView.ql b/ruby/ql/test/library-tests/frameworks/action_view/ActionView.ql index 578f975b8e2..a0c9a1fd299 100644 --- a/ruby/ql/test/library-tests/frameworks/action_view/ActionView.ql +++ b/ruby/ql/test/library-tests/frameworks/action_view/ActionView.ql @@ -1,6 +1,25 @@ -import codeql.ruby.Concepts -import codeql.ruby.DataFlow +private import ruby +private import codeql.ruby.AST +private import codeql.ruby.frameworks.ActionView +private import codeql.ruby.frameworks.Rails +private import codeql.ruby.Concepts query predicate fileSystemResolverAccesses(FileSystemAccess a, DataFlow::Node path) { a.getAPathArgument() = path } + +query predicate rawCalls(RawCall c) { any() } + +query predicate renderCalls(Rails::RenderCall c) { any() } + +query predicate renderToCalls(Rails::RenderToCall c) { any() } + +query predicate linkToCalls(LinkToCall c) { any() } + +query predicate httpResponses(Http::Server::HttpResponse r, DataFlow::Node body, string mimeType) { + r.getBody() = body and r.getMimetype() = mimeType +} + +query predicate rawHelperCalls(ActionView::Helpers::RawHelperCall c, Expr arg) { + arg = c.getRawArgument() +} diff --git a/ruby/ql/test/library-tests/frameworks/app/components/DummyComponent.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/components/DummyComponent.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/components/DummyComponent.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/components/DummyComponent.rb diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/config/routes.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/config/routes.rb new file mode 100644 index 00000000000..9c33071aa50 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/config/routes.rb @@ -0,0 +1,52 @@ +Rails.application.routes.draw do + resources :posts, only: [:show, :index] do + resources :comments do + resources :replies, only: [:create] + post "flag", to: :flag + end + post "upvote", to: "posts#upvote" + end + + if Rails.env.test? + post "destroy_all_posts", to: "posts#destroy_alll" + end + + constraints(number: /[0-9]+/) do + get "/numbers/:number", to: "numbers#show" + end + + scope path: "/admin" do + get "/jobs", to: "background_jobs#index" + end + + scope "/admin" do + get "secrets", controller: "secrets", action: "view_secrets" + delete ":user_id", to: "users#destroy" + end + + match "photos/:id" => "photos#show", via: :get + match "photos/:id", to: "photos#show", via: :get + match "photos/:id", controller: "photos", action: "show", via: :get + match "photos/:id", to: "photos#show", via: :all + + scope controller: "users" do + post "upgrade", action: "start_upgrade" + end + + scope module: "enterprise", controller: "billing" do + get "current_billing_cycle" + end + + resource :global_config, only: [:show] + + namespace :foo do + resources :bar, only: [:index, :show] do + get "show_debug", to: :show_debug + end + end + + scope "/users/:user" do + delete "/notifications", to: "users/notifications#destroy", as: :user_destroy_notifications + post "notifications/:notification_id/mark_as_read", to: "users/notifications#mark_as_read" + end +end diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/comments_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/comments_controller.rb new file mode 100644 index 00000000000..57fac7797bd --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/comments_controller.rb @@ -0,0 +1,40 @@ +class CommentsController < ApplicationController + def index + request.params + request.parameters + request.GET + request.POST + request.query_parameters + request.request_parameters + request.filtered_parameters + + response.body = "some content" + + response.status = 200 + + response.header["Content-Type"] = "text/html" + response.set_header("Content-Length", 100) + response.headers["X-Custom-Header"] = "hi" + response["X-Another-Custom-Header"] = "yes" + response.add_header "X-Yet-Another", "indeed" + + response.send_file("my-file.ext") + + response.request + + response.location = "http://..." # relevant for url redirect query + response.cache_control = "value" + response._cache_control = "value" + response.etag = "value" + response.charset = "value" # sets the charset part of the content-type header + response.content_type = "value" # sets the main part of the content-type header + + response.date = Date.today + response.last_modified = Date.yesterday + response.weak_etag = "value" + response.strong_etag = "value" + end + + def show + end +end diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/foo/bars_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/foo/bars_controller.rb new file mode 100644 index 00000000000..9778b8d5bcc --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/foo/bars_controller.rb @@ -0,0 +1,46 @@ +require 'json' + +class BarsController < ApplicationController + + def index + render template: "foo/bars/index" + end + + def show_debug + user_info = JSON.load cookies[:user_info] + puts "User: #{user_info['name']}" + + @user_website = params[:website] + dt = params[:text] + rendered = render_to_string "foo/bars/show", locals: { display_text: dt, safe_text: "hello" } + puts rendered + redirect_to action: "show" + end + + def show + @user_website = params[:website] + dt = params[:text] + render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" } + end + + def go_back + redirect_back_or_to action: "index" + end + + def go_back_2 + redirect_back fallback_location: { action: "index" } + end + + def show_2 + render json: { some: "data" } + body = render_to_string @user, content_type: "application/json" + rescue => e + render e.backtrace, content_type: "text/plain" + end + + private + + def unreachable_action + render "show" + end +end diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/photos_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/photos_controller.rb new file mode 100644 index 00000000000..0de193b9029 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/photos_controller.rb @@ -0,0 +1,4 @@ +class PhotosController < ApplicationController + def show + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/posts_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/posts_controller.rb new file mode 100644 index 00000000000..9760219cdf2 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/posts_controller.rb @@ -0,0 +1,10 @@ +class PostsController < ApplicationController + def index + end + + def show + end + + def upvote + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/tags_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/tags_controller.rb new file mode 100644 index 00000000000..ba10ea8ea2e --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/tags_controller.rb @@ -0,0 +1,2 @@ +class TagsController < ActionController::Metal +end diff --git a/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/users/notifications_controller.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/users/notifications_controller.rb new file mode 100644 index 00000000000..c5ff9cd3f5f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/app/controllers/users/notifications_controller.rb @@ -0,0 +1,6 @@ +module Users + class NotificationsController < ApplicationController + def mark_as_read + end + end +end \ No newline at end of file diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/mutations/base_mutation.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/mutations/base_mutation.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/mutations/dummy.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/mutations/dummy.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/resolvers/base.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/resolvers/base.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/resolvers/dummy_resolver.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/resolvers/dummy_resolver.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_argument.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_argument.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_field.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_field.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_input_object.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_input_object.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_interface.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_interface.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_object.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/base_object.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/mutation_type.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/mutation_type.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb b/ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/query_type.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb rename to ruby/ql/test/library-tests/frameworks/action_view/app/graphql/types/query_type.rb diff --git a/ruby/ql/test/library-tests/frameworks/app/views/foo/bars/_widget.html.erb b/ruby/ql/test/library-tests/frameworks/action_view/app/views/foo/bars/_widget.html.erb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/views/foo/bars/_widget.html.erb rename to ruby/ql/test/library-tests/frameworks/action_view/app/views/foo/bars/_widget.html.erb diff --git a/ruby/ql/test/library-tests/frameworks/app/views/foo/bars/show.html.erb b/ruby/ql/test/library-tests/frameworks/action_view/app/views/foo/bars/show.html.erb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/app/views/foo/bars/show.html.erb rename to ruby/ql/test/library-tests/frameworks/action_view/app/views/foo/bars/show.html.erb diff --git a/ruby/ql/test/library-tests/frameworks/Core.expected b/ruby/ql/test/library-tests/frameworks/core/Core.expected similarity index 100% rename from ruby/ql/test/library-tests/frameworks/Core.expected rename to ruby/ql/test/library-tests/frameworks/core/Core.expected diff --git a/ruby/ql/test/library-tests/frameworks/Core.ql b/ruby/ql/test/library-tests/frameworks/core/Core.ql similarity index 100% rename from ruby/ql/test/library-tests/frameworks/Core.ql rename to ruby/ql/test/library-tests/frameworks/core/Core.ql diff --git a/ruby/ql/test/library-tests/frameworks/Eval.rb b/ruby/ql/test/library-tests/frameworks/core/Eval.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/Eval.rb rename to ruby/ql/test/library-tests/frameworks/core/Eval.rb diff --git a/ruby/ql/test/library-tests/frameworks/core/Kernel.expected b/ruby/ql/test/library-tests/frameworks/core/Kernel.expected index e2bf37ada74..3d35933fbf6 100644 --- a/ruby/ql/test/library-tests/frameworks/core/Kernel.expected +++ b/ruby/ql/test/library-tests/frameworks/core/Kernel.expected @@ -38,7 +38,10 @@ kernelSpawnCallExecutions | Kernel.rb:68:1:68:61 | call to spawn | | Kernel.rb:69:1:69:71 | call to spawn | sendCallCodeExecutions +| Eval.rb:4:1:4:22 | call to send | Eval.rb:4:6:4:12 | "raise" | +| Eval.rb:7:1:7:19 | call to send | Eval.rb:7:8:7:13 | "push" | | Kernel.rb:2:1:2:22 | call to send | Kernel.rb:2:6:2:12 | "raise" | | Kernel.rb:5:1:5:19 | call to send | Kernel.rb:5:8:5:13 | "push" | evalCallCodeExecutions +| Eval.rb:3:1:3:43 | call to eval | Eval.rb:3:6:3:22 | "raise \\"error\\"" | | Kernel.rb:1:1:1:43 | call to eval | Kernel.rb:1:6:1:22 | "raise \\"error\\"" | diff --git a/ruby/ql/test/library-tests/frameworks/core/Module.expected b/ruby/ql/test/library-tests/frameworks/core/Module.expected index 3e509c94739..615e38bcec1 100644 --- a/ruby/ql/test/library-tests/frameworks/core/Module.expected +++ b/ruby/ql/test/library-tests/frameworks/core/Module.expected @@ -1,6 +1,7 @@ classEvalCallCodeExecutions | Module.rb:29:1:29:47 | call to class_eval | Module.rb:29:16:29:32 | "def foo; 1; end" | moduleEvalCallCodeExecutions +| Eval.rb:24:1:24:54 | call to module_eval | Eval.rb:24:17:24:33 | "def bar; 1; end" | | Module.rb:30:1:30:54 | call to module_eval | Module.rb:30:17:30:33 | "def bar; 1; end" | moduleConstGetCallCodeExecutions | Module.rb:1:1:1:24 | call to const_get | Module.rb:1:18:1:23 | "Math" | diff --git a/ruby/ql/test/library-tests/frameworks/Stdlib.rb b/ruby/ql/test/library-tests/frameworks/core/Stdlib.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/Stdlib.rb rename to ruby/ql/test/library-tests/frameworks/core/Stdlib.rb diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.expected b/ruby/ql/test/library-tests/frameworks/graphql/GraphQL.expected similarity index 100% rename from ruby/ql/test/library-tests/frameworks/GraphQL.expected rename to ruby/ql/test/library-tests/frameworks/graphql/GraphQL.expected diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.ql b/ruby/ql/test/library-tests/frameworks/graphql/GraphQL.ql similarity index 100% rename from ruby/ql/test/library-tests/frameworks/GraphQL.ql rename to ruby/ql/test/library-tests/frameworks/graphql/GraphQL.ql diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/base_mutation.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/base_mutation.rb new file mode 100644 index 00000000000..0749ec0313f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/base_mutation.rb @@ -0,0 +1,8 @@ +module Mutations + class BaseMutation < GraphQL::Schema::RelayClassicMutation + argument_class Types::BaseArgument + field_class Types::BaseField + input_object_class Types::BaseInputObject + object_class Types::BaseObject + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/dummy.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/dummy.rb new file mode 100644 index 00000000000..52f01c3d6eb --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/mutations/dummy.rb @@ -0,0 +1,14 @@ +module Mutations + class Dummy < BaseMutation + argument :something_id, ID, required: false + + def load_something(id) + "Something number #{id}" + end + + def resolve(something:) + system("echo #{something}") + { success: true } + end + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/base.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/base.rb new file mode 100644 index 00000000000..a51595c00a7 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/base.rb @@ -0,0 +1,4 @@ +module Resolvers + class Base < GraphQL::Schema::Resolver + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/dummy_resolver.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/dummy_resolver.rb new file mode 100644 index 00000000000..1fbc927c816 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/resolvers/dummy_resolver.rb @@ -0,0 +1,15 @@ +module Resolvers + class DummyResolver < Resolvers::Base + type String, null: false + argument :something_id, ID, required: true + + def load_something(id) + "Something number #{id}" + end + + def resolve(something:) + system("echo #{something}") + "true" + end + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_argument.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_argument.rb new file mode 100644 index 00000000000..c1bfdabbfee --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_argument.rb @@ -0,0 +1,4 @@ +module Types + class BaseArgument < GraphQL::Schema::Argument + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_field.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_field.rb new file mode 100644 index 00000000000..7142ef7ddb4 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_field.rb @@ -0,0 +1,5 @@ +module Types + class BaseField < GraphQL::Schema::Field + argument_class Types::BaseArgument + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_input_object.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_input_object.rb new file mode 100644 index 00000000000..c97c4796373 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_input_object.rb @@ -0,0 +1,5 @@ +module Types + class BaseInputObject < GraphQL::Schema::InputObject + argument_class Types::BaseArgument + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_interface.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_interface.rb new file mode 100644 index 00000000000..f25c9650044 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_interface.rb @@ -0,0 +1,7 @@ +module Types + module BaseInterface + include GraphQL::Schema::Interface + + field_class Types::BaseField + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_object.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_object.rb new file mode 100644 index 00000000000..1f918414d98 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/base_object.rb @@ -0,0 +1,5 @@ +module Types + class BaseObject < GraphQL::Schema::Object + field_class Types::BaseField + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/mutation_type.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/mutation_type.rb new file mode 100644 index 00000000000..5ef19f95ae6 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/mutation_type.rb @@ -0,0 +1,5 @@ +module Types + class MutationType < Types::BaseObject + field :dummy, mutation: Mutations::Dummy + end +end diff --git a/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/query_type.rb b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/query_type.rb new file mode 100644 index 00000000000..e0bc578a911 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/graphql/app/graphql/types/query_type.rb @@ -0,0 +1,46 @@ +module Types + class QueryType < Types::BaseObject + field :test_field, String, null: false, + description: "An example field added by the generator", + resolver: Resolvers::DummyResolver + + field :with_arg, String, null: false, description: "A field with an argument" do + argument :number, Int, "A number", required: true + end + def with_arg(number:) + system("echo #{number}") + number.to_s + end + + field :with_method, String, null: false, description: "A field with a custom resolver method", resolver_method: :custom_method do + argument :blah_number, Int, "A number", required: true + end + def custom_method(blah_number:, number: nil) + system("echo #{blah_number}") + system("echo #{number}") + blah_number.to_s + end + + field :with_splat, String, null: false, description: "A field with a double-splatted argument" do + argument :something, Int, "A number", required: true + end + def with_splat(**args) + system("echo #{args[:something]}") + args[:something].to_s + end + + field :with_splat_and_named_arg, String, null: false, description: "A field with two named arguments, where the method captures the second via a hash splat param" do + argument :arg1, Int, "A number", required: true + argument :arg2, Int, "Another number", required: true + end + def with_splat_and_named_arg(arg1:, **rest) + system("echo #{arg1}") + system("echo #{rest[:arg2]}") + arg1.to_s + end + + def foo(arg) + system("echo #{arg}") + end + end +end diff --git a/ruby/ql/test/library-tests/frameworks/PosixSpawn.expected b/ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.expected similarity index 100% rename from ruby/ql/test/library-tests/frameworks/PosixSpawn.expected rename to ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.expected diff --git a/ruby/ql/test/library-tests/frameworks/PosixSpawn.ql b/ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.ql similarity index 100% rename from ruby/ql/test/library-tests/frameworks/PosixSpawn.ql rename to ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.ql diff --git a/ruby/ql/test/library-tests/frameworks/PosixSpawn.rb b/ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.rb similarity index 100% rename from ruby/ql/test/library-tests/frameworks/PosixSpawn.rb rename to ruby/ql/test/library-tests/frameworks/posix-spawn/PosixSpawn.rb diff --git a/ruby/ql/test/library-tests/security/CryptoAlgorithms.expected b/ruby/ql/test/library-tests/security/CryptoAlgorithms.expected index 6af41869909..eedddb2df9f 100644 --- a/ruby/ql/test/library-tests/security/CryptoAlgorithms.expected +++ b/ruby/ql/test/library-tests/security/CryptoAlgorithms.expected @@ -12,6 +12,10 @@ weakHashingAlgorithms | SHA0 | | SHA1 | strongHashingAlgorithms +| BLAKE2 | +| BLAKE2B | +| BLAKE2S | +| BLAKE3 | | DSA | | ECDSA256 | | ECDSA384 | @@ -30,6 +34,10 @@ strongHashingAlgorithms | SHA3256 | | SHA3384 | | SHA3512 | +| SHAKE128 | +| SHAKE256 | +| SM3 | +| WHIRLPOOL | weakEncryptionAlgorithms | 3DES | | ARC2 | diff --git a/ruby/ql/test/query-tests/experimental/improper-memoization/improper_memoization.rb b/ruby/ql/test/query-tests/experimental/improper-memoization/improper_memoization.rb index 9b3bee6e663..e1e60209c79 100644 --- a/ruby/ql/test/query-tests/experimental/improper-memoization/improper_memoization.rb +++ b/ruby/ql/test/query-tests/experimental/improper-memoization/improper_memoization.rb @@ -47,54 +47,54 @@ def m6(arg1, arg2) end # Bad: method has parameter but only one result is memoized. -def m7(arg) # $result=BAD +def m7(arg) @m7 ||= begin arg += 3 end @m7 -end +end # $result=BAD # Bad: method has parameter but only one result is memoized. -def m8(arg) # $result=BAD +def m8(arg) @m8 ||= begin long_running_method(arg) end @m8 -end +end # $result=BAD # Bad: method has parameter but only one result is memoized. -def m9(arg) # $result=BAD +def m9(arg) @m9 ||= long_running_method(arg) -end +end # $result=BAD # Bad: method has parameter but only one result is memoized. -def m10(arg1, arg2) # $result=BAD +def m10(arg1, arg2) @m10 ||= long_running_method(arg1, arg2) -end +end # $result=BAD # Bad: `arg2` not used in key. -def m11(arg1, arg2) # $result=BAD +def m11(arg1, arg2) @m11 ||= {} @m11[arg1] ||= long_running_method(arg1, arg2) -end +end # $result=BAD # Bad: `arg2` not used in key. -def m12(arg1, arg2) # $result=BAD +def m12(arg1, arg2) @m12 ||= Hash.new do |h1, arg1| h1[arg1] = result(arg1, arg2) end @m12[arg1] -end +end # $result=BAD # Bad: arg not used in key. -def m13(id:) # $result=BAD +def m13(id:) @m13 ||= Rails.cache.fetch("product_sku/#{id}", expires_in: 30.minutes) do ActiveRecord::Base.transaction do ProductSku.find_by(id: id) end end @m13 -end +end # $result=BAD # Good (FP): arg is used in key via string interpolation. def m14(arg) diff --git a/ruby/ql/test/query-tests/security/cwe-116/IncompleteMultiCharacterSanitization/incomplete_multi_character_sanitization.rb b/ruby/ql/test/query-tests/security/cwe-116/IncompleteMultiCharacterSanitization/incomplete_multi_character_sanitization.rb index 3301b00e709..a9c61a29c21 100644 --- a/ruby/ql/test/query-tests/security/cwe-116/IncompleteMultiCharacterSanitization/incomplete_multi_character_sanitization.rb +++ b/ruby/ql/test/query-tests/security/cwe-116/IncompleteMultiCharacterSanitization/incomplete_multi_character_sanitization.rb @@ -80,9 +80,9 @@ def m9(x) x = x.gsub(/^(\.\.\/?)+/, "") # OK # NOT OK - x = x.gsub(/)<[^<]*)*<\/script>/) do |match| # $ hasResult=html + x = x.gsub(/)<[^<]*)*<\/script>/) do |match| if unknown then match else "" end - end + end # $ hasResult=html x = x.gsub(/<\/?([a-z][a-z0-9]*)\b[^>]*>/i, "") # NOT OK [INCONSISTENCY] $ hasResult=html @@ -113,10 +113,10 @@ def m9(x) x = x.gsub(//, "") # OK - x = x # $ hasResult=path + x = x .gsub(/^\.\//, "") .gsub(/\/\.\//, "/") - .gsub(/[^\/]*\/\.\.\//, "") + .gsub(/[^\/]*\/\.\.\//, "") # $ hasResult=path x end diff --git a/shared/regex/CHANGELOG.md b/shared/regex/CHANGELOG.md index 6fbffd820ce..122ab5362b6 100644 --- a/shared/regex/CHANGELOG.md +++ b/shared/regex/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.7 + +No user-facing changes. + ## 0.0.6 No user-facing changes. diff --git a/shared/regex/change-notes/released/0.0.7.md b/shared/regex/change-notes/released/0.0.7.md new file mode 100644 index 00000000000..84da6f18c42 --- /dev/null +++ b/shared/regex/change-notes/released/0.0.7.md @@ -0,0 +1,3 @@ +## 0.0.7 + +No user-facing changes. diff --git a/shared/regex/codeql-pack.release.yml b/shared/regex/codeql-pack.release.yml index cf398ce02aa..a2a5484910b 100644 --- a/shared/regex/codeql-pack.release.yml +++ b/shared/regex/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.6 +lastReleaseVersion: 0.0.7 diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml index 12294207f32..07b3584d50b 100644 --- a/shared/regex/qlpack.yml +++ b/shared/regex/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/regex -version: 0.0.7-dev +version: 0.0.8-dev groups: shared library: true dependencies: diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md index 59b8e47aca3..4f07ce5c1ec 100644 --- a/shared/ssa/CHANGELOG.md +++ b/shared/ssa/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.11 + +No user-facing changes. + ## 0.0.10 No user-facing changes. diff --git a/shared/ssa/change-notes/released/0.0.11.md b/shared/ssa/change-notes/released/0.0.11.md new file mode 100644 index 00000000000..19a2a55bd68 --- /dev/null +++ b/shared/ssa/change-notes/released/0.0.11.md @@ -0,0 +1,3 @@ +## 0.0.11 + +No user-facing changes. diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml index b740014e5ae..e679dc42092 100644 --- a/shared/ssa/codeql-pack.release.yml +++ b/shared/ssa/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.10 +lastReleaseVersion: 0.0.11 diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index fee841c9975..9f2bad1207f 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/ssa -version: 0.0.11-dev +version: 0.0.12-dev groups: shared library: true diff --git a/shared/tutorial/CHANGELOG.md b/shared/tutorial/CHANGELOG.md index 54503e1a481..3db1262ff44 100644 --- a/shared/tutorial/CHANGELOG.md +++ b/shared/tutorial/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4 + +No user-facing changes. + ## 0.0.3 No user-facing changes. diff --git a/shared/tutorial/change-notes/released/0.0.4.md b/shared/tutorial/change-notes/released/0.0.4.md new file mode 100644 index 00000000000..eefe286a4d8 --- /dev/null +++ b/shared/tutorial/change-notes/released/0.0.4.md @@ -0,0 +1,3 @@ +## 0.0.4 + +No user-facing changes. diff --git a/shared/tutorial/codeql-pack.release.yml b/shared/tutorial/codeql-pack.release.yml index a24b693d1e7..ec411a674bc 100644 --- a/shared/tutorial/codeql-pack.release.yml +++ b/shared/tutorial/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.3 +lastReleaseVersion: 0.0.4 diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml index 9cc8b266cd1..0108cf86a00 100644 --- a/shared/tutorial/qlpack.yml +++ b/shared/tutorial/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/tutorial description: Library for the CodeQL detective tutorials, helping new users learn to write CodeQL queries. -version: 0.0.4-dev +version: 0.0.5-dev groups: shared library: true diff --git a/shared/typetracking/CHANGELOG.md b/shared/typetracking/CHANGELOG.md index a5e0d0a4ff3..203d814ee87 100644 --- a/shared/typetracking/CHANGELOG.md +++ b/shared/typetracking/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4 + +No user-facing changes. + ## 0.0.3 No user-facing changes. diff --git a/shared/typetracking/change-notes/released/0.0.4.md b/shared/typetracking/change-notes/released/0.0.4.md new file mode 100644 index 00000000000..eefe286a4d8 --- /dev/null +++ b/shared/typetracking/change-notes/released/0.0.4.md @@ -0,0 +1,3 @@ +## 0.0.4 + +No user-facing changes. diff --git a/shared/typetracking/codeql-pack.release.yml b/shared/typetracking/codeql-pack.release.yml index a24b693d1e7..ec411a674bc 100644 --- a/shared/typetracking/codeql-pack.release.yml +++ b/shared/typetracking/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.3 +lastReleaseVersion: 0.0.4 diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml index 632e6e5afb3..aeae3429d62 100644 --- a/shared/typetracking/qlpack.yml +++ b/shared/typetracking/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typetracking -version: 0.0.4-dev +version: 0.0.5-dev groups: shared library: true dependencies: diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md index d00e75f5895..5bfc49ecc91 100644 --- a/shared/typos/CHANGELOG.md +++ b/shared/typos/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.11 + +No user-facing changes. + ## 0.0.10 No user-facing changes. diff --git a/shared/typos/change-notes/released/0.0.11.md b/shared/typos/change-notes/released/0.0.11.md new file mode 100644 index 00000000000..19a2a55bd68 --- /dev/null +++ b/shared/typos/change-notes/released/0.0.11.md @@ -0,0 +1,3 @@ +## 0.0.11 + +No user-facing changes. diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml index b740014e5ae..e679dc42092 100644 --- a/shared/typos/codeql-pack.release.yml +++ b/shared/typos/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.10 +lastReleaseVersion: 0.0.11 diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index af24ed34a09..4358c859ee6 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/typos -version: 0.0.11-dev +version: 0.0.12-dev groups: shared library: true diff --git a/shared/util/CHANGELOG.md b/shared/util/CHANGELOG.md index f7fa0fe0e40..60892d241a6 100644 --- a/shared/util/CHANGELOG.md +++ b/shared/util/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4 + +No user-facing changes. + ## 0.0.3 No user-facing changes. diff --git a/shared/util/change-notes/released/0.0.4.md b/shared/util/change-notes/released/0.0.4.md new file mode 100644 index 00000000000..eefe286a4d8 --- /dev/null +++ b/shared/util/change-notes/released/0.0.4.md @@ -0,0 +1,3 @@ +## 0.0.4 + +No user-facing changes. diff --git a/shared/util/codeql-pack.release.yml b/shared/util/codeql-pack.release.yml index a24b693d1e7..ec411a674bc 100644 --- a/shared/util/codeql-pack.release.yml +++ b/shared/util/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.3 +lastReleaseVersion: 0.0.4 diff --git a/shared/util/codeql/util/FileSystem.qll b/shared/util/codeql/util/FileSystem.qll new file mode 100644 index 00000000000..f685cf9c3e3 --- /dev/null +++ b/shared/util/codeql/util/FileSystem.qll @@ -0,0 +1,212 @@ +/** Provides classes for working with files and folders. */ + +/** Provides the input specification of the files and folders implementation. */ +signature module InputSig { + /** + * A base class for files and folders. + * + * Typically `@container`. + */ + class ContainerBase { + /** + * Gets the absolute path of this container. + * + * Typically `containerparent(result, this)`. + */ + string getAbsolutePath(); + + /** Gets the parent container of this container, if any. */ + ContainerBase getParentContainer(); + } + + /** + * A base class for files. + * + * Typically `@file`. + */ + class FileBase extends ContainerBase; + + /** + * A base class for folders. + * + * Typically `@folder`. + */ + class FolderBase extends ContainerBase; + + /** + * Holds if `s` is the source location prefix. + * + * Typically `sourceLocationPrefix(s)`. + */ + predicate hasSourceLocationPrefix(string s); +} + +/** Provides a class hierarchy for working with files and folders. */ +module Make { + /** A file or folder. */ + class Container instanceof Input::ContainerBase { + /** Gets a file or sub-folder in this container. */ + Container getAChildContainer() { this = result.getParentContainer() } + + /** Gets a file in this container. */ + File getAFile() { result = this.getAChildContainer() } + + /** Gets a sub-folder in this container. */ + Folder getAFolder() { result = this.getAChildContainer() } + + /** + * Gets the absolute, canonical path of this container, using forward slashes + * as path separator. + * + * The path starts with a _root prefix_ followed by zero or more _path + * segments_ separated by forward slashes. + * + * The root prefix is of one of the following forms: + * + * 1. A single forward slash `/` (Unix-style) + * 2. An upper-case drive letter followed by a colon and a forward slash, + * such as `C:/` (Windows-style) + * 3. Two forward slashes, a computer name, and then another forward slash, + * such as `//FileServer/` (UNC-style) + * + * Path segments are never empty (that is, absolute paths never contain two + * contiguous slashes, except as part of a UNC-style root prefix). Also, path + * segments never contain forward slashes, and no path segment is of the + * form `.` (one dot) or `..` (two dots). + * + * Note that an absolute path never ends with a forward slash, except if it is + * a bare root prefix, that is, the path has no path segments. A container + * whose absolute path has no segments is always a `Folder`, not a `File`. + */ + string getAbsolutePath() { result = super.getAbsolutePath() } + + /** + * Gets the base name of this container including extension, that is, the last + * segment of its absolute path, or the empty string if it has no segments. + * + * Here are some examples of absolute paths and the corresponding base names + * (surrounded with quotes to avoid ambiguity): + * + * + * + * + * + * + * + * + * + *
    Absolute pathBase name
    "/tmp/tst.txt""tst.txt"
    "C:/Program Files (x86)""Program Files (x86)"
    "/"""
    "C:/"""
    "D:/"""
    "//FileServer/"""
    + */ + string getBaseName() { + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + } + + /** + * Gets the extension of this container, that is, the suffix of its base name + * after the last dot character, if any. + * + * In particular, + * + * - if the name does not include a dot, there is no extension, so this + * predicate has no result; + * - if the name ends in a dot, the extension is the empty string; + * - if the name contains multiple dots, the extension follows the last dot. + * + * Here are some examples of absolute paths and the corresponding extensions + * (surrounded with quotes to avoid ambiguity): + * + * + * + * + * + * + * + * + *
    Absolute pathExtension
    "/tmp/tst.txt""txt"
    "/tmp/.classpath""classpath"
    "/bin/bash"not defined
    "/tmp/tst2."""
    "/tmp/x.tar.gz""gz"
    + */ + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } + + /** Gets the file in this container that has the given `baseName`, if any. */ + File getFile(string baseName) { + result = this.getAFile() and + result.getBaseName() = baseName + } + + /** Gets the sub-folder in this container that has the given `baseName`, if any. */ + Folder getFolder(string baseName) { + result = this.getAFolder() and + result.getBaseName() = baseName + } + + /** Gets the parent container of this file or folder, if any. */ + Container getParentContainer() { result = super.getParentContainer() } + + /** + * Gets the relative path of this file or folder from the root folder of the + * analyzed source location. The relative path of the root folder itself is + * the empty string. + * + * This has no result if the container is outside the source root, that is, + * if the root folder is not a reflexive, transitive parent of this container. + */ + string getRelativePath() { + exists(string absPath, string pref | + absPath = this.getAbsolutePath() and Input::hasSourceLocationPrefix(pref) + | + absPath = pref and result = "" + or + absPath = pref.regexpReplaceAll("/$", "") + "/" + result and + not result.matches("/%") + ) + } + + /** + * Gets the stem of this container, that is, the prefix of its base name up to + * (but not including) the last dot character if there is one, or the entire + * base name if there is not. + * + * Here are some examples of absolute paths and the corresponding stems + * (surrounded with quotes to avoid ambiguity): + * + * + * + * + * + * + * + * + *
    Absolute pathStem
    "/tmp/tst.txt""tst"
    "/tmp/.classpath"""
    "/bin/bash""bash"
    "/tmp/tst2.""tst2"
    "/tmp/x.tar.gz""x.tar"
    + */ + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } + + /** + * Gets a URL representing the location of this container. + * + * For more information see https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls. + */ + string getURL() { none() } + + /** + * Gets a textual representation of the path of this container. + * + * This is the absolute path of the container. + */ + string toString() { result = this.getAbsolutePath() } + } + + /** A folder. */ + class Folder extends Container instanceof Input::FolderBase { + /** Gets the URL of this folder. */ + override string getURL() { result = "folder://" + this.getAbsolutePath() } + } + + /** A file. */ + class File extends Container instanceof Input::FileBase { + /** Gets the URL of this file. */ + override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } + } +} diff --git a/shared/util/codeql/util/test/InlineExpectationsTest.qll b/shared/util/codeql/util/test/InlineExpectationsTest.qll index 0c4fd403f4f..c297e609a73 100644 --- a/shared/util/codeql/util/test/InlineExpectationsTest.qll +++ b/shared/util/codeql/util/test/InlineExpectationsTest.qll @@ -384,7 +384,7 @@ module Make { la = a.getLocation() and pragma[only_bind_into](lb) = b.getLocation() and pragma[only_bind_into](la).hasLocationInfo(fname, line, _, _, _) and - lb.hasLocationInfo(fname, line, _, _, _) + lb.hasLocationInfo(fname, _, _, line, _) ) } diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml index 469f40a4d3e..54aa156c0cd 100644 --- a/shared/util/qlpack.yml +++ b/shared/util/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/util -version: 0.0.4-dev +version: 0.0.5-dev groups: shared library: true dependencies: diff --git a/swift/.gitignore b/swift/.gitignore index 28451c72aaa..445d287f34a 100644 --- a/swift/.gitignore +++ b/swift/.gitignore @@ -11,5 +11,6 @@ compile_commands.json /.idea /cmake* -# VSCode default build directory +# VSCode default build directory and project directory /build +/.vscode diff --git a/swift/BUILD.bazel b/swift/BUILD.bazel index bafbe01f712..eb7e6a86997 100644 --- a/swift/BUILD.bazel +++ b/swift/BUILD.bazel @@ -15,6 +15,12 @@ filegroup( visibility = ["//swift:__subpackages__"], ) +filegroup( + name = "codegen_conf", + srcs = ["codegen.conf"], + visibility = ["//swift:__subpackages__"], +) + pkg_files( name = "dbscheme_files", srcs = [ diff --git a/swift/README.md b/swift/README.md index b6d7f1d57d2..766c5ff1dce 100644 --- a/swift/README.md +++ b/swift/README.md @@ -39,6 +39,8 @@ bazel run //swift/codegen to update generated files. This can be shortened to `bazel run codegen` if you are in the `swift` directory. +You can also run `../misc/codegen/codegen.py`, as long as you are beneath the `swift` directory. + ## IDE setup ### CLion and the native bazel plugin diff --git a/swift/actions/build-and-test/action.yml b/swift/actions/build-and-test/action.yml index c0c1e7f7e31..2e084e9a97b 100644 --- a/swift/actions/build-and-test/action.yml +++ b/swift/actions/build-and-test/action.yml @@ -62,7 +62,7 @@ runs: if : ${{ github.event_name == 'pull_request' }} shell: bash run: | - bazel test //swift/codegen/test + bazel test //misc/codegen/test - name: Run qltest tests if : ${{ github.event_name == 'pull_request' }} shell: bash diff --git a/swift/actions/run-integration-tests/action.yml b/swift/actions/run-integration-tests/action.yml index 163f572acde..bf46b22558f 100644 --- a/swift/actions/run-integration-tests/action.yml +++ b/swift/actions/run-integration-tests/action.yml @@ -13,7 +13,7 @@ runs: - uses: actions/setup-python@v4 with: python-version-file: 'swift/.python-version' - - uses: swift-actions/setup-swift@194625b58a582570f61cc707c3b558086c26b723 + - uses: swift-actions/setup-swift@da0e3e04b5e3e15dbc3861bd835ad9f0afe56296 with: swift-version: "${{steps.get_swift_version.outputs.version}}" - uses: ./.github/actions/fetch-codeql diff --git a/swift/codegen.conf b/swift/codegen.conf new file mode 100644 index 00000000000..b620e52d04f --- /dev/null +++ b/swift/codegen.conf @@ -0,0 +1,9 @@ +# configuration file for Swift code generation default options +--generate=dbscheme,ql +--dbscheme=ql/lib/swift.dbscheme +--ql-output=ql/lib/codeql/swift/generated +--ql-stub-output=ql/lib/codeql/swift/elements +--ql-test-output=ql/test/extractor-tests/generated +--generated-registry=ql/.generated.list +--script-name=codegen/codegen.py +--trap-library=swift/extractor/trap diff --git a/swift/codegen/BUILD.bazel b/swift/codegen/BUILD.bazel index 2e9d2ab835a..bc807e9329a 100644 --- a/swift/codegen/BUILD.bazel +++ b/swift/codegen/BUILD.bazel @@ -1,16 +1,15 @@ -load("@swift_codegen_deps//:requirements.bzl", "requirement") +load("@bazel_skylib//rules:native_binary.bzl", "native_binary") -py_binary( +native_binary( name = "codegen", - srcs = ["codegen.py"], + out = "codegen", + src = "//misc/codegen", data = [ "//swift:schema", - "//swift:schema_includes", - "//swift/codegen/templates:cpp", - "//swift/codegen/templates:trap", + "//swift:codegen_conf", + ], + args = [ + "--configuration-file=$(location //swift:codegen_conf)", ], visibility = ["//swift:__subpackages__"], - deps = [ - "//swift/codegen/generators", - ], ) diff --git a/swift/codegen/README.md b/swift/codegen/README.md index db94d327da6..eb869cf6a99 100644 --- a/swift/codegen/README.md +++ b/swift/codegen/README.md @@ -1,44 +1,10 @@ -# Code generation suite +This package aliases [`misc/codegen`](../misc/codegen) providing the Swift-specific options +in [`swift/codegen.conf`](../codegen.conf). -This directory contains the code generation suite used by the Swift extractor and the QL library. This suite will use -the abstract class specification of [`schema.yml`](schema.yml) to generate: - -* [the `dbscheme` file](../ql/lib/swift.dbscheme) (see [`dbschemegen.py`](generators/dbschemegen.py)) -* [the QL generated code](../ql/lib/codeql/swift/generated) and when - appropriate [the corresponding stubs](../ql/lib/codeql/swift/elements) (see [`qlgen.py`](generators/qlgen.py)) -* C++ tags and trap entries (see [`trapgen.py`](generators/trapgen.py)) -* C++ structured classes (see [`cppgen.py`](generators/cppgen.py)) - -## Usage - -By default `bazel run //swift/codegen` will update all checked-in generated files (`dbscheme` and QL sources). You can -append `--` followed by other options to tweak the behaviour, which is mainly intended for debugging. -See `bazel run //swift/codegen -- --help` for a list of all options. In particular `--generate` can be used with a comma -separated list to select what to generate (choosing among `dbscheme`, `ql`, `trap` and `cpp`). +Running `bazel run //swift/codegen` will generate all checked in +files ([dbscheme](../ql/lib/swift.dbscheme), [QL generated code](../ql/lib/codeql/swift/generated), +[generated QL stubs](../ql/lib/codeql/swift/elements), [generated QL tests](../ql/test/extractor-tests/generated)). C++ code is generated during build (see [`swift/extractor/trap/BUILD.bazel`](../extractor/trap/BUILD.bazel)). After a -build you can browse the generated code in `bazel-bin/swift/extractor/trap/generated`. - -For debugging you can also run `./codegen.py` directly. You must then ensure dependencies are installed, which you can -with the command - -```bash -pip3 install -r ./requirements.txt -``` - -## Implementation notes - -The suite uses [mustache templating](https://mustache.github.io/) for generation. Templates are -in [the `templates` directory](templates), prefixed with the generation target they are used for. - -Rather than passing dictionaries to the templating engine, python dataclasses are used as defined -in [the `lib` directory](lib). For each of the four generation targets the entry point for the implementation is -specified as the `generate` function in the modules within [the `generators` directory](generators). - -Finally, [`codegen.py`](codegen.py) is the driver script gluing everything together and specifying the command line -options. - -Unit tests are in [the `test` directory](test) and can be run via `bazel test //swift/codegen/test`. - -For more details about each specific generation target, please refer to the module docstrings -in [the `generators` directory](generators). +build you can browse the generated code in `bazel-bin/swift/extractor/trap/generated` from the root of the `codeql` +repository. diff --git a/swift/codegen/codegen.py b/swift/codegen/codegen.py deleted file mode 100755 index f9c85ce6049..00000000000 --- a/swift/codegen/codegen.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -""" Driver script to run all code generation """ - -import argparse -import logging -import os -import sys -import pathlib -import typing - -if 'BUILD_WORKSPACE_DIRECTORY' not in os.environ: - # we are not running with `bazel run`, set up module search path - _repo_root = pathlib.Path(__file__).resolve().parents[2] - sys.path.append(str(_repo_root)) - -from swift.codegen.lib import render, paths -from swift.codegen.generators import generate - - -def _parse_args() -> argparse.Namespace: - p = argparse.ArgumentParser(description="Code generation suite") - p.add_argument("--generate", type=lambda x: x.split(","), default=["dbscheme", "ql"], - help="specify what targets to generate as a comma separated list, choosing among dbscheme, ql, trap " - "and cpp") - p.add_argument("--verbose", "-v", action="store_true", help="print more information") - p.add_argument("--quiet", "-q", action="store_true", help="only print errors") - p.add_argument("--swift-dir", type=_abspath, default=paths.swift_dir, - help="the directory that should be regarded as the root of the swift codebase. Used to compute QL " - "imports and in some comments (default %(default)s)") - p.add_argument("--schema", type=_abspath, default=paths.swift_dir / "schema.py", - help="input schema file (default %(default)s)") - p.add_argument("--dbscheme", type=_abspath, default=paths.swift_dir / "ql/lib/swift.dbscheme", - help="output file for dbscheme generation, input file for trap generation (default %(default)s)") - p.add_argument("--ql-output", type=_abspath, default=paths.swift_dir / "ql/lib/codeql/swift/generated", - help="output directory for generated QL files (default %(default)s)") - p.add_argument("--ql-stub-output", type=_abspath, default=paths.swift_dir / "ql/lib/codeql/swift/elements", - help="output directory for QL stub/customization files (default %(default)s). Defines also the " - "generated qll file importing every class file") - p.add_argument("--ql-test-output", type=_abspath, default=paths.swift_dir / "ql/test/extractor-tests/generated", - help="output directory for QL generated extractor test files (default %(default)s)") - p.add_argument("--ql-format", action="store_true", default=True, - help="use codeql to autoformat QL files (which is the default)") - p.add_argument("--no-ql-format", action="store_false", dest="ql_format", help="do not format QL files") - p.add_argument("--codeql-binary", default="codeql", help="command to use for QL formatting (default %(default)s)") - p.add_argument("--cpp-output", type=_abspath, - help="output directory for generated C++ files, required if trap or cpp is provided to --generate") - p.add_argument("--generated-registry", type=_abspath, default=paths.swift_dir / "ql/.generated.list", - help="registry file containing information about checked-in generated code") - p.add_argument("--force", "-f", action="store_true", - help="generate all files without skipping unchanged files and overwriting modified ones") - return p.parse_args() - - -def _abspath(x: str) -> typing.Optional[pathlib.Path]: - return pathlib.Path(x).resolve() if x else None - - -def run(): - opts = _parse_args() - if opts.verbose: - log_level = logging.DEBUG - elif opts.quiet: - log_level = logging.ERROR - else: - log_level = logging.INFO - logging.basicConfig(format="{levelname} {message}", style='{', level=log_level) - for target in opts.generate: - generate(target, opts, render.Renderer(opts.swift_dir)) - - -if __name__ == "__main__": - run() diff --git a/swift/codegen/generators/BUILD.bazel b/swift/codegen/generators/BUILD.bazel deleted file mode 100644 index 94285e24015..00000000000 --- a/swift/codegen/generators/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -load("@swift_codegen_deps//:requirements.bzl", "requirement") - -py_library( - name = "generators", - srcs = glob(["*.py"]), - visibility = ["//swift/codegen:__subpackages__"], - deps = [ - "//swift/codegen/lib", - requirement("toposort"), - ], -) diff --git a/swift/codegen/lib/BUILD.bazel b/swift/codegen/lib/BUILD.bazel deleted file mode 100644 index 6298b6d195e..00000000000 --- a/swift/codegen/lib/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -load("@swift_codegen_deps//:requirements.bzl", "requirement") - -py_library( - name = "lib", - srcs = glob(["**/*.py"]), - visibility = ["//swift/codegen:__subpackages__"], - deps = [ - requirement("pystache"), - requirement("pyyaml"), - requirement("inflection"), - ], -) diff --git a/swift/codegen/lib/schema/__init__.py b/swift/codegen/lib/schema/__init__.py deleted file mode 100644 index 23e80ae8195..00000000000 --- a/swift/codegen/lib/schema/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .schema import * diff --git a/swift/codegen/templates/ql_stub.mustache b/swift/codegen/templates/ql_stub.mustache deleted file mode 100644 index d15127d9870..00000000000 --- a/swift/codegen/templates/ql_stub.mustache +++ /dev/null @@ -1,9 +0,0 @@ -// generated by {{generator}}, remove this comment if you wish to edit this file -private import {{base_import}} - -{{#ql_internal}} -/** - * INTERNAL: Do not use. - */ -{{/ql_internal}} -class {{name}} extends Generated::{{name}} {} diff --git a/swift/codegen/templates/ql_test_missing.mustache b/swift/codegen/templates/ql_test_missing.mustache deleted file mode 100644 index 0343d40c2aa..00000000000 --- a/swift/codegen/templates/ql_test_missing.mustache +++ /dev/null @@ -1,4 +0,0 @@ -// generated by {{generator}} - -After a swift source file is added in this directory and {{generator}} is run again, test queries -will appear and this file will be deleted diff --git a/swift/extractor/trap/BUILD.bazel b/swift/extractor/trap/BUILD.bazel index 42725dbfb35..0db9b3b3248 100644 --- a/swift/extractor/trap/BUILD.bazel +++ b/swift/extractor/trap/BUILD.bazel @@ -14,12 +14,16 @@ genrule( for ext in ("h", "cpp") ], cmd = " ".join([ - "$(location //swift/codegen)", + "$(location //misc/codegen)", "--generate=dbscheme,trap,cpp", - "--dbscheme $(RULEDIR)/generated/swift.dbscheme", - "--cpp-output $(RULEDIR)/generated", + "--dbscheme=$(RULEDIR)/generated/swift.dbscheme", + "--cpp-output=$(RULEDIR)/generated", + "--trap-library=swift/extractor/trap", + "--use-current-dir", + "--schema=$(location //swift:schema)", + "--script-name=codegen/codegen.py", ]), - exec_tools = ["//swift/codegen"], + exec_tools = ["//misc/codegen", "//swift:schema"], ) filegroup( diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 80b5bc94c24..5f97a0e829c 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -1,77 +1,77 @@ ql/lib/codeql/swift/elements/AvailabilityInfoConstructor.qll 15100f8446c961ca57871ac296c854a19678a84ebaa8faac0b6eb1377a3e0f77 f079769d6e7f9e38995e196863e11108fc1bc42e8f037d6f6bb51cfd351a3465 -ql/lib/codeql/swift/elements/AvailabilitySpec.qll 1e885dc834114454ee7dc1c7127cabcf4af1cb7d8ce634d60bb60f20e630de53 893fc1c2f8317af35dc9039e4c43c4554c4502993d9f0bb0debf8e0e760670bb +ql/lib/codeql/swift/elements/AvailabilitySpec.qll c38bfdebf34bb32463c80870f3dd45d99793bfa9511d33366d6a8a771f5d22bf 893fc1c2f8317af35dc9039e4c43c4554c4502993d9f0bb0debf8e0e760670bb ql/lib/codeql/swift/elements/CommentConstructor.qll c5a4c55fb26e57a9b4efcff329b428f7de22406b35198d99290b6e646794777a 326365475f2fda857ffa00e1c7841089660eca02d739400b6d62ed6f39ea4d03 -ql/lib/codeql/swift/elements/DbFile.qll 9e0f3c54075f75af82a9c917777755f47cb04a5777b064f5cba4a951414ac004 a3b08dd6ccd18d1a5f6f29b829da473c28a921e8d626b264b4b73515a49164f9 +ql/lib/codeql/swift/elements/DbFile.qll 7f94f506d4549233576781de58a538f427179aecb4f3ecbfec4a7c39a1b6e54e a3b08dd6ccd18d1a5f6f29b829da473c28a921e8d626b264b4b73515a49164f9 ql/lib/codeql/swift/elements/DbFileConstructor.qll 2913b16780f4369b405a088bb70f3b0f941b2978e8827ed30745f2ab7ba0cd8e c21b21b100d0b245bb1d498b4c3696db73dd710a5be211c6b825ebf733681da7 -ql/lib/codeql/swift/elements/DbLocation.qll e3e7bf56c7857329e250a44e9df1ccb31f6c2ada47d5199d549b4b92b44bc2f8 aa46535db08966b8045ceb2820b9fd580637272ae4e487192ee57b6215c16e49 +ql/lib/codeql/swift/elements/DbLocation.qll 2b07fe465cc6ea0e876892d8312bedca35d2bef5167b338b0ef5b6101f71693d aa46535db08966b8045ceb2820b9fd580637272ae4e487192ee57b6215c16e49 ql/lib/codeql/swift/elements/DbLocationConstructor.qll 88366e22ba40eaaee097f413130117925dda488f1bcbd3989e301e86dd394df3 c61b32994d403a8c4f85c26251e24ffb8c6ea34dbbe935872d868ccbfb6c1ff6 ql/lib/codeql/swift/elements/DiagnosticsConstructor.qll 6a3e312f3ed57465747c672cbb6d615eca89f42586519221d2973ac3e2ab052c a010ef546f9ed2a75b812ee47db00110056b3076b1f939efa2addb000c327427 -ql/lib/codeql/swift/elements/ErrorElement.qll 6b6be3731a2fd178e5093ddebb7cd519ecc5fbbd549bd4dbd5f69687791c3630 ab0028bab8a9ed14c6b4bfe0f8a10e4768ea1e21f86b495258021ab9b8e65aeb +ql/lib/codeql/swift/elements/ErrorElement.qll e054242b883bcc7fe1e2ee844268325a0a0b83486d5c7b4e334c73a5f8bd1d9f ab0028bab8a9ed14c6b4bfe0f8a10e4768ea1e21f86b495258021ab9b8e65aeb ql/lib/codeql/swift/elements/OtherAvailabilitySpecConstructor.qll fe03628ffbad9369e4b6bf325a58a3013b621090eecd9e01a76710e0d234d66a 0b7ffc7ed88d2b0da9aad86d83272daf124a4597c0fee1184f7d2f3511063afd ql/lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll ce9cc9b15eff28cf0f9ef94f1d7a9dbfbbb2fb64c0053c2b537046784fcd6ee6 8b776cb89ec44704babbce7ac69efb534bf0925ca43f04e7a7dc795435404393 ql/lib/codeql/swift/elements/UnspecifiedElementConstructor.qll 0d179f8189f6268916f88c78a2665f8d4e78dc71e71b6229354677e915ac505d e8f5c313b7d8b0e93cee84151a5f080013d2ca502f3facbbde4cdb0889bc7f8e -ql/lib/codeql/swift/elements/decl/AbstractStorageDecl.qll 6196ecc35d358e6fe1c34b0478c0479acd0f0de67a64daac4d814af90a87d514 74a74330a953d16ce1cc19b2dbabdf8c8ff0fc3d250d101b8108a6597844e179 -ql/lib/codeql/swift/elements/decl/AbstractTypeParamDecl.qll 83950437007703c0f35ef154f46577d8754fb191c93772ff718b29107ce8852e 737ad9c857c079605e84dc7ebaecbafa86fe129283756b98e6e574ac9e24c22c +ql/lib/codeql/swift/elements/decl/AbstractStorageDecl.qll 5cfb9920263784224359ebd60a67ec0b46a7ea60d550d782eb1283d968386a66 74a74330a953d16ce1cc19b2dbabdf8c8ff0fc3d250d101b8108a6597844e179 +ql/lib/codeql/swift/elements/decl/AbstractTypeParamDecl.qll 1847039787c20c187f2df25ea15d645d7225e1f1fd2ca543f19927fe3161fd09 737ad9c857c079605e84dc7ebaecbafa86fe129283756b98e6e574ac9e24c22c ql/lib/codeql/swift/elements/decl/AccessorDeclConstructor.qll 08376434fd14a2b07280e931d3e22d3eafd2063d745f7c78cad0f9fd7e6156ba 6f74d15a88433953998a07eb2131841679a88cb13efb0569ed9b5502c4a2e362 -ql/lib/codeql/swift/elements/decl/AssociatedTypeDecl.qll ae6107c8d9ee9affa7e8430a4d8cd58879578eafcfba668275af4d20f8ea9c53 e81dc740623b4e2c75f83104acaa3d2b6cc6d001dd36a8520c381e0de10e15c4 +ql/lib/codeql/swift/elements/decl/AssociatedTypeDecl.qll 2f6f634fe6e3b69f1925aff0d216680962a3aaa3205bf3a89e2b66394be48f8e e81dc740623b4e2c75f83104acaa3d2b6cc6d001dd36a8520c381e0de10e15c4 ql/lib/codeql/swift/elements/decl/AssociatedTypeDeclConstructor.qll ec9007ea072ff22c367f40da69db2f0a8463bb411bbfd33e2d6c8b489a496027 631f688a8410ddcfbaa575fa2f8ffcdbc1b51ee37639b337c804ca1d5af56e0c ql/lib/codeql/swift/elements/decl/CapturedDeclConstructor.qll 4a33802b047de8d52778c262329f17b88de79c2b3162ebfa3d2b1d40dbf97041 0ed1c94469236252cf81e014138a6b2e6478e3b194512ba36e2a43e03e46cc4a -ql/lib/codeql/swift/elements/decl/ClassDecl.qll 225405ad04e5e959319fbc1ea086ec4eab0b66f5671ebc58290cce45e4103c51 ac681bdc1770a823ea529456f32b1da7b389621254ccd9102e6a49136c53854b +ql/lib/codeql/swift/elements/decl/ClassDecl.qll 40dd7d0d66217023c8f5695eac862b38428d8f2431635f62a65b336c3cc0e9bb ac681bdc1770a823ea529456f32b1da7b389621254ccd9102e6a49136c53854b ql/lib/codeql/swift/elements/decl/ClassDeclConstructor.qll 0092ab4b76cd858489d76be94a43442c0e5f395b1d5684309674957e107979b7 9bc496e483feb88552ca0d48e32039aa4566f4612fc27073fea48ad954985d46 -ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll 7dd23b6145977ec6ca60dd39cf9db09673e0340cdb8de2080279c83599ccd831 3a07a73dc11ef06ddaeb3d401748ef14a1ee66447c86d2e8c8f187dda92b34a2 +ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll 43f54876f39f58beb1d0b8293976648d1e4f5585046a502835eb7befb278f6b0 3a07a73dc11ef06ddaeb3d401748ef14a1ee66447c86d2e8c8f187dda92b34a2 ql/lib/codeql/swift/elements/decl/ConcreteFuncDeclConstructor.qll 4eb2e9dc8b4c93e457bb594085d8f50862dc07a712ce7a0f2dee7f108467ce3e 1f994d6ae1ca2e4fd5da075b70ea22322181bdaf43034face1e82ef353fe34bf -ql/lib/codeql/swift/elements/decl/ConcreteVarDecl.qll be33f40e8870a10aec413f35d8f62a502d7d5dd8a52665730740e880566206d7 d821efa43c6d83aedfb959500de42c5ecabbf856f8556f739bc6cec30a88dfab +ql/lib/codeql/swift/elements/decl/ConcreteVarDecl.qll 94bcbdd91f461295c5b6b49fa597b7e3384556c2383ad0c2a7c58276bade79e6 d821efa43c6d83aedfb959500de42c5ecabbf856f8556f739bc6cec30a88dfab ql/lib/codeql/swift/elements/decl/ConcreteVarDeclConstructor.qll 4b6a9f458db5437f9351b14464b3809a78194029554ea818b3e18272c17afba3 a60d695b0d0ffa917ad01908bec2beaa663e644eddb00fb370fbc906623775d4 ql/lib/codeql/swift/elements/decl/ConstructorDeclConstructor.qll ba5cc6f440cba3d47b364a37febd64f85941cdc0237db52a2b8844d1dc75d483 9fc039ca7a0f33f03b3f573186f02efecbac0c2e0dc5abba5d47876ca26390fe ql/lib/codeql/swift/elements/decl/DestructorDeclConstructor.qll c33b113a3ccb0b1bfd9aad8b909940776da5fdb8a24e1b998c5ebde3903be981 155ad928fbebf9688eec30a2cf61d9a2d4cd15d1161dc3f6202e6331bdb3a56a ql/lib/codeql/swift/elements/decl/EnumCaseDeclConstructor.qll 8c907544170671f713a8665d294eeefdbe78a607c2f16e2c630ea9c33f484baf eec83efc930683628185dbdad8f73311aad510074d168a53d85ea09d13f1f7e1 -ql/lib/codeql/swift/elements/decl/EnumDecl.qll 04271e164379af3a33eb060d230b768878e06acc37c3d132cad089a2c663c6c4 779940ebdbd510eb651972c57eb84b04af39c44ef59a8c307a44549ab730febb +ql/lib/codeql/swift/elements/decl/EnumDecl.qll 29f9d8cbfb19c174af9a666162fd918af7f962fa5d97756105e78d5eec38cb9e 779940ebdbd510eb651972c57eb84b04af39c44ef59a8c307a44549ab730febb ql/lib/codeql/swift/elements/decl/EnumDeclConstructor.qll 642bbfb71e917d84695622f3b2c7b36bf5be4e185358609810267ab1fc4e221b f6e06d79e7ff65fbabf72c553508b67406fb59c577215d28cc47971d34b6af05 ql/lib/codeql/swift/elements/decl/EnumElementDeclConstructor.qll 736074246a795c14a30a8ec7bb8da595a729983187887294e485487309919dc6 4614fb380fad7af1b5fb8afce920f3e7350378254ece60d19722046046672fbb ql/lib/codeql/swift/elements/decl/ExtensionDeclConstructor.qll 4f811e3332720327d2b9019edbb2fa70fb24322e72881afc040e7927452409d6 554f9832311dfc30762507e0bd4b25c5b6fdb9d0c4e8252cc5a1ef1033fafacb -ql/lib/codeql/swift/elements/decl/FuncDecl.qll 47ff5eaccc79944bb01ad819a4a9e373475d7511d477e76226538fc4efc9c88d ba8e48682e93af0804e66f5bf0207049e291a0c1430a872252dc67af17ea700a -ql/lib/codeql/swift/elements/decl/GenericContext.qll b8f21d625cfdccc201201e0d84aab7b5c1e7ccaec21ee788ac425916be8f8ac9 4747af5faf0a93d7508e0ec58021a842ca5ec41831b5d71cbc7fce2a2389a820 -ql/lib/codeql/swift/elements/decl/GenericTypeDecl.qll 774e087cc7208a4fe5df753a848191f4b986265b2b74856a52049aeb018c937a 42e1e3e055f3e5fa70c8624910d635ab10fe4015d378be9e1e6e1adb39f0dc40 -ql/lib/codeql/swift/elements/decl/GenericTypeParamDecl.qll bbcf2844cb26435e3af6d58c2b37ffeee3295a5f3330fbee34881fada7bde85b 569a380917adf4e26b286343c654954d472eabf3fe91e0d1b5f26549d9c6d24e +ql/lib/codeql/swift/elements/decl/FuncDecl.qll d3ff8bfb16c54b4d82bc2a0b9fe400bb511376d008eb0180859e7b6ad5c32b4a ba8e48682e93af0804e66f5bf0207049e291a0c1430a872252dc67af17ea700a +ql/lib/codeql/swift/elements/decl/GenericContext.qll de30cdd5cdf05024dfd25dbe3be91607bd871b03a0d97c9d7c21430d7d5bb325 4747af5faf0a93d7508e0ec58021a842ca5ec41831b5d71cbc7fce2a2389a820 +ql/lib/codeql/swift/elements/decl/GenericTypeDecl.qll ace55c6a6cea01df01a9270c38b0d9867dee1b733bca1d1b23070fc2fe1307a5 42e1e3e055f3e5fa70c8624910d635ab10fe4015d378be9e1e6e1adb39f0dc40 +ql/lib/codeql/swift/elements/decl/GenericTypeParamDecl.qll 8d8c148342b4d77ecb9a849b7172708139509aca19f744b0badf422c07b6d47a 569a380917adf4e26b286343c654954d472eabf3fe91e0d1b5f26549d9c6d24e ql/lib/codeql/swift/elements/decl/GenericTypeParamDeclConstructor.qll 63db91dc8d42746bfdd9a6bcf1f8df5b723b4ee752bd80cc61d512f2813ef959 096972e3f7f5775e60af189345bece7c0e8baec9e218709a49ed9511a3089424 ql/lib/codeql/swift/elements/decl/IfConfigDeclConstructor.qll ebd945f0a081421bd720235d0aefde800a8ad8a1db4cbd37b44447c417ff7114 1448bfdd290ad41e038a1a1ffd5ea60a75b5ec06f3a8d4d138bd56b8b960332e ql/lib/codeql/swift/elements/decl/ImportDeclConstructor.qll f2f09df91784d7a6d348d67eaf3429780ac820d2d3a08f66e1922ea1d4c8c60d 4496865a26be2857a335cbc00b112beb78a319ff891d0c5d2ad41a4d299f0457 -ql/lib/codeql/swift/elements/decl/InfixOperatorDecl.qll ca3af3b403b9d456029cb4f4b94b610a93d2d70ea71a3d6c4532088ebc83bd0b 5dec87f0c43948f38e942b204583043eb4f7386caa80cec8bf2857a2fd933ed4 +ql/lib/codeql/swift/elements/decl/InfixOperatorDecl.qll 58ba4d318b958d73e2446c6c8a839deb041ac965c22fbc218e5107c0f00763f8 5dec87f0c43948f38e942b204583043eb4f7386caa80cec8bf2857a2fd933ed4 ql/lib/codeql/swift/elements/decl/InfixOperatorDeclConstructor.qll ca6c5c477e35e2d6c45f8e7a08577c43e151d3e16085f1eae5c0a69081714b04 73543543dff1f9847f3299091979fdf3d105a84e2bcdb890ce5d72ea18bba6c8 ql/lib/codeql/swift/elements/decl/MissingMemberDeclConstructor.qll 82738836fa49447262e184d781df955429c5e3697d39bf3689397d828f04ce65 8ef82ed7c4f641dc8b4d71cd83944582da539c34fb3d946c2377883abada8578 -ql/lib/codeql/swift/elements/decl/ModuleDecl.qll 0d39d88c926d5633f467ab7a1db0101e8d61250ee5e4847de862232f997de783 410311bf3ae1efac53d8fd6515c2fe69d9ab79902c1048780e87d478cd200e26 +ql/lib/codeql/swift/elements/decl/ModuleDecl.qll a6d2f27dc70a76ec8f3360322cde3961871222c8621d99fec3a3ac5762967687 410311bf3ae1efac53d8fd6515c2fe69d9ab79902c1048780e87d478cd200e26 ql/lib/codeql/swift/elements/decl/ModuleDeclConstructor.qll 9b18b6d3517fd0c524ac051fd5dea288e8f923ada00fe4cc809cbebce036f890 0efc90492417089b0982a9a6d60310faba7a1fce5c1749396e3a29b3aac75dc5 -ql/lib/codeql/swift/elements/decl/OpaqueTypeDecl.qll 7c4a5fda798c9b44e481905f28e6c105ab3f8ab5567c2c336b24d27102fd7d66 e84e0dd1a3175ad29123def00e71efbd6f4526a12601fc027b0892930602046b +ql/lib/codeql/swift/elements/decl/OpaqueTypeDecl.qll 06e94ab2b5cebfc72a390dc420bb4c122d66e80de6d90a6bf77b230aab355f6e e84e0dd1a3175ad29123def00e71efbd6f4526a12601fc027b0892930602046b ql/lib/codeql/swift/elements/decl/OpaqueTypeDeclConstructor.qll f707aab3627801e94c63aedcded21eab14d3617c35da5cf317692eeb39c84710 20888ae6e386ae31e3cb9ff78155cb408e781ef1e7b6d687c2705843bcac0340 ql/lib/codeql/swift/elements/decl/ParamDeclConstructor.qll cfa0ba73a9727b8222efbf65845d6df0d01800646feaf7b407b8ffe21a6691d8 916ff2d3e96546eac6828e1b151d4b045ce5f7bcd5d7dbb074f82ecf126b0e09 ql/lib/codeql/swift/elements/decl/PatternBindingDeclConstructor.qll bcefa54011001b2559f90eb6ddcd286d8c47f2707103226abe3f2701ec1f45ef d58ca16ab91943a2fd97e4c7b71881b097e927156f56f3bd9dfaababccfda8f7 -ql/lib/codeql/swift/elements/decl/PostfixOperatorDecl.qll af46544addbb5bf5241e71c1846b40f33f73d64ae0932f0d057058a32ad63bee 3befb6218e934681e874c7655677eb4618edc817111ed18ef4ebcf16e06f4027 +ql/lib/codeql/swift/elements/decl/PostfixOperatorDecl.qll c2e813e1598902ef62d37d0bec40c8dbe879474b74b74a5ae07e74821760edb4 3befb6218e934681e874c7655677eb4618edc817111ed18ef4ebcf16e06f4027 ql/lib/codeql/swift/elements/decl/PostfixOperatorDeclConstructor.qll 27356cfe1d1c45a1999a200a3f1268bf09cfb019fbb7f9fb48cd32aa38b67880 6638c1acc9b0b642c106b1a14f98dfad7a9ebcc78a1b8212037d32a147e40086 ql/lib/codeql/swift/elements/decl/PoundDiagnosticDeclConstructor.qll 1b85ec959c92d1e8b218ae99d0dcd0acaa1b96e741cf7d0cf1137f2dca25d765 b8f164d00d4c5db4356933de5c3b6833b54ae8d3e9fcb908e324fcdc91a5f6ec ql/lib/codeql/swift/elements/decl/PrecedenceGroupDeclConstructor.qll 4f7548c613ee98f561a104f46ae61335d51be1b4598ae420397ae63d3ae619ca 87c11e093fb0bc5ed498f7fd36bfb844099f0e93e55de731c3e8c5fdeded35f1 -ql/lib/codeql/swift/elements/decl/PrefixOperatorDecl.qll d314c804e5ab476920a6e970b1c33cb09bf1ad076bc1f889b5068053d9de8ab5 19558ab5d027f580463ea096eb7882066d0ff95123493b8e23be79613bfdd28d +ql/lib/codeql/swift/elements/decl/PrefixOperatorDecl.qll ca4728051e2c1757a8ecf0c5a57b786b90bc38fa88b06021bb1f8f18db946215 19558ab5d027f580463ea096eb7882066d0ff95123493b8e23be79613bfdd28d ql/lib/codeql/swift/elements/decl/PrefixOperatorDeclConstructor.qll eee048d4c2314234df17966deefeee08e769a831fa500e6e494f64fca9e9dda1 01d9b09f809645c91f92b981a46c9ed6e332f5734d768ab369b7a328a9a391d4 -ql/lib/codeql/swift/elements/decl/ProtocolDecl.qll 17e89e410275aa2fbc1687a5380e23354a1b64e1b9581d52875210921b0eed8f 0bb0dca7980934cfb98dab5b83fd253153740ac8054cdf85bdce8b5ed6db9398 +ql/lib/codeql/swift/elements/decl/ProtocolDecl.qll 6c2bc4d5de3383e34d17d025f6a7cac0c98242b1fc2bd222be04c56cc5fb88d1 0bb0dca7980934cfb98dab5b83fd253153740ac8054cdf85bdce8b5ed6db9398 ql/lib/codeql/swift/elements/decl/ProtocolDeclConstructor.qll 2bbc92ddcec810cefb6cfa85320f873f1c542b1c62a197a8fbafa12e0e949c00 b2060fb804a16619e235afcd76856cdc377c4e47cfb43c5a6f9d32ff5b852e74 -ql/lib/codeql/swift/elements/decl/StructDecl.qll 1cb599afb1c574a64c2033a2c20bddbf2142b593f0775abc3d5b1cfafccca6b6 ebc04601ac1cd736151783073ef4ad1a42311731aab36b38dc02760ecb22bd4a +ql/lib/codeql/swift/elements/decl/StructDecl.qll 708711bf4236f32174caa256f3b19e00b6337f2fcfdbc67cf9d2fc8e86d65f2c ebc04601ac1cd736151783073ef4ad1a42311731aab36b38dc02760ecb22bd4a ql/lib/codeql/swift/elements/decl/StructDeclConstructor.qll 653fef1ce7a5924f9db110dfab4ebc191b6688fa14ebeb6cf2a09fe338f00646 c7ed15002c41b7dd11a5dd768e0f6f1fe241c680d155364404c64d6251adee5c ql/lib/codeql/swift/elements/decl/SubscriptDeclConstructor.qll 3a88617b41f96827cb6edd596d6d95ebcf5baf99ba113bdd298276666c6aeadf 166e04fc72507cb27e2c16ad2d5217074f8678d286cb6d0980e5b84125648abe ql/lib/codeql/swift/elements/decl/TopLevelCodeDeclConstructor.qll 6920a4e7aec45ae2a561cef95b9082b861f81c16c259698541f317481645e194 4bd65820b93a5ec7332dd1bbf59326fc19b77e94c122ad65d41393c84e6ac581 -ql/lib/codeql/swift/elements/decl/TypeAliasDecl.qll ecb457a9a81c6b13a1068f471c0b87e59227838f54c5d4effe7d4c2f6e7f5800 630dc9cbf20603855c599a9f86037ba0d889ad3d2c2b6f9ac17508d398bff9e3 +ql/lib/codeql/swift/elements/decl/TypeAliasDecl.qll 984c5802c35e595388f7652cef1a50fb963b32342ab4f9d813b7200a0e6a37ca 630dc9cbf20603855c599a9f86037ba0d889ad3d2c2b6f9ac17508d398bff9e3 ql/lib/codeql/swift/elements/decl/TypeAliasDeclConstructor.qll ba70bb69b3a14283def254cc1859c29963838f624b3f1062a200a8df38f1edd5 96ac51d1b3156d4139e583f7f803e9eb95fe25cc61c12986e1b2972a781f9c8b -ql/lib/codeql/swift/elements/decl/ValueDecl.qll b344768498e0d1794d92bc5b7c0417e75079aa8a82e27d7b3449f1e52f78d1e9 e3056cf6a883da2737cb220a89499a9e3977eb1c56b9e1d2f41a56b71a0c29f9 -ql/lib/codeql/swift/elements/expr/AbiSafeConversionExpr.qll 599bdb52d99a1e2800563209cecc01a5b5eb80cb4aff36b2d037b67c34ebb948 a87738539276438cef63145461adf25309d1938cfac367f53f53d33db9b12844 +ql/lib/codeql/swift/elements/decl/ValueDecl.qll 1b7d8eeb17be4bdbabc156cb0689641ed4f9e697e334d2d14f423ed3d1a419f6 e3056cf6a883da2737cb220a89499a9e3977eb1c56b9e1d2f41a56b71a0c29f9 +ql/lib/codeql/swift/elements/expr/AbiSafeConversionExpr.qll 39b856c89b8aff769b75051fd9e319f2d064c602733eaa6fed90d8f626516306 a87738539276438cef63145461adf25309d1938cfac367f53f53d33db9b12844 ql/lib/codeql/swift/elements/expr/AbiSafeConversionExprConstructor.qll 7d70e7c47a9919efcb1ebcbf70e69cab1be30dd006297b75f6d72b25ae75502a e7a741c42401963f0c1da414b3ae779adeba091e9b8f56c9abf2a686e3a04d52 -ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll 125f8bd8f21c95c439616744539577afcfa9fd63c65683132a2c971abcec3523 400790fe643585ad39f40c433eff8934bbe542d140b81341bca3b6dfc5b22861 -ql/lib/codeql/swift/elements/expr/AnyHashableErasureExpr.qll 20dd848a35a47af94d0fb8cf1a33a2bd6582c751440708c365cf338e522f6de5 bf80cab3e9ff5366a6223153409f4852acdb9e4a5d464fb73b2a8cffc664ca29 +ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll 4027b51a171387332f96cb7b78ca87a6906aec76419938157ac24a60cff16519 400790fe643585ad39f40c433eff8934bbe542d140b81341bca3b6dfc5b22861 +ql/lib/codeql/swift/elements/expr/AnyHashableErasureExpr.qll d6193ef0ba97877dfbdb3ea1c18e27dad5b5d0596b4b5b12416b31cbe1b3d1d6 bf80cab3e9ff5366a6223153409f4852acdb9e4a5d464fb73b2a8cffc664ca29 ql/lib/codeql/swift/elements/expr/AnyHashableErasureExprConstructor.qll 12816f18d079477176519a20b0f1262fc84da98f60bce3d3dd6476098c6542e7 4cc5c8492a97f4639e7d857f2fca9065293dfa953d6af451206ce911cda9f323 -ql/lib/codeql/swift/elements/expr/AnyTryExpr.qll 51aa09941b366d147a685452b3b89be4f0cc35f8cf9ff5ebcd53622ddd7df727 988b5df28972e877486704a43698ada91e68fe875efc331f0d7139c78b36f7dd -ql/lib/codeql/swift/elements/expr/AppliedPropertyWrapperExpr.qll b1a6c026b0167c7299d1f2de30935a8f805382edd8d91c1f7f18e9278ccd564c 9508f93ca59561455e1eb194eaddd9f071960a752f985844c65b3b498f057461 +ql/lib/codeql/swift/elements/expr/AnyTryExpr.qll 4a56bb49ed1d9f3c81c1c6cce3c60657e389facd87807eaefa407532259cec70 988b5df28972e877486704a43698ada91e68fe875efc331f0d7139c78b36f7dd +ql/lib/codeql/swift/elements/expr/AppliedPropertyWrapperExpr.qll d72d5fe299aa28c69fa9d42d683a9f7ebc9a51cbb4d889afc40c5701fb441aa6 9508f93ca59561455e1eb194eaddd9f071960a752f985844c65b3b498f057461 ql/lib/codeql/swift/elements/expr/AppliedPropertyWrapperExprConstructor.qll d9baf27c0d64e08466952b584ef08e4f40f7dfb861582aef2e7ebb16bb3da13b 2f19e7dbc02f9450c5521728ff1c5f178b14f50de4ff345fcd9bc834070a21d6 -ql/lib/codeql/swift/elements/expr/ArchetypeToSuperExpr.qll ea81d53ed038e29d0454b2411feb069e3396e6f7a0aa93bcfd05793772fe1d52 64e21e6f3307cd39d817ea66be2935e717168187bbeaedd4247bb77cec9d95ea +ql/lib/codeql/swift/elements/expr/ArchetypeToSuperExpr.qll d792d9eed5f624d2be6097bef5ebdd1c85dc722fac30974fdf5ab073e140e2bc 64e21e6f3307cd39d817ea66be2935e717168187bbeaedd4247bb77cec9d95ea ql/lib/codeql/swift/elements/expr/ArchetypeToSuperExprConstructor.qll df9f0db27fd2420e9d9cc4e1c6796b5513f6781940b5f571e8b8b9850a6e163f b4b15aa01de7ce91f74bd47a2e654c3ea360b90687c92ef9e19257289696f97e ql/lib/codeql/swift/elements/expr/ArrayExprConstructor.qll 57d37bb5a745f504c1bf06e51ffa0c757e224c158034c34e2bbb805b4efdc9f4 808753dccddfc0a02ef871af8f3d6487289ca48e7b4e4ea6356e0a87e3692583 -ql/lib/codeql/swift/elements/expr/ArrayToPointerExpr.qll 202b724bcf20f8083028d9d683d748ffceab3d0becf02c29c57228fe8aca30a5 035b15b1ecb700c4e6961b9a99e3c33476cedaa1a96310601b558e7ede9de39f +ql/lib/codeql/swift/elements/expr/ArrayToPointerExpr.qll dc48c33afea524dd5d2eab8a531cf0d1e3c274706b1047c23637da0554f1ef01 035b15b1ecb700c4e6961b9a99e3c33476cedaa1a96310601b558e7ede9de39f ql/lib/codeql/swift/elements/expr/ArrayToPointerExprConstructor.qll ad4346298ff16512f06f9841bf8171b163f59fde949e24e257db7379eb524c4f b2d038e1e13340b0616044fc28005904562035bc8c9871bd6c9b117f15adffe6 ql/lib/codeql/swift/elements/expr/AssignExprConstructor.qll 14cb0d217bc9ca982d29cdbf39c79399b39faa7e031469bc47884f413507e743 646658cb2f664ba0675f48cb51591c64cf2107a0c756038bfc66243b4c092b45 ql/lib/codeql/swift/elements/expr/AutoClosureExprConstructor.qll 928391f52b914e42625fafadbdfa703e6fb246a09a7d8e39bf7700bc2fc8c22c 2d698cceed54a230890f5f2ad9f019ebe82fdd15831b8a5b6aaabf1ea855063f @@ -79,71 +79,71 @@ ql/lib/codeql/swift/elements/expr/AwaitExprConstructor.qll 5c73999bf54f43c845e3a ql/lib/codeql/swift/elements/expr/BinaryExprConstructor.qll 99baa77331e4e5b2d0fe0ca31e839c901ba677e4337bed3aa4d580c3258fb610 7f42ac4bfc73c18743f73a3e961b529f1d302e70a634ab91fcf3676b959ddb22 ql/lib/codeql/swift/elements/expr/BindOptionalExprConstructor.qll 1dd7074d6513977eb50f857de87aea35686ddda8f1ee442569fcfac16fc02fd6 1c23977e1f5ad4fd1a9d43a01765dda2fe72496a0361701f92212f7eef3f13c2 ql/lib/codeql/swift/elements/expr/BooleanLiteralExprConstructor.qll 561ac38c94fdc3eb7baab09d0f2f2d7f64424dbfe879c395470ee6d5cd6a9354 2b76d00a58cd7d051d422f050d187c36e97614de6d99f52068aff3c20a45c7af -ql/lib/codeql/swift/elements/expr/BridgeFromObjCExpr.qll 129251956d27cd32ce806c4b11cd2ea1774723d53c4dc1d8112cab7401a2db0b 91385232931b55817e53e4caebf7a2dd9c0a520ec055012de82e7b1da923f0ec +ql/lib/codeql/swift/elements/expr/BridgeFromObjCExpr.qll 1a658c5bc73029bc5945c23210ec7a66801e4d58f75fdd5331fd71d9ac93a65b 91385232931b55817e53e4caebf7a2dd9c0a520ec055012de82e7b1da923f0ec ql/lib/codeql/swift/elements/expr/BridgeFromObjCExprConstructor.qll f91e80dad19b7177c6ea1b127c7622d145cb250575acba9bf34d99b933849b94 c3133e6ad25d86bcec697999c16d0c18db1abf894068f5b8d14c90ffae35ca09 -ql/lib/codeql/swift/elements/expr/BridgeToObjCExpr.qll 436b10412525fb6fca966416f2fb563efd569ee2826b003c9cee594a4887658f 8fc781a59f6009fa64fbbf28f302b2e83b0f7fcbe0cf13d5236637248dcb6579 +ql/lib/codeql/swift/elements/expr/BridgeToObjCExpr.qll b44c9b3ef1c540feaaa1459acc1bec1e07cd6b96a0056d09b6c0d4bb37a49356 8fc781a59f6009fa64fbbf28f302b2e83b0f7fcbe0cf13d5236637248dcb6579 ql/lib/codeql/swift/elements/expr/BridgeToObjCExprConstructor.qll 7e51fef328ad149170f83664efd57de2b7058511934f3cf1a9d6cb4033562bed 34ab05bbdddc5477ba681cc89f03283057867116c83b3e57766c3b24f38ca7bf -ql/lib/codeql/swift/elements/expr/BuiltinLiteralExpr.qll 5455879c4f3aef960881da579007544e8f20a973d2fba0c58aa21705800a0c9d 9d9de530709c80cfe710a9e3d62a1b7cede61ba22da46365b1ba7766dbc48b44 -ql/lib/codeql/swift/elements/expr/CallExpr.qll 625c0e0866c1e6384591c5022952391d256b2366d1b83174c2d299ccca086d23 8040ab28b4e1630ff343ab77d10b2449e792908b55e683316f442d853eee6c0a +ql/lib/codeql/swift/elements/expr/BuiltinLiteralExpr.qll fb3c44075ab50713722dac76de4df6129038658bbcf155e52ffab0308b54b771 9d9de530709c80cfe710a9e3d62a1b7cede61ba22da46365b1ba7766dbc48b44 +ql/lib/codeql/swift/elements/expr/CallExpr.qll 3c481940ff9d176b86368dbc8c23a39193e5aa226797233f42d2ba47ad8c54f1 8040ab28b4e1630ff343ab77d10b2449e792908b55e683316f442d853eee6c0a ql/lib/codeql/swift/elements/expr/CallExprConstructor.qll 478caaaee61b5d83126da6de16ff21d11dc452428f15a879e1401d595b7bed75 7014f17d347b781e4c8211568954c2858ab2dcf37ef5dfd5ed36678415000009 ql/lib/codeql/swift/elements/expr/CaptureListExprConstructor.qll 03af12d1b10bdc2cc4ac2b0322c4cd7f68a77699f37315ddca97f1e99a770c93 0fc709cdca8935a3142f7718d660c932af65952db8603bd909087aa68eab9236 -ql/lib/codeql/swift/elements/expr/CheckedCastExpr.qll 766f2fc44952f34ac0609aa346a5fedf7eb9c1d7bf1393890a05cb5bda45725e e7c90a92829472335199fd7a8e4ba7b781fbbf7d18cf12d6c421ddb22c719a4b -ql/lib/codeql/swift/elements/expr/ClassMetatypeToObjectExpr.qll 36fd3daf20130882e26e0f301b02380219e67ed3fe8a1caaac3854789eb6bcad 4b5aca9fa4524dc25dc6d12eb32eeda179a7e7ec20f4504493cf7eb828a8e7be +ql/lib/codeql/swift/elements/expr/CheckedCastExpr.qll 440eeee832401584f46779389d93c2a4faa93f06bd5ea00a6f2049040ae53847 e7c90a92829472335199fd7a8e4ba7b781fbbf7d18cf12d6c421ddb22c719a4b +ql/lib/codeql/swift/elements/expr/ClassMetatypeToObjectExpr.qll 9830ef94d196c93e016237c330a21a9d935d49c3d0493e597c3e29804940b29e 4b5aca9fa4524dc25dc6d12eb32eeda179a7e7ec20f4504493cf7eb828a8e7be ql/lib/codeql/swift/elements/expr/ClassMetatypeToObjectExprConstructor.qll 369cecb4859164413d997ee4afba444853b77fb857fa2d82589603d88d01e1dc 3b4ebd1fb2e426cba21edd91b36e14dc3963a1ede8c482cdf04ef5003a290b28 ql/lib/codeql/swift/elements/expr/ClosureExprConstructor.qll cf2fa2dab328f6b98aeffcdc833de4d74f69d23779ac897f5ada9c2dca9ef093 13f85b735ebb56c361458baba45eb854e70b7987d5e1863e564084c1a6165cc5 -ql/lib/codeql/swift/elements/expr/CoerceExpr.qll efc1e3852212089d81b5c3d06ae74b0a36abf2dd8843689d50dcc22d3bed12ba eb13ef05c7436d039c1f8a4164b039bdbf12323310c249d7702291058f244d38 +ql/lib/codeql/swift/elements/expr/CoerceExpr.qll e68c125466a36af148f0e47ff1d22b13e9806a40f1ec5ddc540d020d2ab7c7dc eb13ef05c7436d039c1f8a4164b039bdbf12323310c249d7702291058f244d38 ql/lib/codeql/swift/elements/expr/CoerceExprConstructor.qll aa80ea0e6c904fab461c463137ce1e755089c3990f789fae6a0b29dea7013f6d 455f5184a3d2e2a6b9720a191f1f568699f598984779d923c2b28e8a3718fa9d -ql/lib/codeql/swift/elements/expr/CollectionExpr.qll 80fedf0757cd8024ebcadd0b82507cfd5cec57b4d7c53ff0f97357384f9d89c4 87977b7661bcd8212b07b36f45ff94f5e98513c6dddb4cca697d1d6b853dff72 -ql/lib/codeql/swift/elements/expr/CollectionUpcastConversionExpr.qll 37aa0e9e829a480a5db855a2d2617ace57ac8d89fe01ec11251aa9183ccbd0a1 ab8370b77f27ed658f58571638f96187746cbafdfdf86583caf807bf3910f8c2 +ql/lib/codeql/swift/elements/expr/CollectionExpr.qll ec0e46338e028821afe1bafb2bed4edc9c9a9f69b65b397c3c0914eb52851bb0 87977b7661bcd8212b07b36f45ff94f5e98513c6dddb4cca697d1d6b853dff72 +ql/lib/codeql/swift/elements/expr/CollectionUpcastConversionExpr.qll 8e5ec3b19aacef6a926e353ced1b42224e64bd699398b4bf6a5259e77214a671 ab8370b77f27ed658f58571638f96187746cbafdfdf86583caf807bf3910f8c2 ql/lib/codeql/swift/elements/expr/CollectionUpcastConversionExprConstructor.qll 4896b2ac56def7a428945c97cd5d5e44ca6378be96707baf1cb3a47c81ef9ca3 c8f1efdfcc67b5d631447ab2b87a0a70722bd52ef3282ad74d8de929c361f626 -ql/lib/codeql/swift/elements/expr/ConditionalBridgeFromObjCExpr.qll f9b1da899020c8dd9c0633376410f5b8b8d00f4df43d5da164e5e5696c813499 4013b1dcebbc873f337ee433042ad1e5d178b0afe2d62434fe235a234e9b8aa6 +ql/lib/codeql/swift/elements/expr/ConditionalBridgeFromObjCExpr.qll 4ff4d0e9f4afbf1317dd9b6b08c0456e5808e6f821d3e8fe2d401769eeefbbbd 4013b1dcebbc873f337ee433042ad1e5d178b0afe2d62434fe235a234e9b8aa6 ql/lib/codeql/swift/elements/expr/ConditionalBridgeFromObjCExprConstructor.qll 7350d9e279995181f08dcc931723d21a36aac17b3ea5b633c82bac5c7aeb733a dc6767f621bddcc22be8594b46b7d3170e5d7bfcee6f1e0279c26492fd88c81d -ql/lib/codeql/swift/elements/expr/ConditionalCheckedCastExpr.qll 527f8f1dd071e2647f6f86a6b204a082c7e9929f9a37f35b8dcd40e99e1064b2 a66a1e07b210a1e8d999380db04a8b3210b66049a876bd92c8f56eae66c5a062 +ql/lib/codeql/swift/elements/expr/ConditionalCheckedCastExpr.qll 3052583ee44e9c859dddefc2ee578710c7ac272ba82eb939e2299008da0c92db a66a1e07b210a1e8d999380db04a8b3210b66049a876bd92c8f56eae66c5a062 ql/lib/codeql/swift/elements/expr/ConditionalCheckedCastExprConstructor.qll 13a1032bfa1199245746d4aac2c54d3ba336d3580c2713a66a91ad47eb8648ca 2a7c66669551aaa3528d77a8525985b850acbc983fea6f076561709a076dadb7 -ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll e8830d2c73a10d394495b8aa5bc68290f9524b0f09dba932d7cd7b533f149a1b fc4b855b27f7afefab8132bd2adc3567cceec6b2fd762bf1dc7463ce76421326 -ql/lib/codeql/swift/elements/expr/CovariantFunctionConversionExpr.qll 687065e8625a249d51e8e92136afacfd3c48f85f689d5aff077a5a9dac56272e 4510d77d211f4b6db9dd4c941706d7eb7579fe7311714758c9d1d24513bfbdc4 +ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll 2d8709f776df9edda8f1c07884fc32d1d25306cc2e8029d7b0c74d91f3828fef fc4b855b27f7afefab8132bd2adc3567cceec6b2fd762bf1dc7463ce76421326 +ql/lib/codeql/swift/elements/expr/CovariantFunctionConversionExpr.qll 0d18efcc60908890fa4ebf3ef90b19b06a4140d06ec90053ab33db3ad864281a 4510d77d211f4b6db9dd4c941706d7eb7579fe7311714758c9d1d24513bfbdc4 ql/lib/codeql/swift/elements/expr/CovariantFunctionConversionExprConstructor.qll eac12524819e9fe29074f90ea89fea866023b5ed4a5494345f2b9d8eec531620 71a6eb320630f42403e1e67bb37c39a1bae1c9f6cc38c0f1688a31f3f206d83f -ql/lib/codeql/swift/elements/expr/CovariantReturnConversionExpr.qll e6a7a3ce538c068bd7ab0974b4615acbf00038d3b01dc594372152114559fa44 720fb172ebcb800c70810539c7a80dbdf61acb970277f2b6a54b9159ab4e016e +ql/lib/codeql/swift/elements/expr/CovariantReturnConversionExpr.qll baa7e9a3c2a2de383d55fac1741b8739c389b9c3cf7a0241d357d226364daaf3 720fb172ebcb800c70810539c7a80dbdf61acb970277f2b6a54b9159ab4e016e ql/lib/codeql/swift/elements/expr/CovariantReturnConversionExprConstructor.qll b32a9b3c067d09bd6350efe57215e3b3b9ae598631756878da4a1e474876fc3f bcc963ee556fdd5e1563c305d1bfc6a89e8953243f5dfa1b92144d280ccb3b1a ql/lib/codeql/swift/elements/expr/DeclRefExprConstructor.qll 1efd7b7de80bdff9c179cdb01777a85369497c5fd02cbdcf41dd9724a663a60b 63dd1e7049091e3e2158fb00498e7b3e82b38abbf5deee56abd00959527ba352 ql/lib/codeql/swift/elements/expr/DefaultArgumentExprConstructor.qll 013827d95e2a9d65830b748093fd8a02da6b6cae78729875f624bf71cc28a4fe 900879fd1c26cfbcea0cd0c3b8f95425644458a8a1dd6628a8bd4bc61bc45809 -ql/lib/codeql/swift/elements/expr/DerivedToBaseExpr.qll 782d47d73634aea8ee4ea991acde27180b77535d8e5112d40df77262d9e9a19e e12acd24f48b7b59009615af6a43e061ffc595f1edc55bfe01c1524f30d7be7c +ql/lib/codeql/swift/elements/expr/DerivedToBaseExpr.qll 93bd80de8627203f0e25759698e989ff9d2067a6e996b7e3b4fe221f3f0c2052 e12acd24f48b7b59009615af6a43e061ffc595f1edc55bfe01c1524f30d7be7c ql/lib/codeql/swift/elements/expr/DerivedToBaseExprConstructor.qll ca74471f6ac2500145de98bb75880450c9185f697f5ce25905271358182a29b3 797b9eaa9d3d56a963d584ba560a67ec94e1a1b10916f0d03f4ad4777e4984f9 -ql/lib/codeql/swift/elements/expr/DestructureTupleExpr.qll 618298ec50ac464268472bba7925695ba3d37bd3ae07b310a69724b396265554 8bc4a6238bec6dbdc2f91e2777cb00d86c63642bf3d2d9758a192d170cf6fcde +ql/lib/codeql/swift/elements/expr/DestructureTupleExpr.qll 2e5556786752b319f41d12e022723b90ddad4811e50f5b09136c7a7e9e65e3c6 8bc4a6238bec6dbdc2f91e2777cb00d86c63642bf3d2d9758a192d170cf6fcde ql/lib/codeql/swift/elements/expr/DestructureTupleExprConstructor.qll 7d844c6c4a0f9008e2fdf9a194621f09595e328a5f5c6f2f993b1a3cd2a74a03 e75d47955ae9a91c75fcb8e0bb12b6ed792c361645ee29bbcc37fa2ac27c4517 ql/lib/codeql/swift/elements/expr/DictionaryExprConstructor.qll 6bd61507158b62fd8d2f3a68c61cceff5926915bf71730c898cf6be402d1e426 37cfce5600dd047a65f1321709350eabae5846429a1940c6f8b27f601420a687 -ql/lib/codeql/swift/elements/expr/DifferentiableFunctionExpr.qll 32d59a601c7ee95715e09478561018788e8f10eca34c5637c94d7700a868636c 520f79dd2fd9b500c32fb31d578fffaec67d232690638746792417a0b80b98e6 +ql/lib/codeql/swift/elements/expr/DifferentiableFunctionExpr.qll 326aafc47dd426fbcf78830ce90ce267cc121d9d3adcacca231c8222d515f688 520f79dd2fd9b500c32fb31d578fffaec67d232690638746792417a0b80b98e6 ql/lib/codeql/swift/elements/expr/DifferentiableFunctionExprConstructor.qll 4ee532a020a6e75ba2971cee5724fcccc7e6b60530ec26385cbbda0b2626f9be 6c35cd2b0142b2c74e7d8a46cf3aebfcf92e5809e5c0c480a666d8a7dacdcfa2 ql/lib/codeql/swift/elements/expr/DifferentiableFunctionExtractOriginalExprConstructor.qll ce008cb7ce392277dd0678203f845f94a9933b9530c265a58a66c16542423495 4b4522c39929d062662b5e321371e76df5f2c9c8e5eebdf5c62e88b8eb84960b ql/lib/codeql/swift/elements/expr/DiscardAssignmentExprConstructor.qll cd814e77f82fac48949382335655f22b0d1d99ece04612f026aebc2bc60f0dc9 d1faa9e2d863175feb00cd2b503ac839e09744cbbfbe4c18b670416f9d50483c ql/lib/codeql/swift/elements/expr/DotSelfExprConstructor.qll 4b6956818dac5b460dfbe9878c2c5b6761fcf1c65556b38555f68de9cc6f2562 2ae26f5e7bde2f972cc5a63e4a3dca1698e3a7c75b06419bb7bb080cb8ce78d9 ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExprConstructor.qll 8ca889cc506cac0eeb35c246a3f317c9da8fe4dbfaf736a2056108b00b1c8521 9a20b12ad44f1dbf58d205a58cdfc1d63d2540353d8c8df48d87393d3b50d8b6 -ql/lib/codeql/swift/elements/expr/DotSyntaxCallExpr.qll f5048cff6fcdd298c8822ece1cd2042a61b40521dfc230f0f0e1798527010e58 5220861621d01b15ea0182bbb8358d700f842b94ec07745f77c5285d0e84a509 -ql/lib/codeql/swift/elements/expr/DynamicLookupExpr.qll cd5670379df14b7a765037378221e541dd93567c97729d6be24bbbbb9aacc054 89f564a793d1f09a8aeb2dd61c475df3e55a49f4f0b6094ceb9f0ebe6d42fa76 +ql/lib/codeql/swift/elements/expr/DotSyntaxCallExpr.qll d2209dafbe8cde6a8a850a96d21af91db4c5a0833bcdd4f14e4a8c137209a3a4 5220861621d01b15ea0182bbb8358d700f842b94ec07745f77c5285d0e84a509 +ql/lib/codeql/swift/elements/expr/DynamicLookupExpr.qll 58e3dfb7fea694653950d09ce00772847cc3f88f0cdbc81399d676f95d67ef62 89f564a793d1f09a8aeb2dd61c475df3e55a49f4f0b6094ceb9f0ebe6d42fa76 ql/lib/codeql/swift/elements/expr/DynamicMemberRefExprConstructor.qll 6bd769bdbb83999bfd94bf4d5a1b8a32cc045460183f5f2fcf7055257f6c3787 e2b72550a71f2f39bde171ada6e04c6bdbd797caa74813ea3c8070b93cefa25e ql/lib/codeql/swift/elements/expr/DynamicSubscriptExprConstructor.qll d40d88069371807c72445453f26e0777ac857e200c9c3e8a88cd55628ccb9230 6ff580bbc1b7f99c95145168f7099ab19b5d150e7d7e83747595ff2eb2c289c4 ql/lib/codeql/swift/elements/expr/DynamicTypeExprConstructor.qll 37066c57e8a9b7044b8b4ecf42a7bf079e3400dd02bf28a1d51abd5406391ba0 62cc0405ecfe4c8d5477957d8789a6b03a4e9eecabbb0f94e1bde5ce2adabb8c ql/lib/codeql/swift/elements/expr/EnumIsCaseExprConstructor.qll a02f992035c7ef7692c381377b1e594f0021025df6bcab23f149efeacd61c8e6 687df32678e1b3bcc4241270962593f7838e461970621f6e5b829321718ed257 -ql/lib/codeql/swift/elements/expr/ErasureExpr.qll 3549ee36cbca32207ec7a339de87e81126b0ca0e087e74a6f525c817b4dd15be 91a60971ff01d158f6358a6cb2e028234b66b3a75c851a3f5289af0aa8c16613 +ql/lib/codeql/swift/elements/expr/ErasureExpr.qll 6aca57c70706f6c26be28d47b2bcb20c6d5eb7104c6a8f1e5885d13fd2f17a48 91a60971ff01d158f6358a6cb2e028234b66b3a75c851a3f5289af0aa8c16613 ql/lib/codeql/swift/elements/expr/ErasureExprConstructor.qll 29e0ab9f363b6009f59a24b2b293d12b12c3cdea0f771952d1a57c693f4db4a3 c4bc12f016b792dff79e38b296ef58dba3370357d088fd63931a8af09c8444a9 -ql/lib/codeql/swift/elements/expr/ErrorExpr.qll 89468d8ed9c1cc69575cb9c890b8e424ec0c8495894f691a657774e9146a896d bc3e4a566bc37590929e90a72e383f9fbc446e4f955e07e83c1c59a86cee8215 +ql/lib/codeql/swift/elements/expr/ErrorExpr.qll 8a68131297e574625a22fbbb28f3f09097e3272b76caf3283d4afdb8a2c5fffd bc3e4a566bc37590929e90a72e383f9fbc446e4f955e07e83c1c59a86cee8215 ql/lib/codeql/swift/elements/expr/ErrorExprConstructor.qll dd2bec0e35121e0a65d47600100834963a7695c268e3832aad513e70b1b92a75 e85dcf686403511c5f72b25ae9cf62f77703575137c39610e61562efc988bbac -ql/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExpr.qll cd5d01e8410ed65165bb4a1a570a63864b0a75c742ac9224cef8c2683d72f62d c0b5811c8665f3324b04d40f5952a62e631ec4b3f00db8e9cc13cb5d60028178 +ql/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExpr.qll 420d534f76e192e89f29c71a7282e0697d259c00a7edc3e168ca895b0dc4f1d1 c0b5811c8665f3324b04d40f5952a62e631ec4b3f00db8e9cc13cb5d60028178 ql/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExprConstructor.qll 1a735425a59f8a2bd208a845e3b4fc961632c82db3b69d0b71a1bc2875090f3b 769b6a80a451c64cbf9ce09729b34493a59330d4ef54ab0d51d8ff81305b680f ql/lib/codeql/swift/elements/expr/FloatLiteralExprConstructor.qll 4dfb34d32e4022b55caadcfbe147e94ebe771395c59f137228213a51a744ba10 1eb78fcda9e0b70d1993e02408fb6032035991bf937c4267149ab9c7c6a99d3a ql/lib/codeql/swift/elements/expr/ForceTryExprConstructor.qll 48cbc408bb34a50558d25aa092188e1ad0f68d83e98836e05072037f3d8b49af 62ce7b92410bf712ecd49d3eb7dd9b195b9157415713aaf59712542339f37e4c ql/lib/codeql/swift/elements/expr/ForceValueExprConstructor.qll 3b201ee2d70ab13ad7e3c52aad6f210385466ec4a60d03867808b4d3d97511a8 d5d9f0e7e7b4cae52f97e4681960fa36a0c59b47164868a4a099754f133e25af -ql/lib/codeql/swift/elements/expr/ForcedCheckedCastExpr.qll 27612d688194618da2403d9c913cb7fe0f423e099f0abdb9b54f4eb58b2767be a3bae0709caac887bec37c502f191ea51608006e719bb17550c3215f65b16f7f +ql/lib/codeql/swift/elements/expr/ForcedCheckedCastExpr.qll f42d96598ca09a014c43eae2fc96189c5279eab5adbebbaa6da386ffb08e7e5d a3bae0709caac887bec37c502f191ea51608006e719bb17550c3215f65b16f7f ql/lib/codeql/swift/elements/expr/ForcedCheckedCastExprConstructor.qll 3fdd87183e72c4b0ee927c5865c8cbadf4f133bd09441bf77324941c4057cbc8 a6e7dc34de8d1767512c2595121524bd8369bd21879857e13590cec87a4b0eeb -ql/lib/codeql/swift/elements/expr/ForeignObjectConversionExpr.qll fbffcd3bde46cd3e443ce583bf7bfb2d73b86e3d061465c7ddb4468be7447b72 7ea9aa492b2d37ad05d92421a92bb9b1786175b2f3b02867c1d39f1c67934f3d +ql/lib/codeql/swift/elements/expr/ForeignObjectConversionExpr.qll 4ca318937bcadd5a042b7f9ec6639144dc671a274d698506a408c94c8caceea0 7ea9aa492b2d37ad05d92421a92bb9b1786175b2f3b02867c1d39f1c67934f3d ql/lib/codeql/swift/elements/expr/ForeignObjectConversionExprConstructor.qll d90fdb1b4125299e45be4dead6831835e8d3cd7137c82143e687e1d0b0a0a3bc a2f38e36823a18d275e199c35a246a6bc5ec4a37bf8547a09a59fe5dd39a0b4e -ql/lib/codeql/swift/elements/expr/FunctionConversionExpr.qll e6dcf7fb3966d2ee5e4434221ec615b066da0e17ddc442692ca7936fcebec70b 87c1f5a44d9cc7dd10d05f17f5d4c718ecc5b673c7b7f4c1662b5d97e0177803 +ql/lib/codeql/swift/elements/expr/FunctionConversionExpr.qll 4685eae5030d599d5149557a1111c0426f944c4fce14edbf24d6b469cbde07bf 87c1f5a44d9cc7dd10d05f17f5d4c718ecc5b673c7b7f4c1662b5d97e0177803 ql/lib/codeql/swift/elements/expr/FunctionConversionExprConstructor.qll ff88509ae6754c622d5d020c0e92e0ea1efe2f7c54e59482366640b2100d187b fd640286e765dc00c4a6c87d766750cad0acd2544566ec9a21bc49c44cf09dba ql/lib/codeql/swift/elements/expr/IfExprConstructor.qll 19450ccaa41321db4114c2751e9083fbd6ceb9f6a68905e6dca5993f90dd567a 42605d9af0376e3e23b982716266f776d998d3073d228e2bf3b90705c7cb6c58 ql/lib/codeql/swift/elements/expr/InOutExprConstructor.qll c8c230f9a396acadca6df83aed6751ec1710a51575f85546c2664e5244b6c395 2e354aca8430185889e091ddaecd7d7df54da10706fe7fe11b4fa0ee04d892e0 -ql/lib/codeql/swift/elements/expr/InOutToPointerExpr.qll 60e70359ea6a433cac1b4d7afe27d739979176d2f881a8108e61fe7c1dea1a9a e9c7db3671cce65c775760c52d1e58e91903ad7be656457f096bfe2abab63d29 +ql/lib/codeql/swift/elements/expr/InOutToPointerExpr.qll 145616d30d299245701f15417d02e6e90a6aa61b33326bfd4bc2a2d69bed5551 e9c7db3671cce65c775760c52d1e58e91903ad7be656457f096bfe2abab63d29 ql/lib/codeql/swift/elements/expr/InOutToPointerExprConstructor.qll 06b1377d3d7399ef308ba3c7787192446452a4c2e80e4bb9e235267b765ae05d 969680fddeb48d9e97c05061ae9cbc56263e4c5ad7f4fad5ff34fdaa6c0010b4 -ql/lib/codeql/swift/elements/expr/InjectIntoOptionalExpr.qll d44e2ccede83bc55fb5fcd135d176a53be55783904be700e4b7bc6ca54f23499 6ec93a725c92a9abf62c39451eaf6435942b61b56bd06db0d494da0b5f407441 +ql/lib/codeql/swift/elements/expr/InjectIntoOptionalExpr.qll 79d859152f5fde76e28b8b01e3ba70ec481650b39e2a686fc6898759948bc716 6ec93a725c92a9abf62c39451eaf6435942b61b56bd06db0d494da0b5f407441 ql/lib/codeql/swift/elements/expr/InjectIntoOptionalExprConstructor.qll e25cee8b12b0640bfcc652973bbe677c93b4cb252feba46f9ffe3d822f9d97e0 4211336657fce1789dcdc97d9fe75e6bc5ab3e79ec9999733488e0be0ae52ca2 ql/lib/codeql/swift/elements/expr/IntegerLiteralExprConstructor.qll 779c97ef157265fa4e02dacc6ece40834d78e061a273d30773ac2a444cf099d0 d57c9e8bbb04d8c852906a099dc319473ae126b55145735b0c2dc2b671e1bcbd ql/lib/codeql/swift/elements/expr/InterpolatedStringLiteralExprConstructor.qll 2d288a4cbaa3d7e412543fe851bb8764c56f8ccd88dc9d3a22734e7aa8da3c1a dfa6bea9f18f17d548d8af0bb4cd15e9a327a8100349d2ecfce51908062b45c8 @@ -152,52 +152,52 @@ ql/lib/codeql/swift/elements/expr/KeyPathApplicationExprConstructor.qll c58c6812 ql/lib/codeql/swift/elements/expr/KeyPathDotExprConstructor.qll d112a3a1c1b421fc6901933685179232ac37134270482a5b18d96ba6f78a1fd1 abce0b957bdf2c4b7316f4041491d31735b6c893a38fbf8d96e700a377617b51 ql/lib/codeql/swift/elements/expr/KeyPathExprConstructor.qll 96f7bc80a1364b95f5a02526b3da4f937abe6d8672e2a324d57c1b036389e102 2f65b63e8eac280b338db29875f620751c8eb14fbdcf6864d852f332c9951dd7 ql/lib/codeql/swift/elements/expr/LazyInitializerExprConstructor.qll deba52e51f31504564adc33da079b70f1f2da1e3e6f9538cba8bf97be0c27c64 4499c688d86c08cb33a754ad86f6adbe47754aa0fc58a4d77dd7cbfa1ca1fa50 -ql/lib/codeql/swift/elements/expr/LinearFunctionExpr.qll bcdc3b7c9f854f622e087a16a892af677439fee023d29341be534d297596bd3e b3253571f09a743a235c0d27384e72cf66b26ba8aa5e34061956c63be4940f15 +ql/lib/codeql/swift/elements/expr/LinearFunctionExpr.qll 37fc05646e4fbce7332fb544e3c1d053a2f2b42acb8ce1f3a9bb19425f74ae34 b3253571f09a743a235c0d27384e72cf66b26ba8aa5e34061956c63be4940f15 ql/lib/codeql/swift/elements/expr/LinearFunctionExprConstructor.qll 18998356c31c95a9a706a62dd2db24b3751015878c354dc36aa4655e386f53c3 7e02b4801e624c50d880c2826ef7149ad609aa896d194d64f715c16cfbd11a7d -ql/lib/codeql/swift/elements/expr/LinearFunctionExtractOriginalExpr.qll fb5d879aa0dd3191dfc587926618b59f977914780c607c6c62c293ecc654b6fe bd9f3c1a5114cec5c360a1bb94fe2ffaa8559dfdd69d78bd1a1c039b9d0cab10 +ql/lib/codeql/swift/elements/expr/LinearFunctionExtractOriginalExpr.qll c968bca2c79985d8899e37a4015de2a6df6fd40f6e519f8f0601202c32c68f70 bd9f3c1a5114cec5c360a1bb94fe2ffaa8559dfdd69d78bd1a1c039b9d0cab10 ql/lib/codeql/swift/elements/expr/LinearFunctionExtractOriginalExprConstructor.qll 4cdacae7a04da12cd19a51ff6b8fa5d0a5fb40b915073a261c1b71a1a0586c90 b4f338fa97ff256a53932901cf209473af8c78c8da0ec7caa66335bfb2aabe1f -ql/lib/codeql/swift/elements/expr/LinearToDifferentiableFunctionExpr.qll c841a3a0d5deb1d0f8c26122270c10793f8d49d8a484ac0fb838ad0733619fb6 a002c9d1cfc933b45eecf317654c90727a2986fb6d3403fc541be431d7c6b901 +ql/lib/codeql/swift/elements/expr/LinearToDifferentiableFunctionExpr.qll 388f59eac6cb7a21ef0222f707f8793045999c3b5bbdc202cb23648dabbdd036 a002c9d1cfc933b45eecf317654c90727a2986fb6d3403fc541be431d7c6b901 ql/lib/codeql/swift/elements/expr/LinearToDifferentiableFunctionExprConstructor.qll 8a66e39915b4945bef0b1d5b31f4cbbf8149e1392ae42a29d661cfea9c0e3476 954242936f413271a64da2b8862168712ee7b3e0a31653344268f1d615e20fdf -ql/lib/codeql/swift/elements/expr/LiteralExpr.qll 8e39746df049b3598013901e5b5f9e5d328c22fb7893c273f1a8ab96ec8305fa a599db9010b51379172c400cbd28ab3ea0e893a2dd049e2af3ed1a5eb9329f73 -ql/lib/codeql/swift/elements/expr/LoadExpr.qll 74643292340ccd9ac1c6449faa65bb02ba86749ec6a4f64e7ff04572822a1acd 44b0d1213be692586ac2a2af025ed2c4c2c2f707d2d3e6abab11ee7a28083510 +ql/lib/codeql/swift/elements/expr/LiteralExpr.qll 505be8b4d5e7e2ce60bc5ef66d0198050c8cdc1429d837088ffa8e8fc6c440ce a599db9010b51379172c400cbd28ab3ea0e893a2dd049e2af3ed1a5eb9329f73 +ql/lib/codeql/swift/elements/expr/LoadExpr.qll e75bd0ffd2da6c0db724ee3c45b2cfbed7e129339e1a597f67689362929fb120 44b0d1213be692586ac2a2af025ed2c4c2c2f707d2d3e6abab11ee7a28083510 ql/lib/codeql/swift/elements/expr/LoadExprConstructor.qll 47e2766b4019cec454177db59429f66ff4cc5e6c2ba811b9afd6b651fb390c8d a37517b63ad9e83b18a6e03cad5a4b31bc58d471a078603e7346c2f52dbb5ef9 -ql/lib/codeql/swift/elements/expr/LookupExpr.qll 46ed9daef8b3fe31ad93bb7450b11d35dfae639a7803c24c999603f49517e1ef cf76a591d96ccd9f64f404332b1be1e0587a124e3de0f9ea978d819549f51582 +ql/lib/codeql/swift/elements/expr/LookupExpr.qll c9204e10adf7e71599422b140bdc3d6f78a9bd67d11d0282555c9584a3342267 cf76a591d96ccd9f64f404332b1be1e0587a124e3de0f9ea978d819549f51582 ql/lib/codeql/swift/elements/expr/MagicIdentifierLiteralExprConstructor.qll 9ac0c8296b8a0920782210520b1d55b780f037cd080bbd1332daddddc23dac97 d87f853e1a761f3986236c44937cbe21d233e821a9ad4739d98ec8255829eb32 ql/lib/codeql/swift/elements/expr/MakeTemporarilyEscapableExprConstructor.qll b291d55ccbdef0d783ba05c68f496c0a015a211c9e5067dc6e4e65b50292a358 1c2ee4068da4b6fc5f3671af5319a784c0d3e1aa715392f8416918738f3d3633 ql/lib/codeql/swift/elements/expr/MemberRefExprConstructor.qll 484391d318c767336ae0b1625e28adcc656cbfa6075a38732d92848aaf8fb25e 2907badc97b8aa8df10912fd116758ce4762940753d6fa66d61a557e9d76cde6 -ql/lib/codeql/swift/elements/expr/MetatypeConversionExpr.qll 50ee8a089204600476f1a629bdfc8efe7718a62806abcd81901df9c8b257797c f4debff6b8aab8ddf041f3d2a9a3d9e1432e77178b3d6128ebd9861c4fa73ac1 +ql/lib/codeql/swift/elements/expr/MetatypeConversionExpr.qll 2aa47134ef9e680333532d26a30fd77054f4aec92cd58f7f39b886378d374bd0 f4debff6b8aab8ddf041f3d2a9a3d9e1432e77178b3d6128ebd9861c4fa73ac1 ql/lib/codeql/swift/elements/expr/MetatypeConversionExprConstructor.qll 925f2a5c20517f60d6464f52fe1f2940ea1c46b418571d9050f387be51b36705 60063f936b7180aea9eba42a029202a362473c0bb620e880001f0b76d326b54a ql/lib/codeql/swift/elements/expr/NilLiteralExprConstructor.qll 483911d82316ea9c4fd29a46aa9e587e91ce51e78e6f55959aa6edafd5ae4c88 12ec784670587f43e793dd50e2bc47555897203dfa9bf3d8fc591ddeb39d3bb5 -ql/lib/codeql/swift/elements/expr/NumberLiteralExpr.qll 14e4dd1acbd947ccb86c1700ac0f0dd0830aee733da356b857d0efe612498fe3 abbe1abbabb1d0511429e2c25b7cbcfba524b9f8391f4d8a5aca079b2c1085e6 +ql/lib/codeql/swift/elements/expr/NumberLiteralExpr.qll c021069046f68c90096ba0af742fe4ff190423eb46a5ce1070cfa5928160b31a abbe1abbabb1d0511429e2c25b7cbcfba524b9f8391f4d8a5aca079b2c1085e6 ql/lib/codeql/swift/elements/expr/ObjCSelectorExprConstructor.qll f61b72989d2729e279b0e70343cf020e72de8daa530ef8f1e996816431720a50 37c5f7695da3a7db0f7281e06cc34328a5ae158a5c7a15e0ac64100e06beb7f9 ql/lib/codeql/swift/elements/expr/ObjectLiteralExprConstructor.qll a18863eb82d0615e631a3fd04343646a2d45f21c14e666d4425a139d333ec035 b41bed928509bd792ec619a08560f1b5c80fb75cec485648601d55b9d7c53d1c ql/lib/codeql/swift/elements/expr/OneWayExprConstructor.qll 1f6b634d0c211d4b2fb13b5ac3f9cf6af93c535f9b0d9b764feb36dbc11a252e a2f0660ac48420cfd73111b1100f7f4f6523140c5860e1e5489c105707106275 -ql/lib/codeql/swift/elements/expr/OpaqueValueExpr.qll 15e24ab58aa38242dcc01cce60fb006da3e1a1fd98d7d3a715af3c96d28f1efc 3bf654dc10e2057a92f5f6b727237ec0b0ec7f564a6cc6ef2027c20e8e23a1e9 +ql/lib/codeql/swift/elements/expr/OpaqueValueExpr.qll 004c10a1abd10fa1596368f53a57398d3b851086d4748f312a69ef457e5586fe 3bf654dc10e2057a92f5f6b727237ec0b0ec7f564a6cc6ef2027c20e8e23a1e9 ql/lib/codeql/swift/elements/expr/OpaqueValueExprConstructor.qll 35e8475fd6a83e3ef7678529465852de9fb60d129bb5db13a26380c1376ada8b c9c999cb816b948be266aaa83bc22fb9af11b104137b4da1d99f453759784a62 -ql/lib/codeql/swift/elements/expr/OpenExistentialExpr.qll d6187b0ccca6e84c502a4528dcaa0ada8ade1c96ba0a85c5fcd2d052ad291558 cfd96b626180ef3c63c2dbc17b13cd6f585515427f5c3beac48896cf98234a67 +ql/lib/codeql/swift/elements/expr/OpenExistentialExpr.qll cd3dca0f54a9d546166af755a6c108be9f11ef73f2bbd65a380223e57d2afc1c cfd96b626180ef3c63c2dbc17b13cd6f585515427f5c3beac48896cf98234a67 ql/lib/codeql/swift/elements/expr/OpenExistentialExprConstructor.qll c56e5e6f7ae59a089316cd66a9b03d2584024625c2c662e7f74526c0b15dbd60 ea3cc78dd1b1f8fb744258e1c2bf6a3ec09eb9c1181e1a502c6a9bc2cf449337 -ql/lib/codeql/swift/elements/expr/OptionalEvaluationExpr.qll 2f46c15d17a50b14e91552be8ac5b72dbdc9f39b8fac9fa068e519ae5c8aa99b 559902efedbf4c5ef24697267c7b48162129b4ab463b41d89bdfb8b94742fa9f +ql/lib/codeql/swift/elements/expr/OptionalEvaluationExpr.qll bba59c32fbe7e76ddf07b8bbe68ce09587f490687e6754c2210e13bda055ba25 559902efedbf4c5ef24697267c7b48162129b4ab463b41d89bdfb8b94742fa9f ql/lib/codeql/swift/elements/expr/OptionalEvaluationExprConstructor.qll 4ba0af8f8b4b7920bc1106d069455eb754b7404d9a4bfc361d2ea22e8763f4fe 6d07e7838339290d1a2aec88addd511f01224d7e1d485b08ef4793e01f4b4421 ql/lib/codeql/swift/elements/expr/OptionalTryExprConstructor.qll 60d2f88e2c6fc843353cc52ce1e1c9f7b80978750d0e780361f817b1b2fea895 4eabd9f03dc5c1f956e50e2a7af0535292484acc69692d7c7f771e213609fd04 ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll cf726ed7ed830e17aaedf1acddf1edc4efc7d72ab9f9580bc89cc8eefbd54d8a 4ef3010dc5500bd503db8aa531d5455a9c80bc30172fb005abc6459b6f66ea00 -ql/lib/codeql/swift/elements/expr/OverloadedDeclRefExpr.qll adb49e25cdd87d2e6259399a7ce3a1fbe6eb345f9b8f4e34eb23cb39eb3555da 47b1c6df5397de490f62e96edc0656b1f97c0be73c6b99ecd78b62d46106ce61 +ql/lib/codeql/swift/elements/expr/OverloadedDeclRefExpr.qll 97e35eda07e243144652648342621a67745c0b3b324940777d38a4a293968cf6 47b1c6df5397de490f62e96edc0656b1f97c0be73c6b99ecd78b62d46106ce61 ql/lib/codeql/swift/elements/expr/OverloadedDeclRefExprConstructor.qll 2cf79b483f942fbf8aaf9956429b92bf9536e212bb7f7940c2bc1d30e8e8dfd5 f4c16a90e3ab944dded491887779f960e3077f0a8823f17f50f82cf5b9803737 ql/lib/codeql/swift/elements/expr/ParenExprConstructor.qll 6baaa592db57870f5ecd9be632bd3f653c44d72581efd41e8a837916e1590f9e 6f28988d04b2cb69ddcb63fba9ae3166b527803a61c250f97e48ff39a28379f6 -ql/lib/codeql/swift/elements/expr/PointerToPointerExpr.qll 921645a373443d050dbc29b9f6bc4a734163c75aeffce453a4f8334b34077d30 54089de77845f6b0e623c537bc25a010ecf1b5c7630b1b4060d2b378abc07f4e +ql/lib/codeql/swift/elements/expr/PointerToPointerExpr.qll dad0616bab644089837f2ee2c4118d012ab62e1c4a19e1fa28c9a3187bb1e710 54089de77845f6b0e623c537bc25a010ecf1b5c7630b1b4060d2b378abc07f4e ql/lib/codeql/swift/elements/expr/PointerToPointerExprConstructor.qll 95cc8003b9a3b2101afb8f110ec4cbd29e380fc048ee080f5047bcf0e14a06c7 114d487a1bb2cd33b27a9c3a47ad1d7254766e169512642f8b09b9c32cf3dc86 ql/lib/codeql/swift/elements/expr/PostfixUnaryExprConstructor.qll c26326e2703b9a8b077ea9f132ae86a76b4010a108b8dcde29864f4206096231 70e45fbe365b63226d0132158cdd453e2e00d740a31c1fb0f7bfb3b2dedfd928 ql/lib/codeql/swift/elements/expr/PrefixUnaryExprConstructor.qll 6d4c915baf460691cc22681154b1129852c26f1bd9fe3e27b4e162f819d934f5 7971698433bc03dbff2fec34426a96a969fab1a5a575aaf91f10044819e16f6d -ql/lib/codeql/swift/elements/expr/PropertyWrapperValuePlaceholderExpr.qll 35a61a7f68e71165690127b445fff39780028cb6be5e7b5eadaafa8aeb6b2321 f9e32f65e6d453d3fa857a4d3ca19700be1f8ea2f3d13534656bc21a2fc5f0b0 +ql/lib/codeql/swift/elements/expr/PropertyWrapperValuePlaceholderExpr.qll d4b6e3f96d79b999e8a83cfa20640ac72a1e99b91ea9a42f7dc29c9471e113b8 f9e32f65e6d453d3fa857a4d3ca19700be1f8ea2f3d13534656bc21a2fc5f0b0 ql/lib/codeql/swift/elements/expr/PropertyWrapperValuePlaceholderExprConstructor.qll 874da84b8ac2fbf6f44e5343e09629225f9196f0f1f3584e6bc314e5d01d8593 e01fc8f9a1d1cddab7c249437c13f63e8dc93e7892409791728f82f1111ac924 -ql/lib/codeql/swift/elements/expr/ProtocolMetatypeToObjectExpr.qll db0a35204b99aa6665d95461db0c5592739172d3def43d38461612622d39fea7 1f342dead634daf2cd77dd32a1e59546e8c2c073e997108e17eb2c3c832b3070 +ql/lib/codeql/swift/elements/expr/ProtocolMetatypeToObjectExpr.qll b43455289de611ba68870298e89ad6f94b5edbac69d3a22b3a91046e95020913 1f342dead634daf2cd77dd32a1e59546e8c2c073e997108e17eb2c3c832b3070 ql/lib/codeql/swift/elements/expr/ProtocolMetatypeToObjectExprConstructor.qll aaaf5fd2496e24b341345933a5c730bbfd4de31c5737e22269c3f6927f8ae733 bece45f59dc21e9deffc1632aae52c17cf41924f953afc31a1aa94149ecc1512 ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll 434e00b6e5d3ccf356dabb4a7d6574966676c32d4c257ad3606d5b9e2b715524 637a16d0f5f504bad4a04bb85d6491a94738781d3282bc27363cceafb3023408 ql/lib/codeql/swift/elements/expr/RegexLiteralExprConstructor.qll 7bf1bdba26d38e8397a9a489d05042ea2057f06e35f2a664876dc0225e45892d dcc697170a9fc03b708f4a13391395e3986d60eb482639e3f5a3ba0984b72349 -ql/lib/codeql/swift/elements/expr/SelfApplyExpr.qll 75a7f14daedd69803bbb2650e503c7db5589044347c3b783f8cd13130c7c508e f0349628f9ead822783e09e56e0721f939bfb7f59c8661e6155b5a7d113c26f3 -ql/lib/codeql/swift/elements/expr/SequenceExpr.qll b1269230db9782dacba9a61e60fb2b962b05d47048b205a5bcf89157fe475b82 3b2d06ac54746033a90319463243f2d0f17265c7f1573cbfedbdca3fb7063fd2 +ql/lib/codeql/swift/elements/expr/SelfApplyExpr.qll 986b3ff9833aac59facecea185517c006264c5011191b4c7f31317a20926467a f0349628f9ead822783e09e56e0721f939bfb7f59c8661e6155b5a7d113c26f3 +ql/lib/codeql/swift/elements/expr/SequenceExpr.qll 813360eff6a312e39c7b6c49928477679a3f32314badf3383bf6204690a280e4 3b2d06ac54746033a90319463243f2d0f17265c7f1573cbfedbdca3fb7063fd2 ql/lib/codeql/swift/elements/expr/SequenceExprConstructor.qll 5a15ede013bb017a85092aff35dd2f4f1fb025e0e4e9002ac6e65b8e27c27a0b 05d6c0e2fa80bbd088b67c039520fe74ef4aa7c946f75c86207af125e7e2e6b4 ql/lib/codeql/swift/elements/expr/StringLiteralExprConstructor.qll 49de92f9566459609f4a05b7bf9b776e3a420a7316151e1d3d4ec4c5471dcffb 4a7474d3782b74a098afe48599faee2c35c88c1c7a47d4b94f79d39921cd4a1f -ql/lib/codeql/swift/elements/expr/StringToPointerExpr.qll 8fcb58665cac6f01df36fbd4f3cd78f515ee57bc1a2bdf5f414174615442cf49 6f6710f7ac709102b0f3240dcd779baf5da00d2e7a547d19291600bc405c5a54 +ql/lib/codeql/swift/elements/expr/StringToPointerExpr.qll c30a9f184de3f395183751a826c59e5e3605560f738315cead3bf89a49cfe23c 6f6710f7ac709102b0f3240dcd779baf5da00d2e7a547d19291600bc405c5a54 ql/lib/codeql/swift/elements/expr/StringToPointerExprConstructor.qll 138dd290fff168d00af79f78d9d39a1940c2a1654afd0ec02e36be86cebef970 66f7385721789915b6d5311665b89feff9469707fab630a6dcbf742980857fd9 ql/lib/codeql/swift/elements/expr/SubscriptExprConstructor.qll dd2a249c6fb3a2ce2641929206df147167682c6294c9e5815dab7dddbac0d3bd ad382cbd793461f4b4b1979b93144b5e545ba91773f06957c8e1b4808113cd80 ql/lib/codeql/swift/elements/expr/SuperRefExprConstructor.qll 7d503393bddf5c32fb4af9b47e6d748d523fc4f3deb58b36a43d3c8c176c7233 86d2312a61ccb3661d899b90ac1f37a1079b5599782d52adaf48f773b7e7dd72 @@ -206,21 +206,21 @@ ql/lib/codeql/swift/elements/expr/TryExprConstructor.qll 786f2e720922c6d485a3e02 ql/lib/codeql/swift/elements/expr/TupleElementExprConstructor.qll d5677df4f573dd79af7636bf632f854e5fd1cbe05a42a5d141892be83550e655 5248a81d39ed60c663987463f1ce35f0d48b300cd8e9c1bcd2fdbf5a32db48dc ql/lib/codeql/swift/elements/expr/TupleExprConstructor.qll 0eec270bb267006b7cdb0579efe4c420e0b01d901254a4034c3d16f98dc18fc0 4dab110e17ff808e01e46fc33436ffd22ebf5644abcb92158b5b09a93c0b1c19 ql/lib/codeql/swift/elements/expr/TypeExprConstructor.qll d4cbe4ddbd7a43a67f9a9ca55081ae11c4a85aa1cc598bc31edd3ff975255c62 1ca407571c456237f3f4f212bbcfa821d96aac44c9e569c6e5a4929c144c4569 -ql/lib/codeql/swift/elements/expr/UnderlyingToOpaqueExpr.qll f8238439d553627d5b82f21fd906f602e2d1fc884d593209be00deb2fb85b8c7 f947161c8956113ff052743fea50645176959f2b04041cb30f4111c2569400be +ql/lib/codeql/swift/elements/expr/UnderlyingToOpaqueExpr.qll f008a4bb8362b237d35702702c388bcbf13878ee4d91e3a0d4cc30e90b627560 f947161c8956113ff052743fea50645176959f2b04041cb30f4111c2569400be ql/lib/codeql/swift/elements/expr/UnderlyingToOpaqueExprConstructor.qll 6b580c0c36a8c5497b3ec7c2b704c230de4529cfdeb44399184503048dc547d7 b896b2635319b2b2498eac7d22c98f1190ff7ba23a1e2e285c97a773860d9884 -ql/lib/codeql/swift/elements/expr/UnevaluatedInstanceExpr.qll 7d390adafff48b7365e4abe80e98a9367030ad62992b0ee8b17e16d140c0e673 a094972b3b30a8a5ead53e12ede960f637190f9fa7dd061f76b4a4ab1ff5282e +ql/lib/codeql/swift/elements/expr/UnevaluatedInstanceExpr.qll 6def5d71ecc3187a7786893d4ba38677757357f9d8ab3684b74351898a74ff7d a094972b3b30a8a5ead53e12ede960f637190f9fa7dd061f76b4a4ab1ff5282e ql/lib/codeql/swift/elements/expr/UnevaluatedInstanceExprConstructor.qll 9453bb0ae5e6b9f92c3c9ded75a6bbaff7a68f8770b160b3dd1e4c133b421a80 51ac38be089bbc98950e8175f8a2b0ab2a6b8e6dbb736c754b46bf3c21b7551e ql/lib/codeql/swift/elements/expr/UnresolvedDeclRefExprConstructor.qll 6f7498cf4edc48fa4c0184bb4068be63a88a0a5ab349bd54228f23d23df292cb b9e16dc1bd56535494a65f8faa780fca70a7eae1e04da132d99638ca2ee5e62c ql/lib/codeql/swift/elements/expr/UnresolvedDotExprConstructor.qll 11d54c61f34291a77e4de8d1d763de06da5933ab784f0ae6b4bf6798ab6e2297 78b01e12cd7f49dc71456419922cf972b322bd76554090bedeb4263a8701f1af -ql/lib/codeql/swift/elements/expr/UnresolvedMemberChainResultExpr.qll 0eaae416c14e9e6cb7319344509012a321587f96fcbd4f9c45002908450ff3d9 97362882ce004dce33e97a76f2857527925696f21ac5f1f1b285d57fea7e1d57 +ql/lib/codeql/swift/elements/expr/UnresolvedMemberChainResultExpr.qll bca5ed65b098dbf13cc655b9542292d745190512f588a24ada8d79747d7f6b14 97362882ce004dce33e97a76f2857527925696f21ac5f1f1b285d57fea7e1d57 ql/lib/codeql/swift/elements/expr/UnresolvedMemberChainResultExprConstructor.qll 3e76d7a004acd986c8d58ff399d6fb0510577b9a67e01a85294f89319038e895 e02f88167623ad78bc44f4682b87312bd3c44ddb1f0f85970e19fdbf4df3a4a8 -ql/lib/codeql/swift/elements/expr/UnresolvedMemberExpr.qll 4afc9da4eeb97f89adf31d3e04610d7df3437b66fe1c601507421fad7d3d3996 6591d38ddf3aa0e4db0fa7fdb28b8f70d8278ff96e8117c560ecb1bdf770bb2a +ql/lib/codeql/swift/elements/expr/UnresolvedMemberExpr.qll 922844a98f88bc6628a0d9c67d0f7f0b6b39490bfa66eaf4a8fc22f921034898 6591d38ddf3aa0e4db0fa7fdb28b8f70d8278ff96e8117c560ecb1bdf770bb2a ql/lib/codeql/swift/elements/expr/UnresolvedMemberExprConstructor.qll db3c55863184bd02e003bf159cab3d7f713a29749d35485473f727f3ccf801a8 ea74f8904d67ac3552d85c12a2b8a19d3e2edf216efccb4263a546501fd4eba2 -ql/lib/codeql/swift/elements/expr/UnresolvedPatternExpr.qll cb316e3bd39f7d558466f91428c5c8da7b3b07ea12e138c72fda33f3b4e3398a f3624cdd8025f1bb525cd0e9a85dc098ca8fa7876f1754849bade0d4e3840589 +ql/lib/codeql/swift/elements/expr/UnresolvedPatternExpr.qll 53c371fd057205d3005967f7d34001e7dafc83f0182875c00f16e7f90098e5aa f3624cdd8025f1bb525cd0e9a85dc098ca8fa7876f1754849bade0d4e3840589 ql/lib/codeql/swift/elements/expr/UnresolvedPatternExprConstructor.qll 7b7f834d2793c7e3d60fbd69cb989a170b0e62c2777d817d33a83110ca337e94 f4f8ee260274e547514f3a46ced487abe074409b209adb84f41dc9ebb3d67691 -ql/lib/codeql/swift/elements/expr/UnresolvedSpecializeExpr.qll 8b6975b0759e4a694d2b715f48b22af0b58b390c85ca1299e5a3aa5a687a61db c6fa963f07ed372dca97ea217a836f603c276ed309576b6a13e7cc75d13038c4 +ql/lib/codeql/swift/elements/expr/UnresolvedSpecializeExpr.qll 6c607ebd3570db81a7b4f2c57069717681ce0d75e5d166eb95d909e3e4dcb59a c6fa963f07ed372dca97ea217a836f603c276ed309576b6a13e7cc75d13038c4 ql/lib/codeql/swift/elements/expr/UnresolvedSpecializeExprConstructor.qll 1cbb484b72efa96b510103bea12247adfe31ec17f9d62b982868d4a5ca3e19b9 af57548a00010dc5e8a51342e85e0c7fc15a30068d7d68b082236cfc53b8c60b -ql/lib/codeql/swift/elements/expr/UnresolvedTypeConversionExpr.qll d7e889aa4c45ea8a7f171b0de7229cae8872f2f37dc2d5cdb458ffba66ef27b9 0270bc88ba7c53e443e35d04309fcff756f0afac0b3cd601779358b54f81e4a1 +ql/lib/codeql/swift/elements/expr/UnresolvedTypeConversionExpr.qll cf710b03294002bf964ea6ad6fc5d7f071296fd8d89718fbf5f4813d021c2002 0270bc88ba7c53e443e35d04309fcff756f0afac0b3cd601779358b54f81e4a1 ql/lib/codeql/swift/elements/expr/UnresolvedTypeConversionExprConstructor.qll 191cc2641ea735a72cedd50a1b4fcc66e0e42e3bdc5d1368003790d1621478f4 07384657c12f97d9cac284154a2bcff9c7bc4a745e705cbd7c1e2f0bc857ad48 ql/lib/codeql/swift/elements/expr/VarargExpansionExprConstructor.qll b3d9bb66747c3495a47f8d7ea27162a216124e94ceb4a0c403faf7c1ca0c1ea1 84cfb1600f461ddfe088b0028ca26b1e2708bd5b59e634eed2d8766817fa6906 ql/lib/codeql/swift/elements/pattern/AnyPatternConstructor.qll 9ce05c2c4c015a072f7ab5b0d1a15fa7c2666f252ae361164c59e90150338b2a 4a0d79d90e5392187cf631397b94a0e23bc6d661d381e880b129e4964e6468f2 @@ -232,7 +232,7 @@ ql/lib/codeql/swift/elements/pattern/IsPatternConstructor.qll 209ad40227f49dfe1b ql/lib/codeql/swift/elements/pattern/NamedPatternConstructor.qll 437ccf0a28c204a83861babc91e0e422846630f001554a3d7764b323c8632a26 91c52727ccf6b035cc1f0c2ca1eb91482ef28fa874bca382fb34f9226c31c84e ql/lib/codeql/swift/elements/pattern/OptionalSomePatternConstructor.qll bc33a81415edfa4294ad9dfb57f5aa929ea4d7f21a013f145949352009a93975 9fb2afa86dc9cedd28af9f27543ea8babf431a4ba48e9941bcd484b9aa0aeab5 ql/lib/codeql/swift/elements/pattern/ParenPatternConstructor.qll 7229439aac7010dbb82f2aaa48aedf47b189e21cc70cb926072e00faa8358369 341cfacd838185178e95a2a7bb29f198e46954098f6d13890351a82943969809 -ql/lib/codeql/swift/elements/pattern/Pattern.qll e2f802e788d00a9da18dd6b5d3536666972d9a6a87969b93f95174a922afbbac cbecbc4b2d9bea7b571b9d184a0bb8cf472f66106e96d4f70e0e98d627f269a5 +ql/lib/codeql/swift/elements/pattern/Pattern.qll a5cee4c72446f884107acc248a10b098871dc027513452c569294aaeecbc5890 cbecbc4b2d9bea7b571b9d184a0bb8cf472f66106e96d4f70e0e98d627f269a5 ql/lib/codeql/swift/elements/pattern/TuplePatternConstructor.qll 208fe1f6af1eb569ea4cd5f76e8fbe4dfab9a6264f6c12b762f074a237934bdc 174c55ad1bf3058059ed6c3c3502d6099cda95fbfce925cfd261705accbddbcd ql/lib/codeql/swift/elements/pattern/TypedPatternConstructor.qll 1befdd0455e94d4daa0332b644b74eae43f98bab6aab7491a37176a431c36c34 e574ecf38aac7d9381133bfb894da8cb96aec1c933093f4f7cc951dba8152570 ql/lib/codeql/swift/elements/stmt/BraceStmtConstructor.qll eb2b4817d84da4063eaa0b95fe22131cc980c761dcf41f1336566e95bc28aae4 c8e5f7fecd01a7724d8f58c2cd8c845264be91252281f37e3eb20f4a6f421c72 @@ -249,124 +249,124 @@ ql/lib/codeql/swift/elements/stmt/FallthroughStmtConstructor.qll 657f6a565884949 ql/lib/codeql/swift/elements/stmt/ForEachStmtConstructor.qll e21b78d279a072736b9e5ce14a1c5c68c6d4536f64093bf21f8c4e2103586105 02a28c4ef39f8e7efffb2e6d8dcfeccb6f0a0fc2889cbcda5dd971711ac0ff07 ql/lib/codeql/swift/elements/stmt/GuardStmtConstructor.qll 77ddea5f97777902854eec271811cd13f86d944bcc4df80a40ed19ad0ee9411e 1602e1209b64530ee0399536bff3c13dcecbccbc92cc1f46bc5bbb5edb4e7350 ql/lib/codeql/swift/elements/stmt/IfStmtConstructor.qll c65681a3e20e383173877720e1a8a5db141215158fffad87db0a5b9e4e76e394 104d1a33a5afb61543f7f76e60a51420599625e857151c02ac874c50c6985ee9 -ql/lib/codeql/swift/elements/stmt/LabeledConditionalStmt.qll 77c2dc7bfa551dd96109ee64ca9bbd5774a36762dd00cfad89a21eaf237e1f18 2b082cc547b431391f143d317c74fe7a3533f21cd422a6bd3c9ef617cacecc0f +ql/lib/codeql/swift/elements/stmt/LabeledConditionalStmt.qll 9b946c4573c053944ca11b9c1dbed73cf17e0553626f0267cd75947e5a835e0b 2b082cc547b431391f143d317c74fe7a3533f21cd422a6bd3c9ef617cacecc0f ql/lib/codeql/swift/elements/stmt/PoundAssertStmtConstructor.qll 70a0d22f81d7d7ce4b67cc22442beee681a64ac9d0b74108dfa2e8b109d7670e 08fee916772704f02c560b06b926cb4a56154d01d87166763b3179c5d4c85542 ql/lib/codeql/swift/elements/stmt/RepeatWhileStmtConstructor.qll e19d34dbf98501b60978db21c69abe2b77896b4b6379c6ff02b15c9f5c37270e a72db7c5cb0eb5be7b07cbddb17247d4d69d2bb8cbc957dc648c25fa6c0636ce ql/lib/codeql/swift/elements/stmt/ReturnStmtConstructor.qll ade838b3c154898f24a8e1d4ef547d460eac1cd6df81148ffb0f904d38855138 c00befd9ac0962172369319d7a791c44268413f760f2ac5e377fdee09c163101 -ql/lib/codeql/swift/elements/stmt/Stmt.qll 18aaec168417ad00fcb7fa120f9b4251b6a260ab7e31799687ac57b31c4a4819 014e29f6cc639359708f4416b1719823218efa0e92dc33630ecfc051144c7ac0 +ql/lib/codeql/swift/elements/stmt/Stmt.qll 205293fa5bb81dff4d7c6ec4016e1a2b319638931e94b4d65f17d2e292bb90c2 014e29f6cc639359708f4416b1719823218efa0e92dc33630ecfc051144c7ac0 ql/lib/codeql/swift/elements/stmt/StmtConditionConstructor.qll 599663e986ff31d0174500788d42a66180efb299769fc0f72a5c751621ddb9e2 8da4524319980f8039289165d01b53d588180cc1139b16ea7a6714b857086795 ql/lib/codeql/swift/elements/stmt/SwitchStmtConstructor.qll e55c4bda4e8c1b02e8bb00b546eca91b8797c9efb315d17aa9d7044bef0568b9 a8315347d620671ec752e7ff150faa6e6cbb2353773bc16f1d0162aa53f2c8ed ql/lib/codeql/swift/elements/stmt/ThrowStmtConstructor.qll 5a0905f1385b41e184c41d474a5d5fa031ed43e11c0f05b0411de097302cf81c 658daa8e97de69ed0c6bb79bc1e945c39bac9ff8d7530bd4aca5a5d3e3606a3a ql/lib/codeql/swift/elements/stmt/WhileStmtConstructor.qll 9b5711a82db7c4f2c01f124a1c787baa26fd038433979fd01e778b3326c2c357 4e89d6b2dfefd88b67ec7335376ea0cdccab047319a7ec23113728f937ff1c26 ql/lib/codeql/swift/elements/stmt/YieldStmtConstructor.qll c0aa7145a96c7ba46b904e39989f6ebf81b53239f84e5b96023ea84aef4b0195 50908d5ee60b7bc811ca1350eff5294e8426dbbab862e0866ef2df6e90c4859c -ql/lib/codeql/swift/elements/type/AnyBuiltinIntegerType.qll f89e8ede8fc455a74ad643521d3910dc27b29359f7e15b0333d823831b7cd20c bbd9611e593c95c7ddff9d648b06b236f1973759f5cd3783d359ddb7d2c7d29e -ql/lib/codeql/swift/elements/type/AnyFunctionType.qll 9a2f25f7f72aa80a2dcd936886dfda32f2b48ae44b79da58dbad5201ef4d7375 c7154b0018d161a6dcf461f351f37b2b4f6813968d2c2d0b1e357ea8c6f50710 -ql/lib/codeql/swift/elements/type/AnyGenericType.qll 9020d36bc6899c7f305cd99403d007c6d63fadfa080b4ec57372e7a76ca60975 4474fb21ac3f092f6c1e551cd9cf397abaa721ac2e30019b1d1a3974224d907d -ql/lib/codeql/swift/elements/type/AnyMetatypeType.qll d71d790b77c2d83f3637a1fbf2bae77ac5e95d8dc81a7fd662c22db586eea71c c73a76b03eee2faee33bb7e80ab057dbc6c302d9c8d5bfa452a7e919f86d942a -ql/lib/codeql/swift/elements/type/ArchetypeType.qll 5dba765115cc421e84c56e196d2a2d70310f3d8048aa78bd3b2042785aa5e880 28190086005e4e14b0556162d18aafe4d59eef0cb69e1a02bc440b27db012197 -ql/lib/codeql/swift/elements/type/ArraySliceType.qll 57184bc51fb02bc966d1ae143750a2a82e704dc52d20e314965420a83ebd9164 21d15a7dab938ce81de00b646b897e7348476da01096168430a4a19261b74f6d +ql/lib/codeql/swift/elements/type/AnyBuiltinIntegerType.qll 87eb8254d0cf194c173dd1572a2271874671b370b4e42a646959670877407d7a bbd9611e593c95c7ddff9d648b06b236f1973759f5cd3783d359ddb7d2c7d29e +ql/lib/codeql/swift/elements/type/AnyFunctionType.qll 41dc8ac19011f615f5f1e8cb0807ebe5147676e5fcbe2f56d8e560b893db7d2b c7154b0018d161a6dcf461f351f37b2b4f6813968d2c2d0b1e357ea8c6f50710 +ql/lib/codeql/swift/elements/type/AnyGenericType.qll d013979e58f7a18a719b312e29903ebb96a8f4da402477f1e2068f95f069efb9 4474fb21ac3f092f6c1e551cd9cf397abaa721ac2e30019b1d1a3974224d907d +ql/lib/codeql/swift/elements/type/AnyMetatypeType.qll 2bb251f092fe50d45735ce8fb48176bd38f4101ca01e2ac9ad4520f7b7000c66 c73a76b03eee2faee33bb7e80ab057dbc6c302d9c8d5bfa452a7e919f86d942a +ql/lib/codeql/swift/elements/type/ArchetypeType.qll 685ddff4c8246bdd4b64040daf3daee5745f13b479045da4d6394e52fb2f6ba9 28190086005e4e14b0556162d18aafe4d59eef0cb69e1a02bc440b27db012197 +ql/lib/codeql/swift/elements/type/ArraySliceType.qll b7d4e856836d2c7aa4a03aad1071824958f881ea8e1ff9e9cbce8f1e88d5a030 21d15a7dab938ce81de00b646b897e7348476da01096168430a4a19261b74f6d ql/lib/codeql/swift/elements/type/ArraySliceTypeConstructor.qll a1f1eb78e59c6ddf2c95a43908b11c25e2113c870a5b0b58e00b1ef5e89974c0 f0b4681e070343a13ee91b25aa20c0c6a474b701d1f7ea587ad72543a32dab72 -ql/lib/codeql/swift/elements/type/BoundGenericClassType.qll 7d02a471484de918f1395638f6e8017a3301f8953016c9ed62300308c6e2b6ac 284da181c967e57023009eb9e91ed4d26ae93925fea07e71d3af0d1b0c50f90a +ql/lib/codeql/swift/elements/type/BoundGenericClassType.qll a2f44b6bbe05c67d8656d389bf47a3f6892559814fbaed65939c5ea12fe98d59 284da181c967e57023009eb9e91ed4d26ae93925fea07e71d3af0d1b0c50f90a ql/lib/codeql/swift/elements/type/BoundGenericClassTypeConstructor.qll 1174753a0421f88abdca9f124768946d790f488554e9af3136bb0c08c5a6027f c6565c9f112f1297e12f025865d6b26c6622d25a8718de92222dd4fb64ede53e -ql/lib/codeql/swift/elements/type/BoundGenericEnumType.qll 685670068892a04cd20b718118c46c768488807a57cc75102b3d6be5b07e3c94 c394d8e963e2edec82b27368dc7832c033dbf56a8acd8990ff6cf825c29cc7d9 +ql/lib/codeql/swift/elements/type/BoundGenericEnumType.qll 3d7f91c9b052af2daf55369c6dfd6cbbe67f96a6595dd4e348a6bbd247dacb89 c394d8e963e2edec82b27368dc7832c033dbf56a8acd8990ff6cf825c29cc7d9 ql/lib/codeql/swift/elements/type/BoundGenericEnumTypeConstructor.qll 4faf2e4f76d446940d2801b457e8b24f5087494b145bae1e1e0a05ba2e8d4eee eda2bdd1b9f2176d8a6c78de68ae86148e35f5d75d96d78a84995ae99816f80e -ql/lib/codeql/swift/elements/type/BoundGenericStructType.qll 8e87dbeb3bad4c3b37a5260aadfac5b6c15c067a84be376ba8b5c3cf0794bd21 a3f7a3549ff7ab0bdbfda7da4c84b125c5b96073744ae62d719e9d3278e127cf +ql/lib/codeql/swift/elements/type/BoundGenericStructType.qll c136c557d506c143bacbab2096abc44463b59e8494e9ff41c04adb9a45a1baad a3f7a3549ff7ab0bdbfda7da4c84b125c5b96073744ae62d719e9d3278e127cf ql/lib/codeql/swift/elements/type/BoundGenericStructTypeConstructor.qll 9bc4dd0ffc865f0d2668e160fb0ce526bb4aa7e400ad20a10707aad839330d31 a0f28828125726f1e5d18ed7a2145ad133c3a2200523928b69abbdc1204e3349 -ql/lib/codeql/swift/elements/type/BoundGenericType.qll 1854ab70126e449cb64e9ac00b2eb465d1fac342e172a4eff6e7417a5d663d0e 86a3a2c73a837a4c58d104af5d473fe3171bd12b03d7a2862cc0ec6d2e85667f -ql/lib/codeql/swift/elements/type/BuiltinBridgeObjectType.qll 86971ec94ed0b5db7b33484d310c01e3b7d835e7845e7ec6f5f7a3e3df3bfe3d d5f2623c2742b9c123bd6789215f32dcb8035475c98b792e53c6ef583e245f65 +ql/lib/codeql/swift/elements/type/BoundGenericType.qll c1ed5f1dfb46528d410e600ddb243ef28fec4acbb3f61bbd41e3285dcb7efb41 86a3a2c73a837a4c58d104af5d473fe3171bd12b03d7a2862cc0ec6d2e85667f +ql/lib/codeql/swift/elements/type/BuiltinBridgeObjectType.qll 725db75405a3372d79ce90c174acd45a1ee7858808a6de8820bdaf094683c468 d5f2623c2742b9c123bd6789215f32dcb8035475c98b792e53c6ef583e245f65 ql/lib/codeql/swift/elements/type/BuiltinBridgeObjectTypeConstructor.qll e309fbf1bb61cc755fd0844697f8d587c63477fe11947f4af7d39b07fc731e8f 41acdb0acf0f2eb6b1b38fb57cbbf4dfcec46afc089798b829c1ffc0539cd0fc -ql/lib/codeql/swift/elements/type/BuiltinDefaultActorStorageType.qll 3f2a38da5222ebddcd9c0ef7ddccf84e26616a56e19978a2caa725ee6743e594 96777d099fe5e06a17e5770ce73fa4f50eefbe27703218871dc7dec4c2e8e11f +ql/lib/codeql/swift/elements/type/BuiltinDefaultActorStorageType.qll 15b5e290d132498c779f404253bae030070ce1f6863c04bf08b5aa63cb39e60b 96777d099fe5e06a17e5770ce73fa4f50eefbe27703218871dc7dec4c2e8e11f ql/lib/codeql/swift/elements/type/BuiltinDefaultActorStorageTypeConstructor.qll 645d8dd261fffb8b7f8d326bcdd0b153085c7cf45fe1cc50c8cb06dbe43a9d8d 0424cf62f6f0efb86a78ba55b2ef799caf04e63fdf15f3f8458108a93ee174b1 -ql/lib/codeql/swift/elements/type/BuiltinExecutorType.qll 226a09b42840529bd31c4e9795d570466462a8e5e1833edbcb36fc96458a33b3 bb2f7e62295b20fa07cc905ef0329293c932ab8ad115f8d37aa021e421b425c0 +ql/lib/codeql/swift/elements/type/BuiltinExecutorType.qll f63b4a0ea571d2561a262f1388123281222f85436332716be6b268180a349f30 bb2f7e62295b20fa07cc905ef0329293c932ab8ad115f8d37aa021e421b425c0 ql/lib/codeql/swift/elements/type/BuiltinExecutorTypeConstructor.qll 72545245dbf61a3ab298ece1de108950c063b146a585126753684218ad40ea10 b926c1688325022c98611b5e7c9747faf0faf8f9d301d976aa208a5aace46e0d -ql/lib/codeql/swift/elements/type/BuiltinFloatType.qll 7b307414ec4175d87ef715abe950830214785eca4728bfe32542f89f061cc3a6 3dfa2ed2e1f469e1f03dcc88b29cb2318a285051aa2941dcc29c7c925dad0d29 +ql/lib/codeql/swift/elements/type/BuiltinFloatType.qll f9fca26d0c875f6bc32f3a93f395ef8b4c5803eca89cfbefe32f1cdd12d21937 3dfa2ed2e1f469e1f03dcc88b29cb2318a285051aa2941dcc29c7c925dad0d29 ql/lib/codeql/swift/elements/type/BuiltinFloatTypeConstructor.qll 4254aa8c61c82fbea44d3ca1a94876546024600a56ac88d0e622c6126dfe6b9f 953f0fcb52668e1a435f6cabf01f9c96c5fc1645bf90b8257907218a4ce51e02 -ql/lib/codeql/swift/elements/type/BuiltinIntegerLiteralType.qll 5ca7d5b579924cd37d67703ce032fd626f6f2e53aecbd8246284471a7c766237 462bfc80eb0cfe478562fc5dcade8e6a1ecdd958b26481e4df19ecf632e72a7f +ql/lib/codeql/swift/elements/type/BuiltinIntegerLiteralType.qll 9c38b871442670d4c61f6b388f334f5013e7c6518d9461404d13ee9e7fbd75fb 462bfc80eb0cfe478562fc5dcade8e6a1ecdd958b26481e4df19ecf632e72a7f ql/lib/codeql/swift/elements/type/BuiltinIntegerLiteralTypeConstructor.qll 21c0ba7a316accd4197d57dafbeb7ce356ccef0a376e9188ec78b3e9a7d046bd 165f4a30ffb1fa34ee94c69975cbea57d940aea2e46558af7eff3a1941a269c2 -ql/lib/codeql/swift/elements/type/BuiltinIntegerType.qll ba9c4722bc8adcd3b81a516f228a2d1d6c6900a0a74c1586e6fda11fdc57cde9 2807cb11ca75f8d8cc3bc87159786528f7f28e6c594ee79bf0984d0dd960d524 +ql/lib/codeql/swift/elements/type/BuiltinIntegerType.qll 7204f4a0bd93886cf890c00285fc617d5b8e7236b564ad375ff2ff98a9b1cc58 2807cb11ca75f8d8cc3bc87159786528f7f28e6c594ee79bf0984d0dd960d524 ql/lib/codeql/swift/elements/type/BuiltinIntegerTypeConstructor.qll 8e738b8996c0b1612900dd40d6dd9ea395e7463a501feb04cc3c27e7fe73ee02 c517e29002513b5ae6d05d52bc3f7e8a85f33f6e9be0f56cdd53eb25de0c9cb9 -ql/lib/codeql/swift/elements/type/BuiltinJobType.qll 77ae06df788a1d6bdf060525f842408fb5ff773397862d30dfd46f80fe889c64 7c381ec2a6be2991518cfeef57be62238f50c27845cad8b72434c404ecc5c298 +ql/lib/codeql/swift/elements/type/BuiltinJobType.qll c216da7f6573f57fcfc72d930da56223b5561cbad9e2b069225183186ac58415 7c381ec2a6be2991518cfeef57be62238f50c27845cad8b72434c404ecc5c298 ql/lib/codeql/swift/elements/type/BuiltinJobTypeConstructor.qll a63724058d426fc38c092235adec6348aa9ea302aca408d4e9721d924ec28539 abf1263e6fad8f3de7692340399f013010f39c01f5fe93b92a491b7301be998c -ql/lib/codeql/swift/elements/type/BuiltinNativeObjectType.qll 5fddd40563fdff908bd357c5b34086b927f9e615554a8c0942a3bc24ee5936fc 3225e0b8e70f488b84d02b84ef02bf1a3ac879d8f442de2b6d2c3ae53445e8e8 +ql/lib/codeql/swift/elements/type/BuiltinNativeObjectType.qll d4d34922e2ace08e0b09cc542c161d9dadb044c1c5bf08519744f082c34ee606 3225e0b8e70f488b84d02b84ef02bf1a3ac879d8f442de2b6d2c3ae53445e8e8 ql/lib/codeql/swift/elements/type/BuiltinNativeObjectTypeConstructor.qll 9ec77aa1da74d7fe83a7c22e60a6b370d04c6859e59eed11b8dbc06a1ac8e68b bd9dcd8c5317d13a07695c51ff15f7d9cbf59ad7549301d42950caf5c6cc878f -ql/lib/codeql/swift/elements/type/BuiltinRawPointerType.qll 06ebac74cfcdc7195de3159d528288afb32786a071e42c2ede932666d89ea4d3 d2f6b327e6c5d4ff9382041bcebad2b9312eb86116c42b24b88c558b10a7561a +ql/lib/codeql/swift/elements/type/BuiltinRawPointerType.qll 1b67c5ccde71e14b30f1e2f636762fa2e21a492410015b4dc5a085b91499be23 d2f6b327e6c5d4ff9382041bcebad2b9312eb86116c42b24b88c558b10a7561a ql/lib/codeql/swift/elements/type/BuiltinRawPointerTypeConstructor.qll 7f77e1c768cb46b0eb8b08bb36e721417b95f1411bd200636ffdfc4e80c3c5c3 ce0916e95044ad74f5d7e762f3cc22065cc37e804f094e6067908bd635da6d97 -ql/lib/codeql/swift/elements/type/BuiltinRawUnsafeContinuationType.qll c91a28c12be5694004e02680d5d32bc3b67208ef6a7e0f9ab04cd4a7bb3a83ed 81682a768dcbcd72b2f13b5257e1f05b642e762de92bb3f0e275f863bad261c7 +ql/lib/codeql/swift/elements/type/BuiltinRawUnsafeContinuationType.qll 1db1db613e5c0c37cdc05347be6e386e65a1ad641d84ada08d074e2d64d09a61 81682a768dcbcd72b2f13b5257e1f05b642e762de92bb3f0e275f863bad261c7 ql/lib/codeql/swift/elements/type/BuiltinRawUnsafeContinuationTypeConstructor.qll f5a6c5ea5dd91c892f242b2a05837b2a4dd440365a33749994df8df30f393701 2eab1e5815c5f4854f310a2706482f1e7b401502291d0328d37184e50c0136b9 -ql/lib/codeql/swift/elements/type/BuiltinType.qll 6031ef4546c562d127d7c7120d12b9183021f2d9ff171ebf41ffa8491ce1a628 8e02dc1d67222a969ba563365897d93be105a64ec405fd0db367370624796db2 -ql/lib/codeql/swift/elements/type/BuiltinUnsafeValueBufferType.qll 2feff34c6e0c3cb22ff287b4b0fd7bac97ce796289175524a63c0a16258ef966 27a98fe13786b8d59d587ac042e440dec6699c76eb65288bbff6d374c28bfc53 +ql/lib/codeql/swift/elements/type/BuiltinType.qll 0db7c8fbeebf26beb7aa7d4b7aeed7de8e216fd90338c1c8e9324e88856afb2b 8e02dc1d67222a969ba563365897d93be105a64ec405fd0db367370624796db2 +ql/lib/codeql/swift/elements/type/BuiltinUnsafeValueBufferType.qll 83cb313f10a00430c2192cbc9c2df918ac847fa56af921cda916c505dcbc604f 27a98fe13786b8d59d587ac042e440dec6699c76eb65288bbff6d374c28bfc53 ql/lib/codeql/swift/elements/type/BuiltinUnsafeValueBufferTypeConstructor.qll 08a3a0f1ab53739a0db79a185a0e05538c1b7c7318b25bea93e0044ad98a3c6b fb8bb4ca4b20c6581d4419ac48581bf6e75b20e1612a953e31a7207c7dd0a0d8 -ql/lib/codeql/swift/elements/type/BuiltinVectorType.qll cfe1887a0f626704881622fb63287bc408fcf72022c8ba7f3bd14974068f36a5 df375c900db766f3f66dc022cb6302f2000bda90b5f2f023be992519948151f1 +ql/lib/codeql/swift/elements/type/BuiltinVectorType.qll c170367af631c35a4dfab970c4c098cd665de5c0a5089c6d2c4c2257c5b21dcd df375c900db766f3f66dc022cb6302f2000bda90b5f2f023be992519948151f1 ql/lib/codeql/swift/elements/type/BuiltinVectorTypeConstructor.qll 81d10e15693a33c51df659d4d8e8fa5dedea310415f580c6861e0043d36e83d3 3f60d067b860f3331edb5c0e67b2e9e469b78a9bcdb39a2f3a8724c6a6638f5e -ql/lib/codeql/swift/elements/type/ClassType.qll a69b0552206ca564124dfc9befd6288c0b84dcbadfd758baa85a33e0d8b820e8 a50d11cff50d948fcbbe3d27332f7e5842291844eaee9750d72063b7d2c0d7c2 +ql/lib/codeql/swift/elements/type/ClassType.qll a1ef05a05913dc14bc6a9f960b68429ba9f97e487eccac5ab0ca6efb6fa48892 a50d11cff50d948fcbbe3d27332f7e5842291844eaee9750d72063b7d2c0d7c2 ql/lib/codeql/swift/elements/type/ClassTypeConstructor.qll 0c462e43cc8139d666fe1d77b394f29f4141064c9295ec3581fe20f920cbbbe7 43cce957ebb274ff34f14ca8bdcf93ab9c81a27a204fa56e37d7d17c4a469600 -ql/lib/codeql/swift/elements/type/DependentMemberType.qll 5d57942f02b68fce9970176a15365cd5a4e7c8092f886781388098d53cdc8615 46b2e84f7731e2cc32b98c25b1c8794f0919fbd3c653ba9b2e82822ab351e164 +ql/lib/codeql/swift/elements/type/DependentMemberType.qll 91859dbfb738f24cf381f89493950dbf68591184c0b0a1c911c16e7abfd9f5a9 46b2e84f7731e2cc32b98c25b1c8794f0919fbd3c653ba9b2e82822ab351e164 ql/lib/codeql/swift/elements/type/DependentMemberTypeConstructor.qll 8580f6bbd73045908f33920cbd5a4406522dc57b5719e6034656eec0812d3754 fdeba4bfc25eecff972235d4d19305747eaa58963024735fd839b06b434ae9f2 -ql/lib/codeql/swift/elements/type/DictionaryType.qll b5b815ec4518781ccc600caaea81371e95fbee8a97803e5dce8e0bfc8789bae6 6b6901e8331ae2bd814a3011f057b12431f37b1ad57d3ecdaf7c2b599809060f +ql/lib/codeql/swift/elements/type/DictionaryType.qll a0f447b3bb321683f657a908cb255d565b51e4d0577691bb8293fa170bfbf871 6b6901e8331ae2bd814a3011f057b12431f37b1ad57d3ecdaf7c2b599809060f ql/lib/codeql/swift/elements/type/DictionaryTypeConstructor.qll 663bd10225565fab7ecd272b29356a89750e9fc57668b83bdb40bfb95b7b1fcb 5bfe2900eceee331765b15889357d3b45fc5b9ccaf034f13c76f51ad073c247f -ql/lib/codeql/swift/elements/type/DynamicSelfType.qll 7ba19e4fa1a8bbbc41fb08c16abbd1949feebe8ddadad7d3dfcb525f2abf5746 f9544f83ee11ae2317c7f67372a98eca904ea25667eeef4d0d21c5ef66fe6b28 +ql/lib/codeql/swift/elements/type/DynamicSelfType.qll 699680b118d85eacbbb5866674b894ba8ef1da735496577183a1cb45993487e9 f9544f83ee11ae2317c7f67372a98eca904ea25667eeef4d0d21c5ef66fe6b28 ql/lib/codeql/swift/elements/type/DynamicSelfTypeConstructor.qll f81ea2287fade045d164e6f14bf3f8a43d2bb7124e0ad6b7adf26e581acd58ff 73889ef1ac9a114a76a95708929185240fb1762c1fff8db9a77d3949d827599a -ql/lib/codeql/swift/elements/type/EnumType.qll d5428bcca8398cfbf706689b32390460d8c93cc2c733ceb10432ed496d11579d 7eb0dad9ffc7fad2a22e68710deac11d5e4dfa18698001f121c50850a758078f +ql/lib/codeql/swift/elements/type/EnumType.qll 660e18e8b8061af413ba0f46d4c7426a49c5294e006b21a82eff552c3bb6009b 7eb0dad9ffc7fad2a22e68710deac11d5e4dfa18698001f121c50850a758078f ql/lib/codeql/swift/elements/type/EnumTypeConstructor.qll aa9dbd67637aae078e3975328b383824a6ad0f0446d17b9c24939a95a0caf8df 1d697f400a5401c7962c09da430b8ce23be063aa1d83985d81bcdc947fd00b81 -ql/lib/codeql/swift/elements/type/ErrorType.qll ac897e297783736a984eb6168be9b300b7a2a536ae3988b6ec29426a38bc11f0 c02282abefeb4c93938cc398d4c06ccd2be2c64e45612f20eafc73783fa84486 +ql/lib/codeql/swift/elements/type/ErrorType.qll 5d76dafba387c6fd039717f2aa73e3976ae647e1abc86343f153ec6ce9221402 c02282abefeb4c93938cc398d4c06ccd2be2c64e45612f20eafc73783fa84486 ql/lib/codeql/swift/elements/type/ErrorTypeConstructor.qll b62dcd329e8bba82bd70aa439ed4d0ddb070da6fcd3ce5ce235e9c660ce5b5a8 43e3c4b7174bc17ca98c40554c2dbae281f1b66617d8ae59e8f970308fd24573 -ql/lib/codeql/swift/elements/type/ExistentialMetatypeType.qll 2b37fa25e3a06b42b3ecb211c1d4ca72f85a99474714811ef5e89d5c2e5e4592 e22e904092b9c5784aa2890968a27265df277c60f88d968e2546f39ab6454536 +ql/lib/codeql/swift/elements/type/ExistentialMetatypeType.qll a4adda440c77818b1bf9e6a749ff3cf8faf208111253277602f4181a41bff049 e22e904092b9c5784aa2890968a27265df277c60f88d968e2546f39ab6454536 ql/lib/codeql/swift/elements/type/ExistentialMetatypeTypeConstructor.qll a6b088425c0b0993b3ba3649a49c72c15c7bb3b369f610a7971d5cef858ed9b8 56e8663f9c50f5437b6f8269e41675e8832cfae7aa3b204fa03b86d4f35ce9ff -ql/lib/codeql/swift/elements/type/ExistentialType.qll 8cc0eb534ea2152dcd83e986103616c4f7aa31f0c0e23c73c1addcb39e3758b2 0d5ef028a6bd998fa2de2f4456bf7519202a2f0e66f2bc98bcb43c8af686cade +ql/lib/codeql/swift/elements/type/ExistentialType.qll 997436bc80cdc5bc383ead44f1ce84050fad048e04aeab2affafbec836eaf7a9 0d5ef028a6bd998fa2de2f4456bf7519202a2f0e66f2bc98bcb43c8af686cade ql/lib/codeql/swift/elements/type/ExistentialTypeConstructor.qll bc9bd26dc789fe389c5f9781a0d5465189c4b685ef29cd9ca3488c64b5423e45 d9977de27830d154e2afa34c3c69a7a02b750eda00a21a70554ca31c086cfe2e -ql/lib/codeql/swift/elements/type/FunctionType.qll e2d289fcb9e2fabfaef2a1265b29fa1595e3e188eec7d8d5847ad7d2862d4a6e 1bfc06f2ca2abf5861602fc45ab4531f69bf40646ac39a12f3b6dba8e43b0b21 +ql/lib/codeql/swift/elements/type/FunctionType.qll 0bb0fa2d0dac2159de262afa23950f4b10ee0c03b3ce4ea5ba3048e56623a797 1bfc06f2ca2abf5861602fc45ab4531f69bf40646ac39a12f3b6dba8e43b0b21 ql/lib/codeql/swift/elements/type/FunctionTypeConstructor.qll 1fa2829f1ee961a1ce1cfd8259a6cc88bedcbee0aad7aece207839b4066e73f4 8537e7e2f61998e5cf1920fb872089e68b81d67d5e9939611117e7e5a6d62eb5 -ql/lib/codeql/swift/elements/type/GenericFunctionType.qll 06446c074997ba2b99aa0f4f5d1928e01117e431326578e2ead6294abd90daf0 6d52f6ee2f3b6e9976d473d0d33ab1b9b3274f1e6b352f2d1e33215a27d68ad4 +ql/lib/codeql/swift/elements/type/GenericFunctionType.qll d25013c5db3796d21779998362fc7733e1d4f521a837db866b3ab12643da00d1 6d52f6ee2f3b6e9976d473d0d33ab1b9b3274f1e6b352f2d1e33215a27d68ad4 ql/lib/codeql/swift/elements/type/GenericFunctionTypeConstructor.qll cd3099dfa77dc5186c98e6323a0e02f6496e5b2ab131aab7b3dac403365607d0 cf6c83cef81a52c336e10f83f3eff265df34d97fbe5accdebaccfa24baefe07b -ql/lib/codeql/swift/elements/type/GenericTypeParamType.qll 6881305d3599d5a511561e4eae0664a5681d8cbb2aa6718dfffcde943474cef0 e1288015ff8a0261edc1876320ea475180d0e6e75f4b5565b1ccd1498949740f +ql/lib/codeql/swift/elements/type/GenericTypeParamType.qll 1e30358a2607f8955ec1a6a36fe896a48eb8d80f7b3f5e1b20757f948cfd4f69 e1288015ff8a0261edc1876320ea475180d0e6e75f4b5565b1ccd1498949740f ql/lib/codeql/swift/elements/type/GenericTypeParamTypeConstructor.qll 4265701fad1ad336be3e08e820946dcd1f119b4fa29132ae913318c784236172 d4bf5127edc0dfa4fb8758081a557b768c6e4854c9489184c7955f66b68d3148 -ql/lib/codeql/swift/elements/type/InOutType.qll d2f6be1da40e93a6d6745b467824b1e974bb64ec56378dc328cc3e864c54e433 942f46afd617151783c79c69d96234aa4ca5741084b12b3d8349338cebb99cc2 +ql/lib/codeql/swift/elements/type/InOutType.qll 4492731832cd19d9b789c91b28bb41a35943bae18116928f8b309db986b7f4c7 942f46afd617151783c79c69d96234aa4ca5741084b12b3d8349338cebb99cc2 ql/lib/codeql/swift/elements/type/InOutTypeConstructor.qll c4889f1009018a55d0ac18c5f2a006572ac6de1f57633adc904e8a2046c09e83 8a2496df02e9f5fcb07331165cee64f97dd40dc4b4f8f32eacaf395c7c014a99 ql/lib/codeql/swift/elements/type/LValueTypeConstructor.qll e426dac8fce60f9bbd6aa12b8e33230c405c9c773046226c948bc9791e03c911 4d495938b0eb604033cea8ff105854c0c9917dbad59bb47a8751fc12d7554bdd -ql/lib/codeql/swift/elements/type/MetatypeType.qll 5d2995b2269ec118daf81268cca62beaa4189e65cae32ef7ec83b9129858cef8 34c021dc051d5d80410cd7aa25b45ccd2d7b267b2bbcb92f4249f528f524c5d8 +ql/lib/codeql/swift/elements/type/MetatypeType.qll 9f35b4075ece8a688a6597a1e435d2b65b725b652deeeb24b3921ee1931c2c85 34c021dc051d5d80410cd7aa25b45ccd2d7b267b2bbcb92f4249f528f524c5d8 ql/lib/codeql/swift/elements/type/MetatypeTypeConstructor.qll 5dfa528a0c849afa46ad08c4c92e47c3bc3418abb7674e94a0d36bc0e45d5686 6b95579b99e4cdd53cc95d9288ecbdb07ef268e5344e467336d89adddb7cc853 -ql/lib/codeql/swift/elements/type/ModuleType.qll 5f7540f8520ee7e3c7c15c1f7da269e4acd4b02b57912902e3d334fc53a9ac76 2b6cec36c543c6319178415b9ccb29e4f840b1f6e8b760a83d0f9399722995da +ql/lib/codeql/swift/elements/type/ModuleType.qll 749d4513ec389745d2082ab67bc57ba39338c4ab2421520c61f9c5aa10dd3178 2b6cec36c543c6319178415b9ccb29e4f840b1f6e8b760a83d0f9399722995da ql/lib/codeql/swift/elements/type/ModuleTypeConstructor.qll da4d1836c7e453d67221f59d007b5aff113ee31b4c9ad9445c2a7726851acf9b c902ed1ffbde644498c987708b8a4ea06ab891ffd4656ab7eb5008420bd89273 -ql/lib/codeql/swift/elements/type/NominalOrBoundGenericNominalType.qll 76248640645cf2f6ad096a73189447b3b42565e91d8f85ee1a0e3922a231c1a5 bf7e4ff426288481e9b6b5c48be7ff10a69ace0f2d2a848462c21ad9ec3167b7 -ql/lib/codeql/swift/elements/type/OpaqueTypeArchetypeType.qll fe987d7f715f118695b43ceebd4ab6c7fc9eab1530fbb54f3b79b8edfb5666a2 73bf49c826d791678af964d51836c0e1693e994465af9531aa4d1a542455c93f +ql/lib/codeql/swift/elements/type/NominalOrBoundGenericNominalType.qll a5017d79e03cae5a5ef2754493c960ad4f2d5fe5304930bbfacdae5f0084e270 bf7e4ff426288481e9b6b5c48be7ff10a69ace0f2d2a848462c21ad9ec3167b7 +ql/lib/codeql/swift/elements/type/OpaqueTypeArchetypeType.qll a607eccaa3b13eb5733698cb7580248f07ff364e4c84cec6b7aa8e78415b52da 73bf49c826d791678af964d51836c0e1693e994465af9531aa4d1a542455c93f ql/lib/codeql/swift/elements/type/OpaqueTypeArchetypeTypeConstructor.qll 20c8aa032f25f2e9759d69849e943e7049a22f8b452c055591be982f8c1aee2b 17341a9c4ec4bbad59c82d217501c771df2a58cb6adb8f1d50cf4ec31e65f803 -ql/lib/codeql/swift/elements/type/OpenedArchetypeType.qll a69b4dc52f6e25014a0db401ca90a7f827c1c906cc91ab9dd18be6b3296acefe 49fd53e2f449da6b2f40bf16f3e8c394bf0f46e5d1e019b54b5a29a3ad964e2b +ql/lib/codeql/swift/elements/type/OpenedArchetypeType.qll 3af97aac92e30de46c02df1d5cc0aaa013157c8e7b918754de162edb7bdc7130 49fd53e2f449da6b2f40bf16f3e8c394bf0f46e5d1e019b54b5a29a3ad964e2b ql/lib/codeql/swift/elements/type/OpenedArchetypeTypeConstructor.qll cc114bee717de27c63efed38ddb9d8101e6ba96e91c358541625dc24eb0c6dd5 92c1f22b4c9e0486a2fd6eca7d43c7353ac265026de482235d2045f32473aeb7 -ql/lib/codeql/swift/elements/type/OptionalType.qll 27e81ae79cbfa22c8cda3839ebaac95d11abf68615caedc2bd8c0c3362cbc7c6 37be60f19fd806fa4e1c66d6bee4091e1fb605861d1f79aa428a1e7b6b991280 +ql/lib/codeql/swift/elements/type/OptionalType.qll 1a10dfe16e62c31570a88217922b00adb5a6476a6108ee0f153eedc8c2d808ac 37be60f19fd806fa4e1c66d6bee4091e1fb605861d1f79aa428a1e7b6b991280 ql/lib/codeql/swift/elements/type/OptionalTypeConstructor.qll 61219c8fa7226e782b36e1f5a2719272e532146004da9358e1b369e669760b7e 74621440a712a77f85678bc408e0f1dc3da4d0971e18ef70c4de112800fc48ac -ql/lib/codeql/swift/elements/type/ParameterizedProtocolType.qll 342a6a5bc7709d9de4819041e1b9b85caf8d716e4b817020d4eff12d8790006c 78b09022b0f9448d347c9faf7b8373ebae40c889428e342e0cefbd228ceff053 +ql/lib/codeql/swift/elements/type/ParameterizedProtocolType.qll c6f6200aca0b3fdd7bc4ed44b667b98f6d5e175ca825bf58ed89b7a68e10415b 78b09022b0f9448d347c9faf7b8373ebae40c889428e342e0cefbd228ceff053 ql/lib/codeql/swift/elements/type/ParameterizedProtocolTypeConstructor.qll 549649fd93b455bb6220677733a26539565240bc8b49163e934e9a42ebebd115 3886762d26172facf53a0baab2fe7b310a2f356cf9c30d325217ba2c51c136f4 -ql/lib/codeql/swift/elements/type/ParenType.qll 8a1aaf7c3e4c354a3848b3285d0261d1dc14324d65dfa64986cc9240f3869eed cde8c9488dfefbbdb177c6d37f7aa3f9c2f327e0d92383b294fbd2172bba2dff +ql/lib/codeql/swift/elements/type/ParenType.qll d4bbda58390f3da19cd7eca5a166c9b655c8182b95933379e1f14554e39d3d31 cde8c9488dfefbbdb177c6d37f7aa3f9c2f327e0d92383b294fbd2172bba2dff ql/lib/codeql/swift/elements/type/ParenTypeConstructor.qll a8dc27a9de0d1492ba3bab4bf87aa45e557eccf142cee12ffde224cd670d41df a08ce80fcd6255bc2492e2447c26210631ca09a30c4cc3874eb747ae1153bf66 -ql/lib/codeql/swift/elements/type/PrimaryArchetypeType.qll f9807812ae3827e0f195935b44528537ff91e769df131ac4755b0547c113834d c950a30ba14eaad1b72d944b5a65ba04dd064726cf65061b472fefdfa8828dbb +ql/lib/codeql/swift/elements/type/PrimaryArchetypeType.qll a23c97ee4f7a4f07c7f733e993172a0254e6a1685bcb688d96e93665efcdfefe c950a30ba14eaad1b72d944b5a65ba04dd064726cf65061b472fefdfa8828dbb ql/lib/codeql/swift/elements/type/PrimaryArchetypeTypeConstructor.qll a0d24202332449b15a1e804959896f045c123e2153291a7a2805473b8efbb347 1be1fbfbff1bb63f18402e4e082878b81d57708cfc20d1499f5fd91e8332b90b -ql/lib/codeql/swift/elements/type/ProtocolCompositionType.qll 97bdcfde6955bef578f121f803ce5cea42ebca80568ae6eb8d3451f079b8fd3d 3048be59e02ee821e8bf2d470b8901f61b18075696d598babda1964b2b00cbde +ql/lib/codeql/swift/elements/type/ProtocolCompositionType.qll 1b22a4ac7bd800c9d159f38c1b12230e54c0991abec8a578ec92e950c092f458 3048be59e02ee821e8bf2d470b8901f61b18075696d598babda1964b2b00cbde ql/lib/codeql/swift/elements/type/ProtocolCompositionTypeConstructor.qll b5f4d7e73ea9281874521acf0d91a1deb2f3744854531ee2026913e695d5090d be55225d2fd21e40d9cacb0ad52f5721fed47c36a559d859fba9c9f0cb3b73c3 -ql/lib/codeql/swift/elements/type/ProtocolType.qll 7f6806952e1fe87648516cdc310370ccd886a53f4a2014e9d62cd6ce14dbd7c3 527b2acdc24eca89847fa80deb84b9584d9c92fab333724f5994dfb5e475269d +ql/lib/codeql/swift/elements/type/ProtocolType.qll 7e1246c87e6119b14d31ae40b66e1ab049938ae6843f4e7831872b63066cac1a 527b2acdc24eca89847fa80deb84b9584d9c92fab333724f5994dfb5e475269d ql/lib/codeql/swift/elements/type/ProtocolTypeConstructor.qll c0252a9975f1a21e46969d03e608d2bd11f4d1f249406f263c34232d31c9574d 145e536a0836ed5047408f0f4cf79ab8855938e99927e458d3a893cd796fda74 -ql/lib/codeql/swift/elements/type/ReferenceStorageType.qll 12966c9aeaec22d3991ba970a314d8618971f7f6a579f249c88c47333fc518a2 5635deaf09199afe8fff909f34f989c864c65447c43edf8d8e2afdf0e89a7351 -ql/lib/codeql/swift/elements/type/StructType.qll 1b92a9a6107abd816d00193b910ab236de700299793b90fa50bfbea6e0055f45 07d5b0a29e946a7e5bf6dc131b6373745f75dbdbca6fe6a3843d4b0ba7ab0309 +ql/lib/codeql/swift/elements/type/ReferenceStorageType.qll 56572b3fb5d6824f915cab5a30dc9ef09e9aa3fff4e2063d52ad319f2d8f86c6 5635deaf09199afe8fff909f34f989c864c65447c43edf8d8e2afdf0e89a7351 +ql/lib/codeql/swift/elements/type/StructType.qll 27df69f9bd97539dbd434be8d72f60fc655b2ad3880975f42713e9ff1c066f20 07d5b0a29e946a7e5bf6dc131b6373745f75dbdbca6fe6a3843d4b0ba7ab0309 ql/lib/codeql/swift/elements/type/StructTypeConstructor.qll a784445a9bb98bb59b866aff23bbe4763e02a2dc4a268b84a72e6cd60da5b17d 8718e384a94fd23910f5d04e18f2a6f14b2148047244e485214b55ae7d28e877 -ql/lib/codeql/swift/elements/type/SubstitutableType.qll 2dc4774a5b6c941376e37785b34891e9311075715af840273322fd422e93e671 cdc27e531f61fb50aaa9a20f5bf05c081759ac27df35e16afcdd2d1ecdac5da0 -ql/lib/codeql/swift/elements/type/SugarType.qll d13faf1eb71d9fa1d6fd378455cbbcfea49029e94303e33f1d08bb03d115d654 cbcbd68098b76d99c09e7ee43c9e7d04e1b2e860df943a520bf793e835c4db81 -ql/lib/codeql/swift/elements/type/SyntaxSugarType.qll 0843801d8abcb3090a6dc8c41cce5d60bba47761aa68f3c89ce21cf659696af5 a7a002cf597c3e3d0fda67111116c61a80f1e66ab8db8ddb3e189c6f15cadda6 -ql/lib/codeql/swift/elements/type/TupleType.qll ef49280a8d01acf3ecba2d3c12b512d3d3480048c412d922a1997cb1ac76fc6b 0b34c17ce9db336d0be9a869da988f31f10f754d6ffab6fa88791e508044edd2 +ql/lib/codeql/swift/elements/type/SubstitutableType.qll 78a240c6226c2167a85dce325f0f3c552364daf879c0309ebefd4787d792df23 cdc27e531f61fb50aaa9a20f5bf05c081759ac27df35e16afcdd2d1ecdac5da0 +ql/lib/codeql/swift/elements/type/SugarType.qll 0833a0f1bd26b066817f55df7a58243dbd5da69051272c38effb45653170d5c1 cbcbd68098b76d99c09e7ee43c9e7d04e1b2e860df943a520bf793e835c4db81 +ql/lib/codeql/swift/elements/type/SyntaxSugarType.qll 699fe9b4805494b62416dc86098342a725020f59a649138e6f5ba405dd536db5 a7a002cf597c3e3d0fda67111116c61a80f1e66ab8db8ddb3e189c6f15cadda6 +ql/lib/codeql/swift/elements/type/TupleType.qll 1dc14882028be534d15e348fba318c0bb1b52e692ca833987e00c9a66a1921ad 0b34c17ce9db336d0be9a869da988f31f10f754d6ffab6fa88791e508044edd2 ql/lib/codeql/swift/elements/type/TupleTypeConstructor.qll 060633b22ee9884cb98103b380963fac62a02799461d342372cfb9cc6303d693 c9a89f695c85e7e22947287bcc32909b1f701168fd89c3598a45c97909e879f4 -ql/lib/codeql/swift/elements/type/TypeAliasType.qll 615273f833d588940a32e16adacdfa56b6ac480e1aca6ebd11adfaa878b6d19e 760c79b9b581cc645f1002ca892656d406d3d339267fd58e765738257dbb45ce +ql/lib/codeql/swift/elements/type/TypeAliasType.qll 8149cc01f6d47ab10c0e20f1892af5e5d778e11a76be5f4752ad349a4c5b4fa4 760c79b9b581cc645f1002ca892656d406d3d339267fd58e765738257dbb45ce ql/lib/codeql/swift/elements/type/TypeAliasTypeConstructor.qll f63ada921beb95d5f3484ab072aa4412e93adfc8e7c0b1637273f99356f5cb13 f90d2789f7c922bc8254a0d131e36b40db1e00f9b32518633520d5c3341cd70a ql/lib/codeql/swift/elements/type/TypeReprConstructor.qll 2bb9c5ece40c6caed9c3a614affc0efd47ad2309c09392800ad346bf369969bf 30429adc135eb8fc476bc9bc185cff0a4119ddc0e618368c44f4a43246b5287f -ql/lib/codeql/swift/elements/type/UnarySyntaxSugarType.qll 072fbc064fb059a49befab907dd6049b4bf1a28e4ba3fcddf3e73d7913bc3906 0b113b1a7834779fabfa046a64c6d256cde0f510edb84da253e89d36f41f8241 -ql/lib/codeql/swift/elements/type/UnboundGenericType.qll 21878a4bf3ad77085812ad55c85e3ed0257cad10e6d7c72e513aae81616ef405 cca58789f97e51acb9d873d826eb77eda793fc514db6656ee44d33180578680c +ql/lib/codeql/swift/elements/type/UnarySyntaxSugarType.qll 712c7e75b8169a80a44a6609da7f5a39cc4f36773eb520c8824ea09295c6929c 0b113b1a7834779fabfa046a64c6d256cde0f510edb84da253e89d36f41f8241 +ql/lib/codeql/swift/elements/type/UnboundGenericType.qll 5a74162b28290141d389562e3cb49237977c6d642a80ae634b57dc10e7c811b1 cca58789f97e51acb9d873d826eb77eda793fc514db6656ee44d33180578680c ql/lib/codeql/swift/elements/type/UnboundGenericTypeConstructor.qll 63462b24e0acceea0546ec04c808fb6cf33659c44ea26df1f407205e70b0243d d591e96f9831cce1ca6f776e2c324c8e0e1c4e37077f25f3457c885e29afbf3e -ql/lib/codeql/swift/elements/type/UnmanagedStorageType.qll 3e8276cc1bae19f448027d2a0629c95c0b58b3e096b898ef006cb5eaea613908 d32206af9bf319b4b0b826d91705dbd920073d6aaa002a21ec60175996ab9d1a +ql/lib/codeql/swift/elements/type/UnmanagedStorageType.qll e36e70fd22798af490cb2a5c3ca0bc6ae418831ae99cab1e0444e6e70808545d d32206af9bf319b4b0b826d91705dbd920073d6aaa002a21ec60175996ab9d1a ql/lib/codeql/swift/elements/type/UnmanagedStorageTypeConstructor.qll c5927ab988beb973785a840840647e47cc0fb6d51712bed796cb23de67b9d7d6 b9f0f451c58f70f54c47ad98d9421a187cf8bd52972e898c66988a9f49e4eda0 -ql/lib/codeql/swift/elements/type/UnownedStorageType.qll 18923326a76bcfa31697551fb001a06b2a38ea074fa312c47953dd9a7ac16604 3b5d90688070be5dc0b84ab29aed2439b734e65d57c7556c6d763f5714a466ba +ql/lib/codeql/swift/elements/type/UnownedStorageType.qll 2a8be26447acc1bcfddc186b955764cea7ef8e4d64068ec55d8759b6c59d30bf 3b5d90688070be5dc0b84ab29aed2439b734e65d57c7556c6d763f5714a466ba ql/lib/codeql/swift/elements/type/UnownedStorageTypeConstructor.qll 211c9f3a9d41d1c9e768aa8ece5c48cca37f7811c5daab8bf80fdc2bd663dd86 c4fb8b39d319e1c27175f96ceec9712f473e0df1597e801d5b475b4c5c9c6389 -ql/lib/codeql/swift/elements/type/UnresolvedType.qll d573017fef5394a11d43cdcbaad91060e0b1e4c9ba6f2a9e358f818176ca8f45 680dd2fc64eeec5f81d2c2a05221c56a1ef7004bdcb1a8517640caa5fba0890d +ql/lib/codeql/swift/elements/type/UnresolvedType.qll 9bdb52645208b186cd55dac91cdee50dc33fc49e10e49fadbfd1d21c33996460 680dd2fc64eeec5f81d2c2a05221c56a1ef7004bdcb1a8517640caa5fba0890d ql/lib/codeql/swift/elements/type/UnresolvedTypeConstructor.qll 76c34ca055a017a0fa7cfff93843392d0698657fbf864ac798e1ae98325b3556 d0770637ec9674f9e2a47ad5c59423b91d12bb22a9d35dcfa8afa65da9e6ed93 -ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 5bca77dd661d3b2653d31005c2341b408c86661e89ae0cab9539999ecac60eea 3ac870a1d6df1642fae26ccda6274a288524a5cf242fab6fac8705d70e3fca88 +ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 325e4c4481e9ac07acdc6aebbcfef618bcaeb420c026c62978a83cf8db4a2964 3ac870a1d6df1642fae26ccda6274a288524a5cf242fab6fac8705d70e3fca88 ql/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856 -ql/lib/codeql/swift/elements/type/WeakStorageType.qll 87a28616eea3600fb0156fffcd65eeddc1ea74ce9c0ba5886c6365b9359e00ce 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996 +ql/lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996 ql/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897 ql/lib/codeql/swift/elements.qll 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 ql/lib/codeql/swift/generated/AstNode.qll 02ca56d82801f942ae6265c6079d92ccafdf6b532f6bcebd98a04029ddf696e4 6216fda240e45bd4302fa0cf0f08f5f945418b144659264cdda84622b0420aa2 @@ -660,11 +660,11 @@ ql/lib/codeql/swift/generated/type/VariadicSequenceType.qll 796537097d8e32eda38b ql/lib/codeql/swift/generated/type/WeakStorageType.qll dda4397a49f537ec44117a86dc09705a07d281e31bf4643738b15219053ed380 dda4397a49f537ec44117a86dc09705a07d281e31bf4643738b15219053ed380 ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo.ql 6e06e222636d5e3451afdce4d5e1b801206a0abf060cc5714350d25e784f8eda 3274ca1b3d85142037d0f12ecf9e15f77c3eeb285621adc9312a6691806d08c8 ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo_getSpec.ql 44ccccad28d8648aa3349d9290bd1478bb021797c26bc2f8c1e3de14a42be3bd aefab61b6fa1c06c5c79d337cffb61335dca74ef9906deba12f7eaea42f9ac14 -ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/Diagnostics/Diagnostics.ql 6a4a9480cc929381e0337b181e5ac519a7abc6d597ebe24fb6701acf79ced86f 199c5bf8bd38e161d989e0e4db1ea1d3ddcb4d7cf571afd9112ce3ed8d9b8d2a ql/test/extractor-tests/generated/File/File.ql ab0968ae31b749da2b66462bd04e4dfb30604dba405a84594b575abfc4fa4c35 bcc0ff648b28c5ecd567e196e700272883756bbcc65296bbb880a979e3162628 -ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql 5c017af7e6b16ee68990eec12affe81eb114338bac4d445f4b231fe0f110eccc db86c828a892b0acd150a780914e7e48c280cad473d3680a453bdee03aee1e9d ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql 1d42eb1a5b832cfaf1949b61a01a6a11448a6d4369a44f2511bb31d1d7fc10a8 b326a6743121353f8a66410d3d9151ca969939abcbbe5c411872ca290da45123 ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql 17f9903978c9a8fc607d970532270090cea030ff57c2f6699c37672707ce5c70 cdd7ce47691a84aa5402a8946d4027f7b9dbce930057dfd62c14b470a5710cb0 @@ -700,19 +700,19 @@ ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getProper ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperBackingVarBinding.ql addbf4e32d383fc35b7505a33c5a675feeedd708c4b94ce8fc89c5bc88c36f1f 549c8ec9cf2c1dc6881e848af8be9900d54604a747ded1f04bd5cadf93e5ede3 ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperProjectionVar.ql 502a76b34c78d3cf8f38969671840dc9e28d478ba7afe671963145ba4dc9460d 6125a91820b6b8d139392c32478383e52e40e572e0f92a32f0e513409d2c4e11 ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperProjectionVarBinding.ql 40274aac8b67cb6a285bf91ccdc725ae1556b13ebcc6854a43e759b029733687 44e569aac32148bcce4cd5e8ebb33d7418580b7f5f03dfbd18635db9965b28d9 -ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl.ql e1906b751a4b72081a61b175e016f5182fdd0e27518f16017d17e14c65dd4268 8a1dd50e951ed2c25f18823ff8b9ab36dc2dc49703801dd48da443bc384bd9b4 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl_getBaseType.ql 4ace6176a57dd4c759356ddbefc28b25481c80bdeddfeb396d91b07db55af22a d0d1337ccbba45a648fe68fefc51006e14506d4fb7211fb2bde45f7761c4dbf1 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl_getGenericTypeParam.ql 3a0927f87a21d69bfc309f5f7faedb3d0cc2956c071b16c38b2b4acd36f24ea9 aafed56a1744579f05b3817adef6a5fd011d1b5cb7da2db230a43b6f55a04649 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl_getMember.ql 621870b7dbeaeefa93cbbfc102e97810b15d39b49db685019c9e3cbf2423ffef e110630f0ba8f588e7f8ebc56a1a31c2ca2f22f2cc763baa76854beb3b3a4ece -ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/ExtensionDecl/ExtensionDecl.ql 71523b034d2abc6225f433f140841a35a466e82c04cbf07bdb3a9e384024fedb 919c66eeff004324b48249fd746c38891f6f8723f1281ad60126cf4b3c1febe0 ql/test/extractor-tests/generated/decl/ExtensionDecl/ExtensionDecl_getGenericTypeParam.ql e8c9815756cd3d82abfb421b1e38d6381e48938a21f798fd9abd93686acc070b 2574ead6e511f41ba416e831e176ecdaac27dde410157a4ee472a680f922dd20 ql/test/extractor-tests/generated/decl/ExtensionDecl/ExtensionDecl_getMember.ql 8d1c6a2b7cb381a81d11775f0d1cfb13ee04dd27dc742e00a72d676f21481dde 430e5b9ed7eccd90383e362ffa5e512704883304c711b13c9110a57ae282bb40 ql/test/extractor-tests/generated/decl/ExtensionDecl/ExtensionDecl_getProtocol.ql 11fc53f70f6e7f29546337a9f06157baaecd9c7d1d392910e94d18b71a0a9ae2 3591d4ff4108bd3399cecdf444161d770c01af20c14f23afac167beead564998 -ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/IfConfigDecl/IfConfigDecl.ql 5322f06ce9efe44baa798f31039c2955b31a8c1272580a0db7182ff1a3082509 3b6f34bc90b337b08eb159142bd5c8cbededd5e97d160e1f7342a7eb6e72e0a1 ql/test/extractor-tests/generated/decl/IfConfigDecl/IfConfigDecl_getActiveElement.ql 914165306a2eb5c8039750e1e03bda156a684946abc8709d786b4144d9c9eb3b 5e87dfd99858ae257506415369bff937a731b6309dac2242b03ea79ead045fc1 ql/test/extractor-tests/generated/decl/IfConfigDecl/IfConfigDecl_getMember.ql 2a2f4e89cb045c0f67c18d6c25e7f8cdcee5ce416304783c25ba2efb2afb45d4 4930c38baf0295399478733e24102a99307fe398986060d29e437bd65720f62d @@ -720,7 +720,7 @@ ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl.ql 65c03a28d5f5638b ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getDeclaration.ql a76c6360ed7b423229ec64dc4d03f586204fbf5107408b7d07c06ef43b30526e bc8569ecf097f0e6176da4f42379158137f70dcfb9b6d60f4c16f643b68f9d91 ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getImportedModule.ql 0339867ca4f414cceba85df20d12eca64a3eea9847bb02829dc28fa95701e987 8c292768f56cecbdfeb92985212e6b39ecada819891921c3ba1532d88d84c43e ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getMember.ql 6d48d3a93bc96dba3bda71ec9d9d6282615c2228a58da6167c169fafaedb3e17 8560b23d0f52b845c81727ce09c0b2f9647965c83d7de165e8cd3d91be5bdd42 -ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.ql f9216e83077ebc0cb5a5bf2d7368af86167a1bfd378f9cd5592fd484a1bbc5dd 1c2de61cb064474340db10de4399c49f15eb0a5669e6dc9587d8b4f656b0134f ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getBaseType.ql 54a4bd2cfa666271ae9092285bb7217b082c88483d614066cfb599fc8ab84305 8b24ab8e93efe3922cb192eb5de5f517763058782e83e8732153421adddd68e1 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql cfca012f0951c86560d892ea5eae182d5eda661c9484a0df71ef9c905123e8f6 dfebda4fcad0e2f2a2c944782a7355b3caeac569e5a45621c582bc1bb243b2cc @@ -743,152 +743,152 @@ ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getPropertyWrapperLoc ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getPropertyWrapperLocalWrappedVarBinding.ql 14f50b706a2dba7123888868d93fa72a4871e6e04949cc87a7df52e27b7197d1 680242c73f78a64a1687cf59b0a80f715c98b994b32ec90044bcedd2c258f786 ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getPropertyWrapperProjectionVar.ql 406436f415d5a6895be712471e7ab2d8b945539ac01b845ce191c4186e1cd275 4fdd0bc67207fd5cbe30743df46fdc61eeb5e58d877ef4aef5c7d7f0f684ef05 ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getPropertyWrapperProjectionVarBinding.ql c79a13e49d3375edac8e51b27a58318afee959a8df639f7b0d7d77de1e2d60bc 8c3b9dae1079e674854d15f4bd43f1f507b7fac6900f0831d92f2140aae268b4 -ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/PoundDiagnosticDecl/PoundDiagnosticDecl.ql 17ac00f962db0e003c5845660b0dbad4ba59ce6e1def6384084ec937158544a5 df27465bc073fc4c031f75fa6b53263df2b902a8168f5d5c08851cc24bf0a647 ql/test/extractor-tests/generated/decl/PoundDiagnosticDecl/PoundDiagnosticDecl_getMember.ql d670ff4ea33ea15aa5f0299fd5bb6cc637e8a16faebe19433d250627732f4903 9a2482a469797248aaeed33caa226c92c97392cad3aa9608554d8ad16cc5cb38 -ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/AppliedPropertyWrapperExpr/AppliedPropertyWrapperExpr.ql 88d7539565c64d29ffd99e8201a0b47954d13c6ca7df6141fab6311fc37588f0 2ebaaaa97b492762273516355004a6cbc88d75250d856ed5e21660294e150ca0 ql/test/extractor-tests/generated/expr/AppliedPropertyWrapperExpr/AppliedPropertyWrapperExpr_getType.ql 1caa0b9c70afc6f63fb1cb05b30499a615a997849d5128006f9c7147b7f1d4a4 64474604bf6d9028bdcbbb8dd2a607c65cb74038e2d6e88e86908f82590ba7a7 -ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.ql 0214077b52ed4c152c70bbd0347c7340d42e584954fba5242f1380e357ec79a0 f8ce48428247f8616c15d39198bf8b3857f1acca12a800bcc912c34720f5f039 ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql a3a01f99aa8df3aafed50cc7828829e567e01fed7874854e7a620904f1641fc9 962669b36b9adbc3d75bae79a9a754692c20d6e14ee2b47aca8f3f93b27895da ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql c3504dda8c41ebc386a9011deb06b0f5312538306b5ca10f7c4ff2e0f2c277dd aa6785ac86fe4954ef679fdfa6cd91f964d9281ab0162240b6e4b9eb67b0eda3 -ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/DotSyntaxCallExpr/DotSyntaxCallExpr.ql b161e81b9eee4c3ab66776542559457c02f30da68e59efb98d6388425e66d2e3 d7571dbca05dd36185c0eb2ad4ad9e821433362c10045875fb433fae5264346a ql/test/extractor-tests/generated/expr/DotSyntaxCallExpr/DotSyntaxCallExpr_getArgument.ql ab0023396a31a9fad384ac6ab2819fa3b45726d651fee6ee5d84ea4fbdb55992 410afe1ae14ca17bc245c9fa88f84ba1d02e20a7803910746316ddcacc062ace ql/test/extractor-tests/generated/expr/DotSyntaxCallExpr/DotSyntaxCallExpr_getType.ql ea3d25737d4c02d6ecd405d23471a587945362dee1160f6346484fffa166835d 3edcaae4cd47839dc716640ac9c098a9c65f365a69fb5442d15eb1955c06dcaa ql/test/extractor-tests/generated/expr/DynamicLookupExpr/DynamicLookupExpr.ql 3c08d6e00606b76499ba1a04547cba9918f3be5b3baa4b3fc287bd288c467c8d 6685c8133d7c34346a85653589b3ae9cf2dbedaaff5e87f4dd9e94719a31b715 ql/test/extractor-tests/generated/expr/DynamicLookupExpr/DynamicLookupExpr_getMember.ql ab1669430da9e60e3b5187bd4f45e7a9b501348cd0c66e4d8570c6facc3a82a3 a2e5e9781c9af9c52fe9d5735f146dc4a2e077096f2baee8db75f2a2f82b0037 ql/test/extractor-tests/generated/expr/DynamicLookupExpr/DynamicLookupExpr_getType.ql 216b9caa3388b85959b19db012c6a7af40981ef92e4749b9cc644caee830041c 32691b624baed5c89fbef438214ecb893f9c1d1a575194133b56d79877e3feec -ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/EnumIsCaseExpr/EnumIsCaseExpr.ql 9a4505f330e014769509be594299bcaa046d0a2c9a8ce4ac3a1d6d6b050af317 92c8392ded3fb26af7434b8aae34b1649b4c808acafc3adbd8ecb60ada5f6e72 ql/test/extractor-tests/generated/expr/EnumIsCaseExpr/EnumIsCaseExpr_getType.ql edc2e175c971465f5667c4586bc4c77e5c245d267f80009a049b8f657238a5f4 5df26b5bdf975ba910a7c3446705c3ac82a67d05565d860fe58464ee82bafdde -ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/IdentityExpr/IdentityExpr.ql f87db45ad56628ce62200e1034d1cfd2ff1c799be5a24681fe939bf80108937a e8484eaab79f3be6b53ecb258eb9a3cd8cdcba8534c0ee7d275b8b67b3d2f538 ql/test/extractor-tests/generated/expr/IdentityExpr/IdentityExpr_getType.ql 7a8520abbf50642f886a3cdea37530b0577d509f31d76224467ad5d435bb0e39 a6fd63a7964cf778cc4b23ce5112138d7d5a5db96956e9514741ef9789bd1f19 -ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.ql 7ffb80368c4d80adccaa0267cc76b42b76304d5d485286f82e22ae51776812f3 51b38032cb3d392be56fa8bdf53379a174cf3de39d4bf6b730c611ae3ab7cec8 ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.ql 184ff1dec5d65024c8a0c2b316706ac58c68c62c715c266211e947168750c89a 486fc8d65c0db86bdada2d540f665278caab43454a69ccc8c2e702729397fef0 -ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MethodLookupExpr/MethodLookupExpr.ql c0c60154b070a8a7ad333544a30f216adf063ae26cac466d60d46b26154eccde 360c9a3ddd9d02a82d0c9de81b8742137d76dba74942f09c9172459565cae19d ql/test/extractor-tests/generated/expr/MethodLookupExpr/MethodLookupExpr_getMember.ql 859ce0b1f54980e6383ff87d7970eb8a7886d9e1fbe12a8a0a35d216850c6775 24faafdb4a88b0019073c06a1cda8e037154b232a364aa47ae151e95df8a868a ql/test/extractor-tests/generated/expr/MethodLookupExpr/MethodLookupExpr_getType.ql 3e749535dbf7ae2cd671b3e35b43ca4f6a5bc68c92f89a09a0a9193cd3200b9a 176102d8d9d5a7bf14ac654d98556048996f2311be0bfe67d16229fd22362ba7 -ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ObjectLiteralExpr/ObjectLiteralExpr.ql 6c6b146537773b4b4bdb0e530bd581f4d9ffee93e784a8fdfcabe35309bdd09e 47b2a275af169a031faee39e73c67a70ec47969b731f1cc80a8f76e68d934402 ql/test/extractor-tests/generated/expr/ObjectLiteralExpr/ObjectLiteralExpr_getArgument.ql ab308c1fa027136070a6ee9ebe5149c69b34bb9ae910f201f37cecd8b6341ff8 deef69f4a1a94386a32ec964e696972a2c6a91c34d7e99c7e4a3811980f5ecc4 ql/test/extractor-tests/generated/expr/ObjectLiteralExpr/ObjectLiteralExpr_getType.ql 07d59d9962f3705f8f32302c0d730c179ca980172dd000b724a72e768fbf39db cd146e19249590316bb83efec19dd41234723513025cf9df45313f78f2b364dd -ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr.ql 7687a79d05efbbae7ce68780cb946cb500ed79c5e03aa0f3c132d0b98b6efe80 f23082710afb2bc247acab84b669540664461f0ec04a946125f17586640dfba8 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr_getArgument.ql 3b0e6f81599e5565bb78aff753932776c933fefdc8dc49e57db9f5b4164017f6 43031a3d0baa58f69b89a8a5d69f1a40ffeeaddc8a630d241e107de63ea54532 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr_getType.ql fa909883140fe89084c289c18ebc681402c38d0f37159d01f043f62de80521fc 4cd748e201e9374e589eaa0e3cc10310a1378bba15272a327d5cf54dbd526e8f -ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr.ql 9ac73f157d11e4ee1c47dceaadd2f686893da6557e4e600c62edad90db2eb92d bf353009ee1b6127350d976f2e869b615d54b998e59664bdb25ea8d6ab5b132d ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getType.ql 0972415a8ac29f460d480990f85c3976ad947e26510da447bbf74ee61d9b3f4e 463b8ce871911b99c495ea84669b4e6f8eafc645df483f6a99413e930bc0275e ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getWrappedValue.ql 208153f062b04bec13a860b64ea51c1d531597140d81a6d4598294dc9f8649a2 dfaea19e1075c02dfc0366fac8fd2edfae8dde06308730eb462c54be5b571129 -ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/stmt/FailStmt/FailStmt.ql 75bf8a697d3a610caf25cb0d25748f2d1620c20fdd84c278c3e2f2502bc3f418 6e2377b8d2a63deaadbf8661dc7da70e8523637020e7d5fd601ca6893f10a573 -ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/stmt/PoundAssertStmt/PoundAssertStmt.ql dc72e3a7ff4c5dc39530322c343931cdfe63565eb76b29deef64bb311bfe302a 18eb3dab5ae8cfada5d42f1e70be9cb464a61ab5ce91897ce5a44a34387915e7 -ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/BuiltinIntegerType/BuiltinIntegerType.ql f85efff665246a0fb345def44cb60ae2415f82c6ef82b9689a61e08e7f1754ae 4c1c50193bfad688a708b4bc0dd08979e561ff764e0786ec37fbb6a654a404d6 ql/test/extractor-tests/generated/type/BuiltinIntegerType/BuiltinIntegerType_getWidth.ql 61e99a3987c5a4b10d5d105184c60dacc1c08d8106cf41b81d491a7f0ac36ef2 b02395a219768e0f41cbf77e4111da3a271e777bfe448eea1ea5d6f0910ff1e8 ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.ql 48f3b997bdb2c37dc22fd3dc2d18bc853888503d0d8d8cb075c6cd18657553e2 278d18e1fae3d8693a4d363b67c6ff111c111464f104d72ccad37793bc425200 -ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/DynamicSelfType/DynamicSelfType.ql d2c942b55f3a9f5af2cde39999b736ce2d50ae4514f36cc1e3f750905b03c49b b7ccdcf083da1598eaf4b5ad22e393253b8d58577580048290651a20f6e6df2f -ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/ExistentialType/ExistentialType.ql f7894f01a440b5db281dfaa9c083be0898d15b67e1b0047be3f9c959b97bdeb0 725a54f6ed26d53603a3e25cbf78c90b1f16837c1c0c39b56e7d3bdd51a78265 -ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/InOutType/InOutType.ql 35b7c048fbd053f6821ab1d996fabf55dada014873f25c5ed7141b59eb5e0fb6 06ca9b5be9a999cbd7e1ab2f26918a5923d7d351dd9ec74137550f1947013b7d -ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/ModuleType/ModuleType.ql 8f798fea381d1b502f262b5ee790758b38008cadcdee848d0ddba1bd9f8ff4f9 4c3d623607be1a5f6503500f3331ee3b3e5200e9e78cca8a4ef3d24c83d0e7ba ql/test/extractor-tests/generated/type/OpaqueTypeArchetypeType/OpaqueTypeArchetypeType.ql e34e98f70a987fe9a5017c897a507f9de4fffff837e3e2cf6c13287bb6165381 e60a5754173210f3af543bea15eadb2a3349e2f71653249cc421b33266adf344 ql/test/extractor-tests/generated/type/OpaqueTypeArchetypeType/OpaqueTypeArchetypeType_getProtocol.ql fb9baf55660e0eedf1a387267d170ae066a8d1531156eab5447feca92f05b751 139529998fc2060a46a70cb645a9aa36240ab225bd9fbdb3decc3eaec3aa2261 @@ -896,23 +896,23 @@ ql/test/extractor-tests/generated/type/OpaqueTypeArchetypeType/OpaqueTypeArchety ql/test/extractor-tests/generated/type/OpenedArchetypeType/OpenedArchetypeType.ql d902b873db34a3b7f0bc4da82ecf59b01d283d4ca61be3b090cb47358c8dd6c2 656a938735cfa5bf5ca65a7c0e347fca993e966d568404ac204f60de18faa03f ql/test/extractor-tests/generated/type/OpenedArchetypeType/OpenedArchetypeType_getProtocol.ql c208618d6bd7d4759581f06fad2b452077a0d865b4fb4288eff591fc7b16cd67 3bd6b8e1d1bc14bd27144a8356e07520d36ea21b6ea4adb61e84a2013e8701fc ql/test/extractor-tests/generated/type/OpenedArchetypeType/OpenedArchetypeType_getSuperclass.ql bb7fc71b2d84e8c5492bb4c61492dabbce898bfb680979aadd88c4de44ea5af7 acae343087222e8eb7e4dfa0e256097d9592a9668afcb5706bcba5548afc0770 -ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/ParameterizedProtocolType/ParameterizedProtocolType.ql dad743465b62dca457d64ff04bde24027050edb6d80054738f59e6026fbb00d7 119d085d65930b0b286ccdb8dc3aecb7eb46133e9f4ea18a6733751713b8ae5c ql/test/extractor-tests/generated/type/ParameterizedProtocolType/ParameterizedProtocolType_getArg.ql 8d10c3c858dedba47f227ebc92745916a248cd040ad944b80bf0d7a19af229d3 a29e2e0df269034c4f1fbd8f6de6d5898e895ad8b90628d5c869a45b596b53fc -ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/PrimaryArchetypeType/PrimaryArchetypeType.ql 1d733e0447587d52a3b84ca19480e410c487c02541cd070ac80fcd2dbef5b57d 6ffd1e7ce8ec9b9fea0680805700262e472711b4d9a2b4336e57445e8f1a6d48 ql/test/extractor-tests/generated/type/PrimaryArchetypeType/PrimaryArchetypeType_getProtocol.ql 8af9b686cb9c3d988aea21cdaca42a0b625985111caa71d3eebaba4aea883e9c beecb31ab8fccb05c853926bccec33e298bed519385a25d6158646c94a019af9 ql/test/extractor-tests/generated/type/PrimaryArchetypeType/PrimaryArchetypeType_getSuperclass.ql 3b752a38eac8204ae6d902d03da8caeaad4072f30206420c97056e4bf3639eb4 fc5959969d5b229fa5d90dde7d997aa0d1b91bdb9d77cc6811377044eed4a6cb ql/test/extractor-tests/generated/type/ProtocolCompositionType/ProtocolCompositionType.ql 007c64d8ea8f69addc61e8759ce9cf2e32f5e8f73de6e35541a16ea19d4695ab 156ef6560aa5d866e6ed70237cf0335b2df0c75f87d23cc4d1024ee80fe0a543 ql/test/extractor-tests/generated/type/ProtocolCompositionType/ProtocolCompositionType_getMember.ql 8c1e8e5932cd775f0d0812a64954be5fd5b3eedd8a26eedb0bd6009cbc156e24 5c43ef8000bb67ed0e070bbd9d5fc167dcb7b6334ae34747d27eb8060af1a7e5 -ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/TupleType/TupleType.ql 3ef454f940299726c035f0472ae4362d4b34fbe18a9af2a7d3581b1c734fad66 b5756e68f4eef3a02e7f1d2a7e16e41dc90d53fc631e0bd0c91ad015d63b77ca ql/test/extractor-tests/generated/type/TupleType/TupleType_getName.ql ab5c578f6e257960aa43b84dd5d4a66e17f2312b5f9955af0953aaecbe9e093a 1ff62da991b35e946446ecee706ac0e07a80059f35654c022ffe06bf7ae32cfe ql/test/extractor-tests/generated/type/TupleType/TupleType_getType.ql 3f861729c996b37e170adab56200e0671415663ff319bbf87c7c46ec8532d575 96a9735d69f250f3d67716d6a1552909d2aaa9b7758275b1b9002dca19000d22 -ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd -ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd +ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/type/UnmanagedStorageType/UnmanagedStorageType.ql 3047ed64cbdb03d719d096fd3b2c4c54c92a2b65e46943424e84eeca705ab2d3 a8ee8ca4bf257c7472fa8cd7e661d352e8856b9e5855ebb3681f4d313209141c ql/test/extractor-tests/generated/type/UnownedStorageType/UnownedStorageType.ql 11e205283b368b9c9dbc79636c6007df501c952e6f715a9f07e65ec452192b38 ceb1e9c1279df07c77f9b23356b71c3e7672ec4cd5253898e09b27b2b24e4b00 ql/test/extractor-tests/generated/type/VariadicSequenceType/VariadicSequenceType.ql 8c44ebc1fd1fa0b5caad5eb5b280f227f002dcfaddba45131b2959dad0b458f6 5f497990e2bd57a3ea8e2eb7da598af0c4ba7c7b4cc89b549e45de0ae3712e60 diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index 1a1095dc3df..eda7d314ac3 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -81,6 +81,7 @@ private module Frameworks { private import codeql.swift.frameworks.StandardLibrary.Collection private import codeql.swift.frameworks.StandardLibrary.CustomUrlSchemes private import codeql.swift.frameworks.StandardLibrary.Data + private import codeql.swift.frameworks.StandardLibrary.FileManager private import codeql.swift.frameworks.StandardLibrary.FilePath private import codeql.swift.frameworks.StandardLibrary.InputStream private import codeql.swift.frameworks.StandardLibrary.NsData diff --git a/swift/ql/lib/codeql/swift/dataflow/FlowSources.qll b/swift/ql/lib/codeql/swift/dataflow/FlowSources.qll index 93aeb44618a..c32759c8aa8 100644 --- a/swift/ql/lib/codeql/swift/dataflow/FlowSources.qll +++ b/swift/ql/lib/codeql/swift/dataflow/FlowSources.qll @@ -28,7 +28,7 @@ abstract class RemoteFlowSource extends FlowSource { } /** * A data flow source of local user input that is defined through 'models as data'. */ -private class ExternalLocalFlowSource extends RemoteFlowSource { +private class ExternalLocalFlowSource extends LocalFlowSource { ExternalLocalFlowSource() { sourceNode(this, "local") } override string getSourceType() { result = "external" } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 9a8b64af131..059fd4ae26f 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -153,6 +153,9 @@ private module Cached { or nodeFrom.asExpr() = nodeTo.asExpr().(OptionalEvaluationExpr).getSubExpr() or + // flow through unary `+` (which does nothing) + nodeFrom.asExpr() = nodeTo.asExpr().(UnaryPlusExpr).getOperand() + or // flow through nil-coalescing operator `??` exists(BinaryExpr nco | nco.getOperator().(FreeFunctionDecl).getName() = "??(_:_:)" and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll index 6fdcca98c36..911f44627a6 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll @@ -43,12 +43,8 @@ private module Cached { nodeFrom.asExpr() = interpolated.getAppendingExpr() ) or - // allow flow through string concatenation. - exists(AddExpr ae | - ae.getAnOperand() = nodeFrom.asExpr() and - ae = nodeTo.asExpr() and - ae.getType().getName() = "String" - ) + // allow flow through arithmetic (this case includes string concatenation) + nodeTo.asExpr().(ArithmeticOperation).getAnOperand() = nodeFrom.asExpr() or // flow through a subscript access exists(SubscriptExpr se | diff --git a/swift/ql/lib/codeql/swift/elements/expr/ArithmeticOperation.qll b/swift/ql/lib/codeql/swift/elements/expr/ArithmeticOperation.qll index faa2941a637..c2c7dc346a3 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/ArithmeticOperation.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/ArithmeticOperation.qll @@ -97,7 +97,12 @@ class RemExpr extends BinaryExpr { * -a * ``` */ -class UnaryArithmeticOperation extends PrefixUnaryExpr instanceof UnaryMinusExpr { } +class UnaryArithmeticOperation extends PrefixUnaryExpr { + UnaryArithmeticOperation() { + this instanceof UnaryMinusExpr or + this instanceof UnaryPlusExpr + } +} /** * A unary minus expression. @@ -108,3 +113,13 @@ class UnaryArithmeticOperation extends PrefixUnaryExpr instanceof UnaryMinusExpr class UnaryMinusExpr extends PrefixUnaryExpr { UnaryMinusExpr() { this.getStaticTarget().getName() = "-(_:)" } } + +/** + * A unary plus expression. + * ``` + * +a + * ``` + */ +class UnaryPlusExpr extends PrefixUnaryExpr { + UnaryPlusExpr() { this.getStaticTarget().getName() = "+(_:)" } +} diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/FileManager.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/FileManager.qll new file mode 100644 index 00000000000..931871c6538 --- /dev/null +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/FileManager.qll @@ -0,0 +1,25 @@ +/** + * Provides models for the `FileManager` Swift class. + */ + +import swift +private import codeql.swift.dataflow.ExternalFlow + +/** + * A model for `FileManager` members that are flow sources. + */ +private class FileManagerSource extends SourceModelCsv { + override predicate row(string row) { + row = + [ + ";FileManager;true;contentsOfDirectory(at:includingPropertiesForKeys:options:);;;ReturnValue;local", + ";FileManager;true;contentsOfDirectory(atPath:);;;ReturnValue;local", + ";FileManager;true;directoryContents(atPath:);;;ReturnValue;local", + ";FileManager;true;subpathsOfDirectory(atPath:);;;ReturnValue;local", + ";FileManager;true;subpaths(atPath:);;;ReturnValue;local", + ";FileManager;true;destinationOfSymbolicLink(atPath:);;;ReturnValue;local", + ";FileManager;true;pathContentOfSymbolicLink(atPath:);;;ReturnValue;local", + ";FileManager;true;contents(atPath:);;;ReturnValue;local" + ] + } +} diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll index 3640eca6a97..cf9b73d05ab 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll @@ -58,8 +58,8 @@ private class StringSummaries extends SummaryModelCsv { ";StringProtocol;true;propertyListFromStringsFileFormat();;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;replacingCharacters(in:with:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;replacingCharacters(in:with:);;;Argument[1];ReturnValue;taint", - ";StringProtocol;true;replacingOccurrences(of:with:options:range);;;Argument[-1];ReturnValue;taint", - ";StringProtocol;true;replacingOccurrences(of:with:options:range);;;Argument[1];ReturnValue;taint", + ";StringProtocol;true;replacingOccurrences(of:with:options:range:);;;Argument[-1];ReturnValue;taint", + ";StringProtocol;true;replacingOccurrences(of:with:options:range:);;;Argument[1];ReturnValue;taint", ";StringProtocol;true;replacingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;substring(from:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;substring(with:);;;Argument[-1];ReturnValue;taint", @@ -79,7 +79,7 @@ private class StringSummaries extends SummaryModelCsv { ";String;true;init(format:locale:arguments:);;;Argument[0];ReturnValue;taint", ";String;true;init(_:radix:uppercase:);;;Argument[0];ReturnValue;taint", ";String;true;init(bytes:encoding:);;;Argument[0];ReturnValue;taint", - ";String;true;init(bytesNoCopy:length:encoding:freeWhenDone);;;Argument[0];ReturnValue;taint", + ";String;true;init(bytesNoCopy:length:encoding:freeWhenDone:);;;Argument[0];ReturnValue;taint", ";String;true;init(describing:);;;Argument[0];ReturnValue;taint", ";String;true;init(contentsOf:);;;Argument[0];ReturnValue;taint", ";String;true;init(contentsOf:encoding:);;;Argument[0];ReturnValue;taint", @@ -101,7 +101,7 @@ private class StringSummaries extends SummaryModelCsv { ";String;true;write(_:);;;Argument[0];Argument[-1];taint", ";String;true;write(to:);;;Argument[-1];Argument[0];taint", ";String;true;insert(contentsOf:at:);;;Argument[0];Argument[-1];taint", - ";String;true;replaceSubrange(_:with::);;;Argument[1];Argument[-1];taint", + ";String;true;replaceSubrange(_:with:);;;Argument[1];Argument[-1];taint", ";String;true;max();;;Argument[-1];ReturnValue;taint", ";String;true;max(by:);;;Argument[-1];ReturnValue;taint", ";String;true;min();;;Argument[-1];ReturnValue;taint", diff --git a/swift/ql/lib/codeql/swift/printast/PrintAst.qll b/swift/ql/lib/codeql/swift/printast/PrintAst.qll index 267919f951e..4527058adc8 100644 --- a/swift/ql/lib/codeql/swift/printast/PrintAst.qll +++ b/swift/ql/lib/codeql/swift/printast/PrintAst.qll @@ -1,5 +1,5 @@ /** - * Provides queries to pretty-print a Go AST as a graph. + * Provides queries to pretty-print a Swift AST as a graph. */ import PrintAstNode diff --git a/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll b/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll index fd1e217c460..fead27ecf71 100644 --- a/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll +++ b/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll @@ -1,5 +1,5 @@ /** - * Provides classes used to pretty-print a Go AST as a graph. + * Provides classes used to pretty-print a Swift AST as a graph. * This is factored out of `PrintAst.qll` for testing purposes. */ diff --git a/swift/ql/lib/codeql/swift/security/PathInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/PathInjectionExtensions.qll index 916c2fa9c94..4a78cfbf867 100644 --- a/swift/ql/lib/codeql/swift/security/PathInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/PathInjectionExtensions.qll @@ -108,6 +108,11 @@ private class PathInjectionSinks extends SinkModelCsv { ";NIOFileHandle;true;init(descriptor:);;;Argument[0];path-injection", ";NIOFileHandle;true;init(path:mode:flags:);;;Argument[0];path-injection", ";NIOFileHandle;true;init(path:);;;Argument[0];path-injection", + ";String;true;init(contentsOfFile:);;;Argument[0];path-injection", + ";String;true;init(contentsOfFile:encoding:);;;Argument[0];path-injection", + ";String;true;init(contentsOfFile:usedEncoding:);;;Argument[0];path-injection", + ";NSString;true;init(contentsOfFile:encoding:);;;Argument[0];path-injection", + ";NSString;true;init(contentsOfFile:usedEncoding:);;;Argument[0];path-injection", ";NSString;true;write(to:atomically:encoding:);;;Argument[0];path-injection", ";NSString;true;write(toFile:atomically:encoding:);;;Argument[0];path-injection", ";NSKeyedUnarchiver;true;unarchiveObject(withFile:);;;Argument[0];path-injection", diff --git a/swift/ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt new file mode 100644 index 00000000000..25daf3d23a2 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py + +After a source file is added in this directory and codegen/codegen.py is run again, test queries +will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt new file mode 100644 index 00000000000..25daf3d23a2 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py + +After a source file is added in this directory and codegen/codegen.py is run again, test queries +will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/EnumElementDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/GenericTypeParamDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/PatternBindingDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/PostfixOperatorDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/PrecedenceGroupDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/PrefixOperatorDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/ProtocolDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/StructDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/SubscriptDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/TopLevelCodeDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/decl/TypeAliasDecl/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/Argument/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ArrayExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/AssignExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/AutoClosureExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/BinaryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DiscardAssignmentExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DotSyntaxBaseIgnoredExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/ForcedCheckedCastExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/NilLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OneWayExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/TapExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/BoolPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/EnumElementPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/ExprPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/IsPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/NamedPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/OptionalSomePattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/ParenPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/TuplePattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/pattern/TypedPattern/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/BraceStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/BreakStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/CaseLabelItem/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/CaseStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/ConditionElement/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/ContinueStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/DeferStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/DoCatchStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/DoStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/FallthroughStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/ForEachStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/GuardStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/IfStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/RepeatWhileStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/ReturnStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/StmtCondition/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/SwitchStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/ThrowStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/WhileStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/stmt/YieldStmt/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/ArraySliceType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/BoundGenericClassType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/BoundGenericEnumType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/BoundGenericStructType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/ClassType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/DependentMemberType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/DictionaryType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/EnumType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/ExistentialMetatypeType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/OptionalType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/ParenType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/ProtocolType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/StructType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/TypeAliasType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/TypeRepr/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt index 0d319d9a669..25daf3d23a2 100644 --- a/swift/ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt +++ b/swift/ql/test/extractor-tests/generated/type/UnboundGenericType/MISSING_SOURCE.txt @@ -1,4 +1,4 @@ // generated by codegen/codegen.py -After a swift source file is added in this directory and codegen/codegen.py is run again, test queries +After a source file is added in this directory and codegen/codegen.py is run again, test queries will appear and this file will be deleted diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index a4dc26557d5..88674e40dbe 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -154,6 +154,7 @@ edges | test.swift:472:20:472:20 | cx [x] : | test.swift:462:9:462:9 | self [x] : | | test.swift:472:20:472:20 | cx [x] : | test.swift:472:20:472:23 | .x : | | test.swift:472:20:472:23 | .x : | test.swift:473:15:473:15 | z1 | +| test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) | nodes | file://:0:0:0:0 | .a [x] : | semmle.label | .a [x] : | | file://:0:0:0:0 | .x : | semmle.label | .x : | @@ -324,6 +325,9 @@ nodes | test.swift:472:20:472:20 | cx [x] : | semmle.label | cx [x] : | | test.swift:472:20:472:23 | .x : | semmle.label | .x : | | test.swift:473:15:473:15 | z1 | semmle.label | z1 | +| test.swift:479:13:479:21 | call to +(_:) | semmle.label | call to +(_:) | +| test.swift:479:14:479:21 | call to source() : | semmle.label | call to source() : | +| test.swift:480:14:480:21 | call to source() | semmle.label | call to source() | subpaths | test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:31:75:32 | [post] &... : | | test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : | @@ -408,3 +412,5 @@ subpaths | test.swift:361:15:361:18 | .1 | test.swift:351:31:351:38 | call to source() : | test.swift:361:15:361:18 | .1 | result | | test.swift:442:19:442:19 | a | test.swift:259:12:259:19 | call to source() : | test.swift:442:19:442:19 | a | result | | test.swift:473:15:473:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:473:15:473:15 | z1 | result | +| test.swift:479:13:479:21 | call to +(_:) | test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) | result | +| test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | result | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected index 9188fff70ef..b78de16c81f 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected @@ -390,3 +390,4 @@ | test.swift:472:20:472:23 | .x | test.swift:472:11:472:15 | SSA def(z1) | | test.swift:474:11:474:15 | SSA def(z2) | test.swift:475:15:475:15 | z2 | | test.swift:474:20:474:23 | .x | test.swift:474:11:474:15 | SSA def(z2) | +| test.swift:479:14:479:21 | call to source() | test.swift:479:13:479:21 | call to +(_:) | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift index 57a0a6c64a7..2f298576bc0 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift +++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift @@ -474,3 +474,8 @@ func testOptionalPropertyAccess(y: Int?) { guard let z2 = cy.x else { return } sink(arg: z2) } + +func testIdentityArithmetic() { + sink(arg: +source()) // $ flow=479 + sink(arg: (source())) // $ flow=480 +} diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowConfig.qll similarity index 95% rename from swift/ql/test/library-tests/dataflow/flowsources/FlowSources.ql rename to swift/ql/test/library-tests/dataflow/flowsources/FlowConfig.qll index c53471ec190..889dfd3481a 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.ql +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowConfig.qll @@ -34,6 +34,3 @@ class CustomTestSourcesCsv extends SourceModelCsv { ] } } - -from RemoteFlowSource source -select source, concat(source.getSourceType(), ", ") diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected b/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected deleted file mode 100644 index 8b872c18b11..00000000000 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected +++ /dev/null @@ -1,109 +0,0 @@ -| alamofire.swift:91:27:91:27 | .result | external | -| alamofire.swift:99:27:99:27 | .result | external | -| alamofire.swift:344:23:344:32 | .data | external | -| alamofire.swift:351:22:351:31 | .value | external | -| alamofire.swift:358:23:358:32 | .value | external | -| alamofire.swift:365:22:365:31 | .value | external | -| alamofire.swift:372:23:372:32 | .value | external | -| alamofire.swift:379:28:379:37 | .value | external | -| alamofire.swift:389:28:389:55 | call to String.init(contentsOfFile:) | external | -| alamofire.swift:396:22:396:31 | .value | external | -| alamofire.swift:403:22:403:31 | .value | external | -| alamofire.swift:404:28:404:50 | call to String.init(contentsOf:) | external | -| alamofire.swift:411:23:411:32 | .value | external | -| alamofire.swift:418:22:418:31 | .value | external | -| alamofire.swift:425:23:425:32 | .value | external | -| alamofire.swift:431:28:431:37 | .value | external | -| alamofire.swift:448:20:448:49 | call to String.init(contentsOfFile:) | external | -| alamofire.swift:455:23:455:32 | .data | external | -| alamofire.swift:461:23:461:32 | .data | external | -| customurlschemes.swift:53:44:53:54 | url | external | -| customurlschemes.swift:57:52:57:68 | url | external | -| customurlschemes.swift:61:52:61:62 | url | external | -| customurlschemes.swift:66:9:66:28 | ...[...] | Remote URL in UIApplicationDelegate.application.launchOptions | -| customurlschemes.swift:71:9:71:28 | ...[...] | Remote URL in UIApplicationDelegate.application.launchOptions | -| customurlschemes.swift:77:59:77:76 | options | external | -| customurlschemes.swift:78:28:78:38 | continue | external | -| customurlschemes.swift:79:28:79:39 | didUpdate | external | -| customurlschemes.swift:80:28:80:65 | openURLContexts | external | -| customurlschemes.swift:86:59:86:76 | options | external | -| customurlschemes.swift:87:28:87:38 | continue | external | -| customurlschemes.swift:88:28:88:39 | didUpdate | external | -| customurlschemes.swift:89:28:89:65 | openURLContexts | external | -| data.swift:18:20:18:54 | call to Data.init(contentsOf:options:) | external | -| file://:0:0:0:0 | .data | external | -| file://:0:0:0:0 | .result | external | -| file://:0:0:0:0 | .result | external | -| file://:0:0:0:0 | .source1 | external | -| file://:0:0:0:0 | .source1 | external | -| file://:0:0:0:0 | .source4 | external | -| file://:0:0:0:0 | .source9 | external | -| generics.swift:10:9:10:16 | .source1 | external | -| generics.swift:11:9:11:16 | .source2 | external | -| generics.swift:12:9:12:24 | call to source3() | external | -| generics.swift:48:9:48:17 | .source1 | external | -| generics.swift:49:9:49:17 | .source2 | external | -| generics.swift:50:9:50:25 | call to source3() | external | -| generics.swift:51:9:51:18 | .source1 | external | -| generics.swift:52:9:52:18 | .source2 | external | -| generics.swift:53:9:53:26 | call to source3() | external | -| generics.swift:54:9:54:17 | .source1 | external | -| generics.swift:55:9:55:17 | .source2 | external | -| generics.swift:56:9:56:25 | call to source3() | external | -| generics.swift:57:9:57:17 | .source4 | external | -| generics.swift:58:9:58:17 | .source5 | external | -| generics.swift:59:9:59:25 | call to source6() | external | -| generics.swift:60:9:60:17 | .source7 | external | -| generics.swift:61:9:61:25 | call to source8() | external | -| generics.swift:62:9:62:18 | .source1 | external | -| generics.swift:63:9:63:18 | .source2 | external | -| generics.swift:64:9:64:26 | call to source3() | external | -| generics.swift:65:9:65:18 | .source9 | external | -| generics.swift:66:9:66:18 | .source10 | external | -| generics.swift:67:9:67:27 | call to source11() | external | -| generics.swift:68:9:68:18 | .source12 | external | -| generics.swift:69:9:69:27 | call to source13() | external | -| generics.swift:93:9:93:15 | .source0 | external | -| generics.swift:94:9:94:15 | .source1 | external | -| generics.swift:95:9:95:15 | .source2 | external | -| generics.swift:96:9:96:14 | .source0 | external | -| generics.swift:97:9:97:14 | .source1 | external | -| generics.swift:98:9:98:14 | .source2 | external | -| generics.swift:99:9:99:15 | .source0 | external | -| generics.swift:100:9:100:15 | .source1 | external | -| generics.swift:101:9:101:15 | .source2 | external | -| generics.swift:125:9:125:15 | .source0 | external | -| generics.swift:126:9:126:15 | .source1 | external | -| generics.swift:127:9:127:15 | .source2 | external | -| generics.swift:128:9:128:14 | .source0 | external | -| generics.swift:129:9:129:14 | .source1 | external | -| generics.swift:130:9:130:14 | .source2 | external | -| generics.swift:131:9:131:15 | .source0 | external | -| generics.swift:132:9:132:15 | .source1 | external | -| generics.swift:133:9:133:15 | .source2 | external | -| generics.swift:162:9:162:22 | call to source2() | external | -| generics.swift:163:9:163:22 | call to source3() | external | -| nsdata.swift:18:17:18:40 | call to NSData.init(contentsOf:) | external | -| nsdata.swift:19:17:19:53 | call to NSData.init(contentsOf:options:) | external | -| string.swift:56:21:56:44 | call to String.init(contentsOf:) | external | -| string.swift:57:21:57:77 | call to String.init(contentsOf:encoding:) | external | -| string.swift:59:21:59:69 | call to String.init(contentsOf:usedEncoding:) | external | -| string.swift:62:21:62:48 | call to String.init(contentsOfFile:) | external | -| string.swift:63:21:63:81 | call to String.init(contentsOfFile:encoding:) | external | -| string.swift:64:21:64:73 | call to String.init(contentsOfFile:usedEncoding:) | external | -| url.swift:53:15:53:19 | .resourceBytes | external | -| url.swift:60:15:60:19 | .lines | external | -| url.swift:67:16:67:22 | .lines | external | -| webview.swift:13:32:13:49 | decidePolicyFor | Navigation action of a WebView | -| webview.swift:14:32:14:49 | decidePolicyFor | Navigation action of a WebView | -| webview.swift:41:82:41:102 | message | external | -| webview.swift:46:5:46:13 | .globalObject | external | -| webview.swift:47:5:47:39 | call to objectForKeyedSubscript(_:) | external | -| webview.swift:60:9:60:9 | .tainted | Member of a type exposed through JSExport | -| webview.swift:64:10:64:10 | self | Member of a type exposed through JSExport | -| webview.swift:64:18:64:24 | arg1 | Member of a type exposed through JSExport | -| webview.swift:64:29:64:35 | arg2 | Member of a type exposed through JSExport | -| webview.swift:72:32:72:49 | decidePolicyFor | Navigation action of a WebView | -| webview.swift:73:32:73:49 | decidePolicyFor | Navigation action of a WebView | -| webview.swift:79:32:79:49 | decidePolicyFor | Navigation action of a WebView | -| webview.swift:80:32:80:49 | decidePolicyFor | Navigation action of a WebView | diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.expected b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql new file mode 100644 index 00000000000..a15bf2eed89 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSourcesInline.ql @@ -0,0 +1,25 @@ +import swift +import TestUtilities.InlineExpectationsTest +import FlowConfig + +string describe(FlowSource source) { + source instanceof RemoteFlowSource and result = "remote" + or + source instanceof LocalFlowSource and result = "local" +} + +class FlowSourcesTest extends InlineExpectationsTest { + FlowSourcesTest() { this = "FlowSourcesTest" } + + override string getARelevantTag() { result = "source" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(FlowSource source | + location = source.getLocation() and + location.getFile().getBaseName() != "" and + element = source.toString() and + tag = "source" and + value = describe(source) + ) + } +} diff --git a/swift/ql/test/library-tests/dataflow/flowsources/alamofire.swift b/swift/ql/test/library-tests/dataflow/flowsources/alamofire.swift index 5fdfad51534..34f3da01c23 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/alamofire.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/alamofire.swift @@ -88,7 +88,7 @@ struct DataResponse { let result: Result - var value: Success? { result.success } // SOURCE + var value: Success? { result.success } // $ source=remote } struct DownloadResponse { @@ -96,7 +96,7 @@ struct DownloadResponse { let result: Result - var value: Success? { result.success } // SOURCE + var value: Success? { result.success } // $ source=remote } typealias AFDataResponse = DataResponse @@ -341,42 +341,42 @@ func testAlamofire() { AF.request("http://example.com/").response { response in - if let data = response.data { // SOURCE + if let data = response.data { // $ source=remote // ... } } AF.request("http://example.com/").response(responseSerializer: MySerializer()) { response in - if let obj = response.value { // SOURCE + if let obj = response.value { // $ source=remote // ... } } AF.request("http://example.com/").responseData { response in - if let data = response.value { // SOURCE + if let data = response.value { // $ source=remote // ... } } AF.request("http://example.com/").responseString { response in - if let str = response.value { // SOURCE + if let str = response.value { // $ source=remote // ... } } AF.request("http://example.com/").responseJSON { response in - if let json = response.value { // SOURCE + if let json = response.value { // $ source=remote // ... } } AF.request("http://example.com/").responseDecodable(of: MyDecodable.self) { response in - if let decodable = response.value { // SOURCE + if let decodable = response.value { // $ source=remote // ... } } @@ -386,49 +386,49 @@ func testAlamofire() { AF.download("http://example.com/").response { response in if let path = response.fileURL?.path { - let str = try? String(contentsOfFile: path) // SOURCE + let str = try? String(contentsOfFile: path) // $ MISSING: source=remote $ SPURIOUS: source=local // ... } } AF.download("http://example.com/").response(responseSerializer: MySerializer()) { response in - if let obj = response.value { // SOURCE + if let obj = response.value { // $ source=remote // ... } } AF.download("http://example.com/").responseURL { response in - if let url = response.value { // just the URL [FALSE POSITIVE] - let str = try? String(contentsOf: url) // SOURCE + if let url = response.value { // $ SPURIOUS: source=remote (this is just the URL) + let str = try? String(contentsOf: url) // $ source=remote // ... } } AF.download("http://example.com/").responseData { response in - if let data = response.value { // SOURCE + if let data = response.value { // $ source=remote // ... } } AF.download("http://example.com/").responseString { response in - if let str = response.value { // SOURCE + if let str = response.value { // $ source=remote // ... } } AF.download("http://example.com/").responseJSON { response in - if let json = response.value { // SOURCE + if let json = response.value { // $ source=remote } } AF.download("http://example.com/").responseDecodable(of: MyDecodable.self) { response in - if let decodable = response.value { // SOURCE + if let decodable = response.value { // $ source=remote // ... } } @@ -445,20 +445,20 @@ func testAlamofire() { // ... } // ... - let str = try? String(contentsOfFile: myPath) // SOURCE + let str = try? String(contentsOfFile: myPath) // $ MISSING: source=remote SPURIOUS: source=local // chaining // - in practice there are a wide range of calls that can be chained through. AF.request("http://example.com/").response { response in - if let data = response.data { // SOURCE + if let data = response.data { // $ source=remote // ... } } .response { response in - if let data = response.data { // SOURCE + if let data = response.data { // $ source=remote // ... } } @@ -470,7 +470,7 @@ func testAlamofire() { switch stream.event { case let .stream(result): switch result { - case let .success(data): // SOURCE [NOT DETECTED] + case let .success(data): // $ MISSING: source=remote doSomethingWith(data) // ... } @@ -485,7 +485,7 @@ func testAlamofire() { switch stream.event { case let .stream(result): switch result { - case let .success(value): // SOURCE [NOT DETECTED] + case let .success(value): // $ MISSING: source=remote doSomethingWith(value) // ... } @@ -500,7 +500,7 @@ func testAlamofire() { switch stream.event { case let .stream(result): switch result { - case let .success(value): // SOURCE [NOT DETECTED] + case let .success(value): // MISSING: source=remote doSomethingWith(value) // ... } @@ -515,7 +515,7 @@ func testAlamofire() { switch stream.event { case let .stream(result): switch result { - case let .success(value): // SOURCE [NOT DETECTED] + case let .success(value): // MISSING: source=remote doSomethingWith(value) // ... } @@ -530,7 +530,7 @@ func testAlamofire() { AF.streamRequest("http://example.com/").responseStream { stream in if case let .stream(myResult) = stream.event { - if case let .success(myData) = myResult { // SOURCE [NOT DETECTED] + if case let .success(myData) = myResult { // MISSING: source=remote doSomethingWith(myData) } } @@ -539,7 +539,7 @@ func testAlamofire() { AF.streamRequest("http://example.com/").responseStream { stream in if case let .stream(myResult) = stream.event { - doSomethingWith(myResult.success!) // SOURCE [NOT DETECTED] + doSomethingWith(myResult.success!) // MISSING: source=remote } } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift index 0e96677fc2a..4a300dcd217 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift @@ -1,4 +1,5 @@ // --- stubs --- + class UIApplication { struct OpenURLOptionsKey : Hashable { static func == (lhs: OpenURLOptionsKey, rhs: OpenURLOptionsKey) -> Bool { @@ -50,41 +51,41 @@ protocol UISceneDelegate { // --- tests --- class AppDelegate: UIApplicationDelegate { - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { // SOURCE + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { // $ source=remote return true } - func application(_ application: UIApplication, handleOpen url: URL) -> Bool { // SOURCE + func application(_ application: UIApplication, handleOpen url: URL) -> Bool { // $ source=remote return true } - func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { // SOURCE + func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { // $ source=remote return true } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool { - launchOptions?[.url] // SOURCE + launchOptions?[.url] // $ source=remote return true } func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool { - launchOptions?[.url] // SOURCE + launchOptions?[.url] // $ source=remote return true } } class SceneDelegate : UISceneDelegate { - func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // SOURCE - func scene(_: UIScene, continue: NSUserActivity) {} // SOURCE - func scene(_: UIScene, didUpdate: NSUserActivity) {} // SOURCE - func scene(_: UIScene, openURLContexts: Set) {} // SOURCE + func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote + func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote + func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote + func scene(_: UIScene, openURLContexts: Set) {} // $ source=remote } class Extended {} extension Extended : UISceneDelegate { - func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // SOURCE - func scene(_: UIScene, continue: NSUserActivity) {} // SOURCE - func scene(_: UIScene, didUpdate: NSUserActivity) {} // SOURCE - func scene(_: UIScene, openURLContexts: Set) {} // SOURCE + func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote + func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote + func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote + func scene(_: UIScene, openURLContexts: Set) {} // $ source=remote } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/data.swift b/swift/ql/test/library-tests/dataflow/flowsources/data.swift index eef374b62a9..b0d9fd9a871 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/data.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/data.swift @@ -15,5 +15,5 @@ struct Data { func testData() { let url = URL(string: "http://example.com/") - let data = try Data(contentsOf: url!, options: []) // SOURCE + let data = try Data(contentsOf: url!, options: []) // $ source=remote } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/filemanager.swift b/swift/ql/test/library-tests/dataflow/flowsources/filemanager.swift new file mode 100644 index 00000000000..869f4e58190 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/flowsources/filemanager.swift @@ -0,0 +1,51 @@ +// --- stubs --- + +class NSObject { +} + +struct URL { +} + +struct URLResourceKey { +} + +struct Data { +} + +class FileManager : NSObject { + struct DirectoryEnumerationOptions : OptionSet{ + let rawValue: Int + } + + func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options mask: FileManager.DirectoryEnumerationOptions = []) throws -> [URL] { return [] } + func contentsOfDirectory(atPath path: String) throws -> [String] { return [] } + func directoryContents(atPath path: String) -> [Any]? { return [] } // returns array of NSString + func subpathsOfDirectory(atPath path: String) throws -> [String] { return [] } + func subpaths(atPath path: String) -> [String]? { return [] } + + func destinationOfSymbolicLink(atPath path: String) throws -> String { return "" } + func pathContentOfSymbolicLink(atPath path: String) -> String? { return "" } + + func contents(atPath path: String) -> Data? { return nil } +} + +// --- tests --- + +func testFileHandle(fm: FileManager, url: URL, path: String) { + do + { + let contents1 = try fm.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) // $ source=local + let contents2 = try fm.contentsOfDirectory(atPath: path) // $ source=local + let contents3 = fm.directoryContents(atPath: path)! // $ source=local + + let subpaths1 = try fm.subpathsOfDirectory(atPath: path) // $ source=local + let subpaths2 = fm.subpaths(atPath: path)! // $ source=local + + let link1 = try fm.destinationOfSymbolicLink(atPath: path) // $ source=local + let link2 = fm.pathContentOfSymbolicLink(atPath: path)! // $ source=local + + let data = fm.contents(atPath: path)! // $ source=local + } catch { + // ... + } +} diff --git a/swift/ql/test/library-tests/dataflow/flowsources/generics.swift b/swift/ql/test/library-tests/dataflow/flowsources/generics.swift index 9b52d0a27df..0a973b68e72 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/generics.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/generics.swift @@ -7,9 +7,9 @@ class MySimpleClass } func useMySimpleClass(simple: MySimpleClass) { - _ = simple.source1 // SOURCE - _ = simple.source2 // SOURCE - _ = simple.source3() // SOURCE + _ = simple.source1 // $ source=remote + _ = simple.source2 // $ source=remote + _ = simple.source3() // $ source=remote } // --- @@ -45,28 +45,28 @@ extension MyDerived2 } func useDerived(generic: MyGeneric, generic2: MyGeneric, derived: MyDerived, derived2: MyDerived2) { - _ = generic.source1 // SOURCE - _ = generic.source2 // SOURCE - _ = generic.source3() // SOURCE - _ = generic2.source1 // SOURCE - _ = generic2.source2 // SOURCE - _ = generic2.source3() // SOURCE - _ = derived.source1 // SOURCE - _ = derived.source2 // SOURCE - _ = derived.source3() // SOURCE - _ = derived.source4 // SOURCE - _ = derived.source5 // SOURCE - _ = derived.source6() // SOURCE - _ = derived.source7 // SOURCE - _ = derived.source8() // SOURCE - _ = derived2.source1 // SOURCE - _ = derived2.source2 // SOURCE - _ = derived2.source3() // SOURCE - _ = derived2.source9 // SOURCE - _ = derived2.source10 // SOURCE - _ = derived2.source11() // SOURCE - _ = derived2.source12 // SOURCE - _ = derived2.source13() // SOURCE + _ = generic.source1 // $ source=remote + _ = generic.source2 // $ source=remote + _ = generic.source3() // $ source=remote + _ = generic2.source1 // $ source=remote + _ = generic2.source2 // $ source=remote + _ = generic2.source3() // $ source=remote + _ = derived.source1 // $ source=remote + _ = derived.source2 // $ source=remote + _ = derived.source3() // $ source=remote + _ = derived.source4 // $ source=remote + _ = derived.source5 // $ source=remote + _ = derived.source6() // $ source=remote + _ = derived.source7 // $ source=remote + _ = derived.source8() // $ source=remote + _ = derived2.source1 // $ source=remote + _ = derived2.source2 // $ source=remote + _ = derived2.source3() // $ source=remote + _ = derived2.source9 // $ source=remote + _ = derived2.source10 // $ source=remote + _ = derived2.source11() // $ source=remote + _ = derived2.source12 // $ source=remote + _ = derived2.source13() // $ source=remote } // --- @@ -90,15 +90,15 @@ extension MyImpl { } func useProtocol(proto: MyProtocol, impl: MyImpl, impl2: MyImpl) { - _ = proto.source0 // SOURCE - _ = proto.source1 // SOURCE - _ = proto.source2 // SOURCE - _ = impl.source0 // SOURCE - _ = impl.source1 // SOURCE - _ = impl.source2 // SOURCE - _ = impl2.source0 // SOURCE - _ = impl2.source1 // SOURCE - _ = impl2.source2 // SOURCE + _ = proto.source0 // $ source=remote + _ = proto.source1 // $ source=remote + _ = proto.source2 // $ source=remote + _ = impl.source0 // $ source=remote + _ = impl.source1 // $ source=remote + _ = impl.source2 // $ source=remote + _ = impl2.source0 // $ source=remote + _ = impl2.source1 // $ source=remote + _ = impl2.source2 // $ source=remote } // --- @@ -122,15 +122,15 @@ extension MyImpl2 : MyProtocol2 { } func useProtocol2(proto: MyProtocol2, impl: MyImpl2, impl2: MyImpl2) { - _ = proto.source0 // SOURCE - _ = proto.source1 // SOURCE - _ = proto.source2 // SOURCE - _ = impl.source0 // SOURCE - _ = impl.source1 // SOURCE - _ = impl.source2 // SOURCE - _ = impl2.source0 // SOURCE - _ = impl2.source1 // SOURCE - _ = impl2.source2 // SOURCE + _ = proto.source0 // $ source=remote + _ = proto.source1 // $ source=remote + _ = proto.source2 // $ source=remote + _ = impl.source0 // $ source=remote + _ = impl.source1 // $ source=remote + _ = impl.source2 // $ source=remote + _ = impl2.source0 // $ source=remote + _ = impl2.source1 // $ source=remote + _ = impl2.source2 // $ source=remote } // --- @@ -159,6 +159,6 @@ class MyChildClass3: MyClass3 { func useProtocol3(impl: MyChildClass3) { _ = impl.source1() // not a source (`MyProtocol3.source1` is the declared source and `MyParentClass3` doesn't extend it) - _ = impl.source2() // SOURCE - _ = impl.source3() // SOURCE + _ = impl.source2() // $ source=remote + _ = impl.source3() // $ source=remote } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/nsdata.swift b/swift/ql/test/library-tests/dataflow/flowsources/nsdata.swift index d1258f10364..8f37704234c 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/nsdata.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/nsdata.swift @@ -15,6 +15,6 @@ class NSData { func testNSData() { let url = URL(string: "http://example.com/") - let _ = try NSData(contentsOf: url!) // SOURCE - let _ = try NSData(contentsOf: url!, options: []) // SOURCE + let _ = try NSData(contentsOf: url!) // $ source=remote + let _ = try NSData(contentsOf: url!, options: []) // $ source=remote } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/string.swift b/swift/ql/test/library-tests/dataflow/flowsources/string.swift index 24ad9f38a72..9becb5dac00 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/string.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/string.swift @@ -53,15 +53,15 @@ func testStrings() { let string2 = String(repeating: "abc", count: 10) let url = URL(string: "http://example.com/") - let string3 = try String(contentsOf: url!) // SOURCE - let string4 = try String(contentsOf: url!, encoding: String.Encoding.ascii) // SOURCE + let string3 = try String(contentsOf: url!) // $ source=remote + let string4 = try String(contentsOf: url!, encoding: String.Encoding.ascii) // $ source=remote var encoding = String.Encoding.ascii - let string5 = try String(contentsOf: url!, usedEncoding: &encoding) // SOURCE + let string5 = try String(contentsOf: url!, usedEncoding: &encoding) // $ source=remote let path = "file.txt" - let string6 = try String(contentsOfFile: path) // SOURCE - let string7 = try String(contentsOfFile: path, encoding: String.Encoding.ascii) // SOURCE - let string8 = try String(contentsOfFile: path, usedEncoding: &encoding) // SOURCE + let string6 = try String(contentsOfFile: path) // $ source=local + let string7 = try String(contentsOfFile: path, encoding: String.Encoding.ascii) // $ source=local + let string8 = try String(contentsOfFile: path, usedEncoding: &encoding) // $ source=local } catch { // ... } diff --git a/swift/ql/test/library-tests/dataflow/flowsources/url.swift b/swift/ql/test/library-tests/dataflow/flowsources/url.swift index 0eab68736ce..66df5c827db 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/url.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/url.swift @@ -50,21 +50,21 @@ func testURLs() async { do { let url = URL(string: "http://example.com/")! - let bytes = url.resourceBytes // SOURCE + let bytes = url.resourceBytes // $ source=remote for try await byte in bytes { print(byte) } - let lines = url.lines // SOURCE + let lines = url.lines // $ source=remote for try await line in lines { print(line) } - let lines2 = bytes.lines // SOURCE + let lines2 = bytes.lines // $ source=remote for try await line in lines2 { diff --git a/swift/ql/test/library-tests/dataflow/flowsources/webview.swift b/swift/ql/test/library-tests/dataflow/flowsources/webview.swift index 1f949839be1..6fbc2b69721 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/webview.swift +++ b/swift/ql/test/library-tests/dataflow/flowsources/webview.swift @@ -10,8 +10,8 @@ protocol WKScriptMessageHandler { } protocol WKNavigationDelegate { - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) // $ SPURIOUS?: source=remote + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) // $ SPURIOUS?: source=remote } class WKWebView {} @@ -30,21 +30,22 @@ class JSValue {} class JSContext { var globalObject: JSValue { get { return JSValue() } } - func objectForKeyedSubscript(_: Any!) -> JSValue! { return JSValue() } + func objectForKeyedSubscript(_: Any!) -> JSValue! { return JSValue() } func setObject(_: Any, forKeyedSubscript: (NSCopying & NSObjectProtocol) ) {} } protocol JSExport {} // --- tests --- + class TestMessageHandler: WKScriptMessageHandler { - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { // SOURCE + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { // $ source=remote } } func testJsContext(context: JSContext) { - context.globalObject // SOURCE - context.objectForKeyedSubscript("") // SOURCE + context.globalObject // $ source=remote + context.objectForKeyedSubscript("") // $ source=remote } protocol Exported : JSExport { @@ -57,25 +58,25 @@ class ExportedImpl : Exported { var notTainted: Any { get { return ""} } func readFields() { - tainted // SOURCE + tainted // $ source=remote notTainted } - func tainted(arg1: Any, arg2: Any) { // SOURCES + func tainted(arg1: Any, arg2: Any) { // $ source=remote } func notTainted(arg1: Any, arg2: Any) { } -} +} class WebViewDelegate : WKNavigationDelegate { - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // SOURCE - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // SOURCE + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // $ source=remote + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // $ source=remote } class Extended {} extension Extended : WKNavigationDelegate { - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // SOURCE - func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // SOURCE + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // $ source=remote + func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // $ source=remote } diff --git a/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected index 05b72586dac..f6dd70752fa 100644 --- a/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected @@ -557,6 +557,86 @@ | nsmutabledata.swift:48:9:48:9 | SSA def(nsMutableDataTainted6) | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 | | nsmutabledata.swift:48:33:48:40 | call to source() | nsmutabledata.swift:48:9:48:9 | SSA def(nsMutableDataTainted6) | | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 | nsmutabledata.swift:49:15:49:37 | .mutableBytes | +| simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... | +| simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | +| simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | +| simple.swift:13:24:13:24 | 1 | simple.swift:13:13:13:24 | ... .+(_:_:) ... | +| simple.swift:14:13:14:13 | 1 | simple.swift:14:13:14:24 | ... .-(_:_:) ... | +| simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | +| simple.swift:15:13:15:20 | call to source() | simple.swift:15:13:15:24 | ... .-(_:_:) ... | +| simple.swift:15:24:15:24 | 1 | simple.swift:15:13:15:24 | ... .-(_:_:) ... | +| simple.swift:16:13:16:13 | 2 | simple.swift:16:13:16:24 | ... .*(_:_:) ... | +| simple.swift:16:17:16:24 | call to source() | simple.swift:16:13:16:24 | ... .*(_:_:) ... | +| simple.swift:17:13:17:20 | call to source() | simple.swift:17:13:17:24 | ... .*(_:_:) ... | +| simple.swift:17:24:17:24 | 2 | simple.swift:17:13:17:24 | ... .*(_:_:) ... | +| simple.swift:18:13:18:13 | 100 | simple.swift:18:13:18:26 | ... ./(_:_:) ... | +| simple.swift:18:19:18:26 | call to source() | simple.swift:18:13:18:26 | ... ./(_:_:) ... | +| simple.swift:19:13:19:20 | call to source() | simple.swift:19:13:19:24 | ... ./(_:_:) ... | +| simple.swift:19:24:19:24 | 100 | simple.swift:19:13:19:24 | ... ./(_:_:) ... | +| simple.swift:20:13:20:13 | 100 | simple.swift:20:13:20:26 | ... .%(_:_:) ... | +| simple.swift:20:19:20:26 | call to source() | simple.swift:20:13:20:26 | ... .%(_:_:) ... | +| simple.swift:21:13:21:20 | call to source() | simple.swift:21:13:21:24 | ... .%(_:_:) ... | +| simple.swift:21:24:21:24 | 100 | simple.swift:21:13:21:24 | ... .%(_:_:) ... | +| simple.swift:23:14:23:21 | call to source() | simple.swift:23:13:23:21 | call to -(_:) | +| simple.swift:36:7:36:7 | SSA def(a) | simple.swift:37:13:37:13 | a | +| simple.swift:36:11:36:11 | 0 | simple.swift:36:7:36:7 | SSA def(a) | +| simple.swift:37:13:37:13 | [post] a | simple.swift:38:3:38:3 | a | +| simple.swift:37:13:37:13 | a | simple.swift:38:3:38:3 | a | +| simple.swift:38:3:38:3 | &... | simple.swift:39:13:39:13 | a | +| simple.swift:38:3:38:3 | [post] &... | simple.swift:39:13:39:13 | a | +| simple.swift:38:3:38:3 | a | simple.swift:38:3:38:3 | &... | +| simple.swift:39:13:39:13 | [post] a | simple.swift:40:3:40:3 | a | +| simple.swift:39:13:39:13 | a | simple.swift:40:3:40:3 | a | +| simple.swift:40:3:40:3 | &... | simple.swift:41:13:41:13 | a | +| simple.swift:40:3:40:3 | [post] &... | simple.swift:41:13:41:13 | a | +| simple.swift:40:3:40:3 | a | simple.swift:40:3:40:3 | &... | +| simple.swift:41:13:41:13 | [post] a | simple.swift:42:3:42:3 | a | +| simple.swift:41:13:41:13 | a | simple.swift:42:3:42:3 | a | +| simple.swift:42:3:42:3 | &... | simple.swift:43:13:43:13 | a | +| simple.swift:42:3:42:3 | [post] &... | simple.swift:43:13:43:13 | a | +| simple.swift:42:3:42:3 | a | simple.swift:42:3:42:3 | &... | +| simple.swift:44:3:44:7 | SSA def(a) | simple.swift:45:13:45:13 | a | +| simple.swift:44:7:44:7 | 0 | simple.swift:44:3:44:7 | SSA def(a) | +| simple.swift:47:7:47:7 | SSA def(b) | simple.swift:48:3:48:3 | b | +| simple.swift:47:11:47:11 | 128 | simple.swift:47:7:47:7 | SSA def(b) | +| simple.swift:48:3:48:3 | &... | simple.swift:49:13:49:13 | b | +| simple.swift:48:3:48:3 | [post] &... | simple.swift:49:13:49:13 | b | +| simple.swift:48:3:48:3 | b | simple.swift:48:3:48:3 | &... | +| simple.swift:49:13:49:13 | [post] b | simple.swift:50:3:50:3 | b | +| simple.swift:49:13:49:13 | b | simple.swift:50:3:50:3 | b | +| simple.swift:50:3:50:3 | &... | simple.swift:51:13:51:13 | b | +| simple.swift:50:3:50:3 | [post] &... | simple.swift:51:13:51:13 | b | +| simple.swift:50:3:50:3 | b | simple.swift:50:3:50:3 | &... | +| simple.swift:53:7:53:7 | SSA def(c) | simple.swift:54:3:54:3 | c | +| simple.swift:53:11:53:11 | 10 | simple.swift:53:7:53:7 | SSA def(c) | +| simple.swift:54:3:54:3 | &... | simple.swift:55:13:55:13 | c | +| simple.swift:54:3:54:3 | [post] &... | simple.swift:55:13:55:13 | c | +| simple.swift:54:3:54:3 | c | simple.swift:54:3:54:3 | &... | +| simple.swift:55:13:55:13 | [post] c | simple.swift:56:3:56:3 | c | +| simple.swift:55:13:55:13 | c | simple.swift:56:3:56:3 | c | +| simple.swift:56:3:56:3 | &... | simple.swift:57:13:57:13 | c | +| simple.swift:56:3:56:3 | [post] &... | simple.swift:57:13:57:13 | c | +| simple.swift:56:3:56:3 | c | simple.swift:56:3:56:3 | &... | +| simple.swift:59:7:59:7 | SSA def(d) | simple.swift:60:3:60:3 | d | +| simple.swift:59:11:59:11 | 100 | simple.swift:59:7:59:7 | SSA def(d) | +| simple.swift:60:3:60:3 | &... | simple.swift:61:13:61:13 | d | +| simple.swift:60:3:60:3 | [post] &... | simple.swift:61:13:61:13 | d | +| simple.swift:60:3:60:3 | d | simple.swift:60:3:60:3 | &... | +| simple.swift:61:13:61:13 | [post] d | simple.swift:62:3:62:3 | d | +| simple.swift:61:13:61:13 | d | simple.swift:62:3:62:3 | d | +| simple.swift:62:3:62:3 | &... | simple.swift:63:13:63:13 | d | +| simple.swift:62:3:62:3 | [post] &... | simple.swift:63:13:63:13 | d | +| simple.swift:62:3:62:3 | d | simple.swift:62:3:62:3 | &... | +| simple.swift:65:7:65:7 | SSA def(e) | simple.swift:66:3:66:3 | e | +| simple.swift:65:11:65:11 | 1000 | simple.swift:65:7:65:7 | SSA def(e) | +| simple.swift:66:3:66:3 | &... | simple.swift:67:13:67:13 | e | +| simple.swift:66:3:66:3 | [post] &... | simple.swift:67:13:67:13 | e | +| simple.swift:66:3:66:3 | e | simple.swift:66:3:66:3 | &... | +| simple.swift:67:13:67:13 | [post] e | simple.swift:68:3:68:3 | e | +| simple.swift:67:13:67:13 | e | simple.swift:68:3:68:3 | e | +| simple.swift:68:3:68:3 | &... | simple.swift:69:13:69:13 | e | +| simple.swift:68:3:68:3 | [post] &... | simple.swift:69:13:69:13 | e | +| simple.swift:68:3:68:3 | e | simple.swift:68:3:68:3 | &... | | string.swift:6:8:6:8 | SSA def(self) | string.swift:6:8:6:8 | self[return] | | string.swift:6:8:6:8 | self | string.swift:6:8:6:8 | SSA def(self) | | string.swift:10:3:10:3 | SSA def(self) | string.swift:10:3:10:27 | self[return] | @@ -697,296 +777,218 @@ | string.swift:84:38:84:38 | &... | string.swift:84:3:84:50 | self[return] | | string.swift:84:38:84:38 | [post] &... | string.swift:84:3:84:50 | self[return] | | string.swift:84:38:84:38 | self | string.swift:84:38:84:38 | &... | -| string.swift:88:29:88:29 | SSA def(self) | string.swift:88:29:88:38 | self[return] | -| string.swift:88:29:88:29 | self | string.swift:88:29:88:29 | SSA def(self) | -| string.swift:89:38:89:38 | SSA def(self) | string.swift:89:38:89:47 | self[return] | -| string.swift:89:38:89:38 | self | string.swift:89:38:89:38 | SSA def(self) | -| string.swift:90:36:90:36 | SSA def(self) | string.swift:90:36:90:45 | self[return] | -| string.swift:90:36:90:36 | self | string.swift:90:36:90:36 | SSA def(self) | -| string.swift:91:36:91:36 | SSA def(self) | string.swift:91:36:91:45 | self[return] | -| string.swift:91:36:91:36 | self | string.swift:91:36:91:36 | SSA def(self) | -| string.swift:92:42:92:42 | SSA def(self) | string.swift:92:42:92:51 | self[return] | -| string.swift:92:42:92:42 | self | string.swift:92:42:92:42 | SSA def(self) | -| string.swift:93:54:93:54 | SSA def(self) | string.swift:93:54:93:63 | self[return] | -| string.swift:93:54:93:54 | self | string.swift:93:54:93:54 | SSA def(self) | -| string.swift:94:58:94:58 | SSA def(self) | string.swift:94:58:94:67 | self[return] | -| string.swift:94:58:94:58 | self | string.swift:94:58:94:58 | SSA def(self) | -| string.swift:95:55:95:55 | SSA def(self) | string.swift:95:55:95:64 | self[return] | -| string.swift:95:55:95:55 | self | string.swift:95:55:95:55 | SSA def(self) | -| string.swift:96:59:96:59 | SSA def(self) | string.swift:96:59:96:68 | self[return] | -| string.swift:96:59:96:59 | self | string.swift:96:59:96:59 | SSA def(self) | -| string.swift:98:8:98:8 | SSA def(self) | string.swift:98:3:98:63 | self[return] | -| string.swift:98:8:98:8 | self | string.swift:98:8:98:8 | SSA def(self) | -| string.swift:99:8:99:8 | SSA def(self) | string.swift:99:3:99:63 | self[return] | -| string.swift:99:8:99:8 | self | string.swift:99:8:99:8 | SSA def(self) | -| string.swift:100:8:100:8 | SSA def(self) | string.swift:100:3:100:64 | self[return] | -| string.swift:100:8:100:8 | self | string.swift:100:8:100:8 | SSA def(self) | -| string.swift:101:8:101:8 | SSA def(self) | string.swift:101:3:101:64 | self[return] | +| string.swift:86:17:86:17 | SSA def(self) | string.swift:86:12:87:51 | self[return] | +| string.swift:86:17:86:17 | self | string.swift:86:17:86:17 | SSA def(self) | +| string.swift:91:29:91:29 | SSA def(self) | string.swift:91:29:91:38 | self[return] | +| string.swift:91:29:91:29 | self | string.swift:91:29:91:29 | SSA def(self) | +| string.swift:92:38:92:38 | SSA def(self) | string.swift:92:38:92:47 | self[return] | +| string.swift:92:38:92:38 | self | string.swift:92:38:92:38 | SSA def(self) | +| string.swift:93:36:93:36 | SSA def(self) | string.swift:93:36:93:45 | self[return] | +| string.swift:93:36:93:36 | self | string.swift:93:36:93:36 | SSA def(self) | +| string.swift:94:36:94:36 | SSA def(self) | string.swift:94:36:94:45 | self[return] | +| string.swift:94:36:94:36 | self | string.swift:94:36:94:36 | SSA def(self) | +| string.swift:95:42:95:42 | SSA def(self) | string.swift:95:42:95:51 | self[return] | +| string.swift:95:42:95:42 | self | string.swift:95:42:95:42 | SSA def(self) | +| string.swift:96:54:96:54 | SSA def(self) | string.swift:96:54:96:63 | self[return] | +| string.swift:96:54:96:54 | self | string.swift:96:54:96:54 | SSA def(self) | +| string.swift:97:58:97:58 | SSA def(self) | string.swift:97:58:97:67 | self[return] | +| string.swift:97:58:97:58 | self | string.swift:97:58:97:58 | SSA def(self) | +| string.swift:98:55:98:55 | SSA def(self) | string.swift:98:55:98:64 | self[return] | +| string.swift:98:55:98:55 | self | string.swift:98:55:98:55 | SSA def(self) | +| string.swift:99:59:99:59 | SSA def(self) | string.swift:99:59:99:68 | self[return] | +| string.swift:99:59:99:59 | self | string.swift:99:59:99:59 | SSA def(self) | +| string.swift:101:8:101:8 | SSA def(self) | string.swift:101:3:101:63 | self[return] | | string.swift:101:8:101:8 | self | string.swift:101:8:101:8 | SSA def(self) | -| string.swift:102:8:102:8 | SSA def(self) | string.swift:102:3:102:71 | self[return] | +| string.swift:102:8:102:8 | SSA def(self) | string.swift:102:3:102:63 | self[return] | | string.swift:102:8:102:8 | self | string.swift:102:8:102:8 | SSA def(self) | -| string.swift:103:8:103:8 | SSA def(self) | string.swift:103:3:103:82 | self[return] | +| string.swift:103:8:103:8 | SSA def(self) | string.swift:103:3:103:64 | self[return] | | string.swift:103:8:103:8 | self | string.swift:103:8:103:8 | SSA def(self) | -| string.swift:104:8:104:8 | SSA def(self) | string.swift:104:3:104:138 | self[return] | +| string.swift:104:8:104:8 | SSA def(self) | string.swift:104:3:104:64 | self[return] | | string.swift:104:8:104:8 | self | string.swift:104:8:104:8 | SSA def(self) | -| string.swift:105:8:105:8 | SSA def(self) | string.swift:105:3:105:80 | self[return] | +| string.swift:105:8:105:8 | SSA def(self) | string.swift:105:3:105:71 | self[return] | | string.swift:105:8:105:8 | self | string.swift:105:8:105:8 | SSA def(self) | -| string.swift:106:8:106:8 | SSA def(self) | string.swift:106:3:106:92 | self[return] | +| string.swift:106:8:106:8 | SSA def(self) | string.swift:106:3:106:82 | self[return] | | string.swift:106:8:106:8 | self | string.swift:106:8:106:8 | SSA def(self) | -| string.swift:107:8:107:8 | SSA def(self) | string.swift:107:3:107:78 | self[return] | +| string.swift:107:8:107:8 | SSA def(self) | string.swift:107:3:107:138 | self[return] | | string.swift:107:8:107:8 | self | string.swift:107:8:107:8 | SSA def(self) | -| string.swift:108:8:108:8 | SSA def(self) | string.swift:108:3:108:74 | self[return] | +| string.swift:108:8:108:8 | SSA def(self) | string.swift:108:3:108:80 | self[return] | | string.swift:108:8:108:8 | self | string.swift:108:8:108:8 | SSA def(self) | -| string.swift:109:8:109:8 | SSA def(self) | string.swift:109:3:109:79 | self[return] | +| string.swift:109:8:109:8 | SSA def(self) | string.swift:109:3:109:92 | self[return] | | string.swift:109:8:109:8 | self | string.swift:109:8:109:8 | SSA def(self) | -| string.swift:112:7:112:7 | SSA def(self) | string.swift:112:7:112:7 | self[return] | -| string.swift:112:7:112:7 | self | string.swift:112:7:112:7 | SSA def(self) | -| string.swift:114:5:114:5 | SSA def(self) | string.swift:114:5:114:29 | self[return] | -| string.swift:114:5:114:5 | self | string.swift:114:5:114:5 | SSA def(self) | -| string.swift:120:32:120:32 | SSA def(self) | string.swift:120:32:120:47 | self[return] | -| string.swift:120:32:120:32 | self | string.swift:120:32:120:32 | SSA def(self) | -| string.swift:121:30:121:30 | SSA def(self) | string.swift:121:30:121:45 | self[return] | -| string.swift:121:30:121:30 | self | string.swift:121:30:121:30 | SSA def(self) | -| string.swift:122:43:122:43 | SSA def(self) | string.swift:122:43:122:58 | self[return] | -| string.swift:122:43:122:43 | self | string.swift:122:43:122:43 | SSA def(self) | -| string.swift:123:8:123:8 | SSA def(self) | string.swift:123:3:123:60 | self[return] | -| string.swift:123:8:123:8 | self | string.swift:123:8:123:8 | SSA def(self) | -| string.swift:132:7:132:7 | SSA def(x) | string.swift:134:16:134:16 | x | -| string.swift:132:11:132:18 | call to source() | string.swift:132:7:132:7 | SSA def(x) | -| string.swift:134:13:134:13 | | string.swift:134:13:134:13 | [post] | -| string.swift:134:13:134:13 | | string.swift:134:14:134:14 | [post] &... | -| string.swift:134:13:134:13 | SSA def($interpolation) | string.swift:134:14:134:14 | SSA phi($interpolation) | -| string.swift:134:13:134:13 | TapExpr | string.swift:134:13:134:13 | "..." | -| string.swift:134:14:134:14 | $interpolation | string.swift:134:14:134:14 | &... | -| string.swift:134:14:134:14 | &... | string.swift:134:13:134:13 | [post] | -| string.swift:134:14:134:14 | &... | string.swift:134:14:134:14 | [post] &... | -| string.swift:134:14:134:14 | &... | string.swift:134:15:134:15 | $interpolation | -| string.swift:134:14:134:14 | SSA phi($interpolation) | string.swift:134:14:134:14 | $interpolation | -| string.swift:134:14:134:14 | [post] &... | string.swift:134:15:134:15 | $interpolation | -| string.swift:134:15:134:15 | $interpolation | string.swift:134:15:134:15 | &... | -| string.swift:134:15:134:15 | &... | string.swift:134:15:134:15 | [post] &... | -| string.swift:134:15:134:15 | &... | string.swift:134:16:134:16 | [post] x | -| string.swift:134:15:134:15 | &... | string.swift:134:18:134:18 | $interpolation | -| string.swift:134:15:134:15 | [post] &... | string.swift:134:18:134:18 | $interpolation | -| string.swift:134:16:134:16 | [post] x | string.swift:136:16:136:16 | x | -| string.swift:134:16:134:16 | x | string.swift:134:15:134:15 | [post] &... | -| string.swift:134:16:134:16 | x | string.swift:134:16:134:16 | [post] x | -| string.swift:134:16:134:16 | x | string.swift:136:16:136:16 | x | -| string.swift:134:18:134:18 | | string.swift:134:18:134:18 | [post] | -| string.swift:134:18:134:18 | | string.swift:134:18:134:18 | [post] &... | -| string.swift:134:18:134:18 | $interpolation | string.swift:134:18:134:18 | &... | -| string.swift:134:18:134:18 | &... | string.swift:134:13:134:13 | TapExpr | -| string.swift:134:18:134:18 | &... | string.swift:134:18:134:18 | [post] | -| string.swift:134:18:134:18 | &... | string.swift:134:18:134:18 | [post] &... | -| string.swift:134:18:134:18 | [post] &... | string.swift:134:13:134:13 | TapExpr | -| string.swift:136:13:136:13 | | string.swift:136:13:136:13 | [post] | -| string.swift:136:13:136:13 | | string.swift:136:14:136:14 | [post] &... | -| string.swift:136:13:136:13 | SSA def($interpolation) | string.swift:136:14:136:14 | SSA phi($interpolation) | -| string.swift:136:13:136:13 | TapExpr | string.swift:136:13:136:13 | "..." | -| string.swift:136:14:136:14 | $interpolation | string.swift:136:14:136:14 | &... | -| string.swift:136:14:136:14 | &... | string.swift:136:13:136:13 | [post] | -| string.swift:136:14:136:14 | &... | string.swift:136:14:136:14 | [post] &... | -| string.swift:136:14:136:14 | &... | string.swift:136:15:136:15 | $interpolation | -| string.swift:136:14:136:14 | SSA phi($interpolation) | string.swift:136:14:136:14 | $interpolation | -| string.swift:136:14:136:14 | [post] &... | string.swift:136:15:136:15 | $interpolation | -| string.swift:136:15:136:15 | $interpolation | string.swift:136:15:136:15 | &... | -| string.swift:136:15:136:15 | &... | string.swift:136:15:136:15 | [post] &... | -| string.swift:136:15:136:15 | &... | string.swift:136:16:136:16 | [post] x | -| string.swift:136:15:136:15 | &... | string.swift:136:18:136:18 | $interpolation | -| string.swift:136:15:136:15 | [post] &... | string.swift:136:18:136:18 | $interpolation | -| string.swift:136:16:136:16 | [post] x | string.swift:136:21:136:21 | x | -| string.swift:136:16:136:16 | x | string.swift:136:15:136:15 | [post] &... | -| string.swift:136:16:136:16 | x | string.swift:136:16:136:16 | [post] x | -| string.swift:136:16:136:16 | x | string.swift:136:21:136:21 | x | -| string.swift:136:18:136:18 | | string.swift:136:18:136:18 | [post] | -| string.swift:136:18:136:18 | | string.swift:136:18:136:18 | [post] &... | -| string.swift:136:18:136:18 | $interpolation | string.swift:136:18:136:18 | &... | -| string.swift:136:18:136:18 | &... | string.swift:136:18:136:18 | [post] | -| string.swift:136:18:136:18 | &... | string.swift:136:18:136:18 | [post] &... | -| string.swift:136:18:136:18 | &... | string.swift:136:20:136:20 | $interpolation | -| string.swift:136:18:136:18 | [post] &... | string.swift:136:20:136:20 | $interpolation | -| string.swift:136:20:136:20 | $interpolation | string.swift:136:20:136:20 | &... | -| string.swift:136:20:136:20 | &... | string.swift:136:20:136:20 | [post] &... | -| string.swift:136:20:136:20 | &... | string.swift:136:21:136:21 | [post] x | -| string.swift:136:20:136:20 | &... | string.swift:136:23:136:23 | $interpolation | -| string.swift:136:20:136:20 | [post] &... | string.swift:136:23:136:23 | $interpolation | -| string.swift:136:21:136:21 | [post] x | string.swift:138:16:138:16 | x | -| string.swift:136:21:136:21 | x | string.swift:136:20:136:20 | [post] &... | -| string.swift:136:21:136:21 | x | string.swift:136:21:136:21 | [post] x | -| string.swift:136:21:136:21 | x | string.swift:138:16:138:16 | x | -| string.swift:136:23:136:23 | | string.swift:136:23:136:23 | [post] | -| string.swift:136:23:136:23 | | string.swift:136:23:136:23 | [post] &... | -| string.swift:136:23:136:23 | $interpolation | string.swift:136:23:136:23 | &... | -| string.swift:136:23:136:23 | &... | string.swift:136:13:136:13 | TapExpr | -| string.swift:136:23:136:23 | &... | string.swift:136:23:136:23 | [post] | -| string.swift:136:23:136:23 | &... | string.swift:136:23:136:23 | [post] &... | -| string.swift:136:23:136:23 | [post] &... | string.swift:136:13:136:13 | TapExpr | -| string.swift:138:13:138:13 | | string.swift:138:13:138:13 | [post] | -| string.swift:138:13:138:13 | | string.swift:138:14:138:14 | [post] &... | -| string.swift:138:13:138:13 | SSA def($interpolation) | string.swift:138:14:138:14 | SSA phi($interpolation) | -| string.swift:138:13:138:13 | TapExpr | string.swift:138:13:138:13 | "..." | -| string.swift:138:14:138:14 | $interpolation | string.swift:138:14:138:14 | &... | -| string.swift:138:14:138:14 | &... | string.swift:138:13:138:13 | [post] | -| string.swift:138:14:138:14 | &... | string.swift:138:14:138:14 | [post] &... | -| string.swift:138:14:138:14 | &... | string.swift:138:15:138:15 | $interpolation | -| string.swift:138:14:138:14 | SSA phi($interpolation) | string.swift:138:14:138:14 | $interpolation | -| string.swift:138:14:138:14 | [post] &... | string.swift:138:15:138:15 | $interpolation | -| string.swift:138:15:138:15 | $interpolation | string.swift:138:15:138:15 | &... | -| string.swift:138:15:138:15 | &... | string.swift:138:15:138:15 | [post] &... | -| string.swift:138:15:138:15 | &... | string.swift:138:16:138:16 | [post] x | -| string.swift:138:15:138:15 | &... | string.swift:138:18:138:18 | $interpolation | -| string.swift:138:15:138:15 | [post] &... | string.swift:138:18:138:18 | $interpolation | -| string.swift:138:16:138:16 | [post] x | string.swift:138:26:138:26 | x | -| string.swift:138:16:138:16 | x | string.swift:138:15:138:15 | [post] &... | -| string.swift:138:16:138:16 | x | string.swift:138:16:138:16 | [post] x | -| string.swift:138:16:138:16 | x | string.swift:138:26:138:26 | x | -| string.swift:138:18:138:18 | | string.swift:138:18:138:18 | [post] | -| string.swift:138:18:138:18 | | string.swift:138:18:138:18 | [post] &... | -| string.swift:138:18:138:18 | $interpolation | string.swift:138:18:138:18 | &... | -| string.swift:138:18:138:18 | &... | string.swift:138:18:138:18 | [post] | -| string.swift:138:18:138:18 | &... | string.swift:138:18:138:18 | [post] &... | -| string.swift:138:18:138:18 | &... | string.swift:138:20:138:20 | $interpolation | -| string.swift:138:18:138:18 | [post] &... | string.swift:138:20:138:20 | $interpolation | -| string.swift:138:20:138:20 | $interpolation | string.swift:138:20:138:20 | &... | -| string.swift:138:20:138:20 | &... | string.swift:138:20:138:20 | [post] &... | -| string.swift:138:20:138:20 | &... | string.swift:138:21:138:21 | [post] 0 | -| string.swift:138:20:138:20 | &... | string.swift:138:23:138:23 | $interpolation | -| string.swift:138:20:138:20 | [post] &... | string.swift:138:23:138:23 | $interpolation | -| string.swift:138:21:138:21 | 0 | string.swift:138:20:138:20 | [post] &... | -| string.swift:138:21:138:21 | 0 | string.swift:138:21:138:21 | [post] 0 | -| string.swift:138:23:138:23 | | string.swift:138:23:138:23 | [post] | -| string.swift:138:23:138:23 | | string.swift:138:23:138:23 | [post] &... | -| string.swift:138:23:138:23 | $interpolation | string.swift:138:23:138:23 | &... | -| string.swift:138:23:138:23 | &... | string.swift:138:23:138:23 | [post] | -| string.swift:138:23:138:23 | &... | string.swift:138:23:138:23 | [post] &... | -| string.swift:138:23:138:23 | &... | string.swift:138:25:138:25 | $interpolation | -| string.swift:138:23:138:23 | [post] &... | string.swift:138:25:138:25 | $interpolation | -| string.swift:138:25:138:25 | $interpolation | string.swift:138:25:138:25 | &... | -| string.swift:138:25:138:25 | &... | string.swift:138:25:138:25 | [post] &... | -| string.swift:138:25:138:25 | &... | string.swift:138:26:138:26 | [post] x | -| string.swift:138:25:138:25 | &... | string.swift:138:28:138:28 | $interpolation | -| string.swift:138:25:138:25 | [post] &... | string.swift:138:28:138:28 | $interpolation | -| string.swift:138:26:138:26 | [post] x | string.swift:144:16:144:16 | x | -| string.swift:138:26:138:26 | x | string.swift:138:25:138:25 | [post] &... | -| string.swift:138:26:138:26 | x | string.swift:138:26:138:26 | [post] x | -| string.swift:138:26:138:26 | x | string.swift:144:16:144:16 | x | -| string.swift:138:28:138:28 | | string.swift:138:28:138:28 | [post] | -| string.swift:138:28:138:28 | | string.swift:138:28:138:28 | [post] &... | -| string.swift:138:28:138:28 | $interpolation | string.swift:138:28:138:28 | &... | -| string.swift:138:28:138:28 | &... | string.swift:138:13:138:13 | TapExpr | -| string.swift:138:28:138:28 | &... | string.swift:138:28:138:28 | [post] | -| string.swift:138:28:138:28 | &... | string.swift:138:28:138:28 | [post] &... | -| string.swift:138:28:138:28 | [post] &... | string.swift:138:13:138:13 | TapExpr | -| string.swift:140:7:140:7 | SSA def(y) | string.swift:142:16:142:16 | y | -| string.swift:140:11:140:11 | 42 | string.swift:140:7:140:7 | SSA def(y) | -| string.swift:142:13:142:13 | | string.swift:142:13:142:13 | [post] | -| string.swift:142:13:142:13 | | string.swift:142:14:142:14 | [post] &... | -| string.swift:142:13:142:13 | SSA def($interpolation) | string.swift:142:14:142:14 | SSA phi($interpolation) | -| string.swift:142:13:142:13 | TapExpr | string.swift:142:13:142:13 | "..." | -| string.swift:142:14:142:14 | $interpolation | string.swift:142:14:142:14 | &... | -| string.swift:142:14:142:14 | &... | string.swift:142:13:142:13 | [post] | -| string.swift:142:14:142:14 | &... | string.swift:142:14:142:14 | [post] &... | -| string.swift:142:14:142:14 | &... | string.swift:142:15:142:15 | $interpolation | -| string.swift:142:14:142:14 | SSA phi($interpolation) | string.swift:142:14:142:14 | $interpolation | -| string.swift:142:14:142:14 | [post] &... | string.swift:142:15:142:15 | $interpolation | -| string.swift:142:15:142:15 | $interpolation | string.swift:142:15:142:15 | &... | -| string.swift:142:15:142:15 | &... | string.swift:142:15:142:15 | [post] &... | -| string.swift:142:15:142:15 | &... | string.swift:142:16:142:16 | [post] y | -| string.swift:142:15:142:15 | &... | string.swift:142:18:142:18 | $interpolation | -| string.swift:142:15:142:15 | [post] &... | string.swift:142:18:142:18 | $interpolation | -| string.swift:142:16:142:16 | [post] y | string.swift:144:27:144:27 | y | -| string.swift:142:16:142:16 | y | string.swift:142:15:142:15 | [post] &... | -| string.swift:142:16:142:16 | y | string.swift:142:16:142:16 | [post] y | -| string.swift:142:16:142:16 | y | string.swift:144:27:144:27 | y | -| string.swift:142:18:142:18 | | string.swift:142:18:142:18 | [post] | -| string.swift:142:18:142:18 | | string.swift:142:18:142:18 | [post] &... | -| string.swift:142:18:142:18 | $interpolation | string.swift:142:18:142:18 | &... | -| string.swift:142:18:142:18 | &... | string.swift:142:13:142:13 | TapExpr | -| string.swift:142:18:142:18 | &... | string.swift:142:18:142:18 | [post] | -| string.swift:142:18:142:18 | &... | string.swift:142:18:142:18 | [post] &... | -| string.swift:142:18:142:18 | [post] &... | string.swift:142:13:142:13 | TapExpr | -| string.swift:144:13:144:13 | | string.swift:144:13:144:13 | [post] | -| string.swift:144:13:144:13 | | string.swift:144:14:144:14 | [post] &... | -| string.swift:144:13:144:13 | SSA def($interpolation) | string.swift:144:14:144:14 | SSA phi($interpolation) | -| string.swift:144:13:144:13 | TapExpr | string.swift:144:13:144:13 | "..." | -| string.swift:144:14:144:14 | $interpolation | string.swift:144:14:144:14 | &... | -| string.swift:144:14:144:14 | &... | string.swift:144:13:144:13 | [post] | -| string.swift:144:14:144:14 | &... | string.swift:144:14:144:14 | [post] &... | -| string.swift:144:14:144:14 | &... | string.swift:144:15:144:15 | $interpolation | -| string.swift:144:14:144:14 | SSA phi($interpolation) | string.swift:144:14:144:14 | $interpolation | -| string.swift:144:14:144:14 | [post] &... | string.swift:144:15:144:15 | $interpolation | -| string.swift:144:15:144:15 | $interpolation | string.swift:144:15:144:15 | &... | -| string.swift:144:15:144:15 | &... | string.swift:144:15:144:15 | [post] &... | -| string.swift:144:15:144:15 | &... | string.swift:144:16:144:16 | [post] x | -| string.swift:144:15:144:15 | &... | string.swift:144:18:144:18 | $interpolation | -| string.swift:144:15:144:15 | [post] &... | string.swift:144:18:144:18 | $interpolation | -| string.swift:144:16:144:16 | [post] x | string.swift:146:27:146:27 | x | -| string.swift:144:16:144:16 | x | string.swift:144:15:144:15 | [post] &... | -| string.swift:144:16:144:16 | x | string.swift:144:16:144:16 | [post] x | -| string.swift:144:16:144:16 | x | string.swift:146:27:146:27 | x | -| string.swift:144:18:144:18 | hello | string.swift:144:18:144:18 | [post] hello | -| string.swift:144:18:144:18 | hello | string.swift:144:18:144:18 | [post] &... | -| string.swift:144:18:144:18 | $interpolation | string.swift:144:18:144:18 | &... | -| string.swift:144:18:144:18 | &... | string.swift:144:18:144:18 | [post] hello | -| string.swift:144:18:144:18 | &... | string.swift:144:18:144:18 | [post] &... | -| string.swift:144:18:144:18 | &... | string.swift:144:26:144:26 | $interpolation | -| string.swift:144:18:144:18 | [post] &... | string.swift:144:26:144:26 | $interpolation | -| string.swift:144:26:144:26 | $interpolation | string.swift:144:26:144:26 | &... | -| string.swift:144:26:144:26 | &... | string.swift:144:26:144:26 | [post] &... | -| string.swift:144:26:144:26 | &... | string.swift:144:27:144:27 | [post] y | -| string.swift:144:26:144:26 | &... | string.swift:144:29:144:29 | $interpolation | -| string.swift:144:26:144:26 | [post] &... | string.swift:144:29:144:29 | $interpolation | -| string.swift:144:27:144:27 | [post] y | string.swift:146:16:146:16 | y | -| string.swift:144:27:144:27 | y | string.swift:144:26:144:26 | [post] &... | -| string.swift:144:27:144:27 | y | string.swift:144:27:144:27 | [post] y | -| string.swift:144:27:144:27 | y | string.swift:146:16:146:16 | y | -| string.swift:144:29:144:29 | | string.swift:144:29:144:29 | [post] | -| string.swift:144:29:144:29 | | string.swift:144:29:144:29 | [post] &... | -| string.swift:144:29:144:29 | $interpolation | string.swift:144:29:144:29 | &... | -| string.swift:144:29:144:29 | &... | string.swift:144:13:144:13 | TapExpr | -| string.swift:144:29:144:29 | &... | string.swift:144:29:144:29 | [post] | -| string.swift:144:29:144:29 | &... | string.swift:144:29:144:29 | [post] &... | -| string.swift:144:29:144:29 | [post] &... | string.swift:144:13:144:13 | TapExpr | -| string.swift:146:13:146:13 | | string.swift:146:13:146:13 | [post] | -| string.swift:146:13:146:13 | | string.swift:146:14:146:14 | [post] &... | -| string.swift:146:13:146:13 | SSA def($interpolation) | string.swift:146:14:146:14 | SSA phi($interpolation) | -| string.swift:146:13:146:13 | TapExpr | string.swift:146:13:146:13 | "..." | -| string.swift:146:14:146:14 | $interpolation | string.swift:146:14:146:14 | &... | -| string.swift:146:14:146:14 | &... | string.swift:146:13:146:13 | [post] | -| string.swift:146:14:146:14 | &... | string.swift:146:14:146:14 | [post] &... | -| string.swift:146:14:146:14 | &... | string.swift:146:15:146:15 | $interpolation | -| string.swift:146:14:146:14 | SSA phi($interpolation) | string.swift:146:14:146:14 | $interpolation | -| string.swift:146:14:146:14 | [post] &... | string.swift:146:15:146:15 | $interpolation | -| string.swift:146:15:146:15 | $interpolation | string.swift:146:15:146:15 | &... | -| string.swift:146:15:146:15 | &... | string.swift:146:15:146:15 | [post] &... | -| string.swift:146:15:146:15 | &... | string.swift:146:16:146:16 | [post] y | -| string.swift:146:15:146:15 | &... | string.swift:146:18:146:18 | $interpolation | -| string.swift:146:15:146:15 | [post] &... | string.swift:146:18:146:18 | $interpolation | -| string.swift:146:16:146:16 | y | string.swift:146:15:146:15 | [post] &... | -| string.swift:146:16:146:16 | y | string.swift:146:16:146:16 | [post] y | -| string.swift:146:18:146:18 | world | string.swift:146:18:146:18 | [post] world | -| string.swift:146:18:146:18 | world | string.swift:146:18:146:18 | [post] &... | -| string.swift:146:18:146:18 | $interpolation | string.swift:146:18:146:18 | &... | -| string.swift:146:18:146:18 | &... | string.swift:146:18:146:18 | [post] world | -| string.swift:146:18:146:18 | &... | string.swift:146:18:146:18 | [post] &... | -| string.swift:146:18:146:18 | &... | string.swift:146:26:146:26 | $interpolation | -| string.swift:146:18:146:18 | [post] &... | string.swift:146:26:146:26 | $interpolation | -| string.swift:146:26:146:26 | $interpolation | string.swift:146:26:146:26 | &... | -| string.swift:146:26:146:26 | &... | string.swift:146:26:146:26 | [post] &... | -| string.swift:146:26:146:26 | &... | string.swift:146:27:146:27 | [post] x | -| string.swift:146:26:146:26 | &... | string.swift:146:29:146:29 | $interpolation | -| string.swift:146:26:146:26 | [post] &... | string.swift:146:29:146:29 | $interpolation | -| string.swift:146:27:146:27 | x | string.swift:146:26:146:26 | [post] &... | -| string.swift:146:27:146:27 | x | string.swift:146:27:146:27 | [post] x | -| string.swift:146:29:146:29 | | string.swift:146:29:146:29 | [post] | -| string.swift:146:29:146:29 | | string.swift:146:29:146:29 | [post] &... | -| string.swift:146:29:146:29 | $interpolation | string.swift:146:29:146:29 | &... | -| string.swift:146:29:146:29 | &... | string.swift:146:13:146:13 | TapExpr | -| string.swift:146:29:146:29 | &... | string.swift:146:29:146:29 | [post] | -| string.swift:146:29:146:29 | &... | string.swift:146:29:146:29 | [post] &... | -| string.swift:146:29:146:29 | [post] &... | string.swift:146:13:146:13 | TapExpr | -| string.swift:148:3:148:7 | SSA def(x) | string.swift:149:16:149:16 | x | -| string.swift:148:7:148:7 | 0 | string.swift:148:3:148:7 | SSA def(x) | +| string.swift:110:8:110:8 | SSA def(self) | string.swift:110:3:110:78 | self[return] | +| string.swift:110:8:110:8 | self | string.swift:110:8:110:8 | SSA def(self) | +| string.swift:111:8:111:8 | SSA def(self) | string.swift:111:3:111:74 | self[return] | +| string.swift:111:8:111:8 | self | string.swift:111:8:111:8 | SSA def(self) | +| string.swift:112:8:112:8 | SSA def(self) | string.swift:112:3:112:79 | self[return] | +| string.swift:112:8:112:8 | self | string.swift:112:8:112:8 | SSA def(self) | +| string.swift:113:8:113:8 | SSA def(self) | string.swift:113:3:114:77 | self[return] | +| string.swift:113:8:113:8 | self | string.swift:113:8:113:8 | SSA def(self) | +| string.swift:117:7:117:7 | SSA def(self) | string.swift:117:7:117:7 | self[return] | +| string.swift:117:7:117:7 | self | string.swift:117:7:117:7 | SSA def(self) | +| string.swift:119:5:119:5 | SSA def(self) | string.swift:119:5:119:29 | self[return] | +| string.swift:119:5:119:5 | self | string.swift:119:5:119:5 | SSA def(self) | +| string.swift:125:32:125:32 | SSA def(self) | string.swift:125:32:125:47 | self[return] | +| string.swift:125:32:125:32 | self | string.swift:125:32:125:32 | SSA def(self) | +| string.swift:126:30:126:30 | SSA def(self) | string.swift:126:30:126:45 | self[return] | +| string.swift:126:30:126:30 | self | string.swift:126:30:126:30 | SSA def(self) | +| string.swift:127:43:127:43 | SSA def(self) | string.swift:127:43:127:58 | self[return] | +| string.swift:127:43:127:43 | self | string.swift:127:43:127:43 | SSA def(self) | +| string.swift:128:8:128:8 | SSA def(self) | string.swift:128:3:128:60 | self[return] | +| string.swift:128:8:128:8 | self | string.swift:128:8:128:8 | SSA def(self) | +| string.swift:137:7:137:7 | SSA def(x) | string.swift:139:16:139:16 | x | +| string.swift:137:11:137:18 | call to source() | string.swift:137:7:137:7 | SSA def(x) | +| string.swift:139:13:139:13 | | string.swift:139:13:139:13 | [post] | +| string.swift:139:13:139:13 | | string.swift:139:14:139:14 | [post] &... | +| string.swift:139:13:139:13 | SSA def($interpolation) | string.swift:139:14:139:14 | SSA phi($interpolation) | +| string.swift:139:13:139:13 | TapExpr | string.swift:139:13:139:13 | "..." | +| string.swift:139:14:139:14 | $interpolation | string.swift:139:14:139:14 | &... | +| string.swift:139:14:139:14 | &... | string.swift:139:13:139:13 | [post] | +| string.swift:139:14:139:14 | &... | string.swift:139:14:139:14 | [post] &... | +| string.swift:139:14:139:14 | &... | string.swift:139:15:139:15 | $interpolation | +| string.swift:139:14:139:14 | SSA phi($interpolation) | string.swift:139:14:139:14 | $interpolation | +| string.swift:139:14:139:14 | [post] &... | string.swift:139:15:139:15 | $interpolation | +| string.swift:139:15:139:15 | $interpolation | string.swift:139:15:139:15 | &... | +| string.swift:139:15:139:15 | &... | string.swift:139:15:139:15 | [post] &... | +| string.swift:139:15:139:15 | &... | string.swift:139:16:139:16 | [post] x | +| string.swift:139:15:139:15 | &... | string.swift:139:18:139:18 | $interpolation | +| string.swift:139:15:139:15 | [post] &... | string.swift:139:18:139:18 | $interpolation | +| string.swift:139:16:139:16 | [post] x | string.swift:141:16:141:16 | x | +| string.swift:139:16:139:16 | x | string.swift:139:15:139:15 | [post] &... | +| string.swift:139:16:139:16 | x | string.swift:139:16:139:16 | [post] x | +| string.swift:139:16:139:16 | x | string.swift:141:16:141:16 | x | +| string.swift:139:18:139:18 | | string.swift:139:18:139:18 | [post] | +| string.swift:139:18:139:18 | | string.swift:139:18:139:18 | [post] &... | +| string.swift:139:18:139:18 | $interpolation | string.swift:139:18:139:18 | &... | +| string.swift:139:18:139:18 | &... | string.swift:139:13:139:13 | TapExpr | +| string.swift:139:18:139:18 | &... | string.swift:139:18:139:18 | [post] | +| string.swift:139:18:139:18 | &... | string.swift:139:18:139:18 | [post] &... | +| string.swift:139:18:139:18 | [post] &... | string.swift:139:13:139:13 | TapExpr | +| string.swift:141:13:141:13 | | string.swift:141:13:141:13 | [post] | +| string.swift:141:13:141:13 | | string.swift:141:14:141:14 | [post] &... | +| string.swift:141:13:141:13 | SSA def($interpolation) | string.swift:141:14:141:14 | SSA phi($interpolation) | +| string.swift:141:13:141:13 | TapExpr | string.swift:141:13:141:13 | "..." | +| string.swift:141:14:141:14 | $interpolation | string.swift:141:14:141:14 | &... | +| string.swift:141:14:141:14 | &... | string.swift:141:13:141:13 | [post] | +| string.swift:141:14:141:14 | &... | string.swift:141:14:141:14 | [post] &... | +| string.swift:141:14:141:14 | &... | string.swift:141:15:141:15 | $interpolation | +| string.swift:141:14:141:14 | SSA phi($interpolation) | string.swift:141:14:141:14 | $interpolation | +| string.swift:141:14:141:14 | [post] &... | string.swift:141:15:141:15 | $interpolation | +| string.swift:141:15:141:15 | $interpolation | string.swift:141:15:141:15 | &... | +| string.swift:141:15:141:15 | &... | string.swift:141:15:141:15 | [post] &... | +| string.swift:141:15:141:15 | &... | string.swift:141:16:141:16 | [post] x | +| string.swift:141:15:141:15 | &... | string.swift:141:18:141:18 | $interpolation | +| string.swift:141:15:141:15 | [post] &... | string.swift:141:18:141:18 | $interpolation | +| string.swift:141:16:141:16 | [post] x | string.swift:141:21:141:21 | x | +| string.swift:141:16:141:16 | x | string.swift:141:15:141:15 | [post] &... | +| string.swift:141:16:141:16 | x | string.swift:141:16:141:16 | [post] x | +| string.swift:141:16:141:16 | x | string.swift:141:21:141:21 | x | +| string.swift:141:18:141:18 | | string.swift:141:18:141:18 | [post] | +| string.swift:141:18:141:18 | | string.swift:141:18:141:18 | [post] &... | +| string.swift:141:18:141:18 | $interpolation | string.swift:141:18:141:18 | &... | +| string.swift:141:18:141:18 | &... | string.swift:141:18:141:18 | [post] | +| string.swift:141:18:141:18 | &... | string.swift:141:18:141:18 | [post] &... | +| string.swift:141:18:141:18 | &... | string.swift:141:20:141:20 | $interpolation | +| string.swift:141:18:141:18 | [post] &... | string.swift:141:20:141:20 | $interpolation | +| string.swift:141:20:141:20 | $interpolation | string.swift:141:20:141:20 | &... | +| string.swift:141:20:141:20 | &... | string.swift:141:20:141:20 | [post] &... | +| string.swift:141:20:141:20 | &... | string.swift:141:21:141:21 | [post] x | +| string.swift:141:20:141:20 | &... | string.swift:141:23:141:23 | $interpolation | +| string.swift:141:20:141:20 | [post] &... | string.swift:141:23:141:23 | $interpolation | +| string.swift:141:21:141:21 | [post] x | string.swift:143:16:143:16 | x | +| string.swift:141:21:141:21 | x | string.swift:141:20:141:20 | [post] &... | +| string.swift:141:21:141:21 | x | string.swift:141:21:141:21 | [post] x | +| string.swift:141:21:141:21 | x | string.swift:143:16:143:16 | x | +| string.swift:141:23:141:23 | | string.swift:141:23:141:23 | [post] | +| string.swift:141:23:141:23 | | string.swift:141:23:141:23 | [post] &... | +| string.swift:141:23:141:23 | $interpolation | string.swift:141:23:141:23 | &... | +| string.swift:141:23:141:23 | &... | string.swift:141:13:141:13 | TapExpr | +| string.swift:141:23:141:23 | &... | string.swift:141:23:141:23 | [post] | +| string.swift:141:23:141:23 | &... | string.swift:141:23:141:23 | [post] &... | +| string.swift:141:23:141:23 | [post] &... | string.swift:141:13:141:13 | TapExpr | +| string.swift:143:13:143:13 | | string.swift:143:13:143:13 | [post] | +| string.swift:143:13:143:13 | | string.swift:143:14:143:14 | [post] &... | +| string.swift:143:13:143:13 | SSA def($interpolation) | string.swift:143:14:143:14 | SSA phi($interpolation) | +| string.swift:143:13:143:13 | TapExpr | string.swift:143:13:143:13 | "..." | +| string.swift:143:14:143:14 | $interpolation | string.swift:143:14:143:14 | &... | +| string.swift:143:14:143:14 | &... | string.swift:143:13:143:13 | [post] | +| string.swift:143:14:143:14 | &... | string.swift:143:14:143:14 | [post] &... | +| string.swift:143:14:143:14 | &... | string.swift:143:15:143:15 | $interpolation | +| string.swift:143:14:143:14 | SSA phi($interpolation) | string.swift:143:14:143:14 | $interpolation | +| string.swift:143:14:143:14 | [post] &... | string.swift:143:15:143:15 | $interpolation | +| string.swift:143:15:143:15 | $interpolation | string.swift:143:15:143:15 | &... | +| string.swift:143:15:143:15 | &... | string.swift:143:15:143:15 | [post] &... | +| string.swift:143:15:143:15 | &... | string.swift:143:16:143:16 | [post] x | +| string.swift:143:15:143:15 | &... | string.swift:143:18:143:18 | $interpolation | +| string.swift:143:15:143:15 | [post] &... | string.swift:143:18:143:18 | $interpolation | +| string.swift:143:16:143:16 | [post] x | string.swift:143:26:143:26 | x | +| string.swift:143:16:143:16 | x | string.swift:143:15:143:15 | [post] &... | +| string.swift:143:16:143:16 | x | string.swift:143:16:143:16 | [post] x | +| string.swift:143:16:143:16 | x | string.swift:143:26:143:26 | x | +| string.swift:143:18:143:18 | | string.swift:143:18:143:18 | [post] | +| string.swift:143:18:143:18 | | string.swift:143:18:143:18 | [post] &... | +| string.swift:143:18:143:18 | $interpolation | string.swift:143:18:143:18 | &... | +| string.swift:143:18:143:18 | &... | string.swift:143:18:143:18 | [post] | +| string.swift:143:18:143:18 | &... | string.swift:143:18:143:18 | [post] &... | +| string.swift:143:18:143:18 | &... | string.swift:143:20:143:20 | $interpolation | +| string.swift:143:18:143:18 | [post] &... | string.swift:143:20:143:20 | $interpolation | +| string.swift:143:20:143:20 | $interpolation | string.swift:143:20:143:20 | &... | +| string.swift:143:20:143:20 | &... | string.swift:143:20:143:20 | [post] &... | +| string.swift:143:20:143:20 | &... | string.swift:143:21:143:21 | [post] 0 | +| string.swift:143:20:143:20 | &... | string.swift:143:23:143:23 | $interpolation | +| string.swift:143:20:143:20 | [post] &... | string.swift:143:23:143:23 | $interpolation | +| string.swift:143:21:143:21 | 0 | string.swift:143:20:143:20 | [post] &... | +| string.swift:143:21:143:21 | 0 | string.swift:143:21:143:21 | [post] 0 | +| string.swift:143:23:143:23 | | string.swift:143:23:143:23 | [post] | +| string.swift:143:23:143:23 | | string.swift:143:23:143:23 | [post] &... | +| string.swift:143:23:143:23 | $interpolation | string.swift:143:23:143:23 | &... | +| string.swift:143:23:143:23 | &... | string.swift:143:23:143:23 | [post] | +| string.swift:143:23:143:23 | &... | string.swift:143:23:143:23 | [post] &... | +| string.swift:143:23:143:23 | &... | string.swift:143:25:143:25 | $interpolation | +| string.swift:143:23:143:23 | [post] &... | string.swift:143:25:143:25 | $interpolation | +| string.swift:143:25:143:25 | $interpolation | string.swift:143:25:143:25 | &... | +| string.swift:143:25:143:25 | &... | string.swift:143:25:143:25 | [post] &... | +| string.swift:143:25:143:25 | &... | string.swift:143:26:143:26 | [post] x | +| string.swift:143:25:143:25 | &... | string.swift:143:28:143:28 | $interpolation | +| string.swift:143:25:143:25 | [post] &... | string.swift:143:28:143:28 | $interpolation | +| string.swift:143:26:143:26 | [post] x | string.swift:149:16:149:16 | x | +| string.swift:143:26:143:26 | x | string.swift:143:25:143:25 | [post] &... | +| string.swift:143:26:143:26 | x | string.swift:143:26:143:26 | [post] x | +| string.swift:143:26:143:26 | x | string.swift:149:16:149:16 | x | +| string.swift:143:28:143:28 | | string.swift:143:28:143:28 | [post] | +| string.swift:143:28:143:28 | | string.swift:143:28:143:28 | [post] &... | +| string.swift:143:28:143:28 | $interpolation | string.swift:143:28:143:28 | &... | +| string.swift:143:28:143:28 | &... | string.swift:143:13:143:13 | TapExpr | +| string.swift:143:28:143:28 | &... | string.swift:143:28:143:28 | [post] | +| string.swift:143:28:143:28 | &... | string.swift:143:28:143:28 | [post] &... | +| string.swift:143:28:143:28 | [post] &... | string.swift:143:13:143:13 | TapExpr | +| string.swift:145:7:145:7 | SSA def(y) | string.swift:147:16:147:16 | y | +| string.swift:145:11:145:11 | 42 | string.swift:145:7:145:7 | SSA def(y) | +| string.swift:147:13:147:13 | | string.swift:147:13:147:13 | [post] | +| string.swift:147:13:147:13 | | string.swift:147:14:147:14 | [post] &... | +| string.swift:147:13:147:13 | SSA def($interpolation) | string.swift:147:14:147:14 | SSA phi($interpolation) | +| string.swift:147:13:147:13 | TapExpr | string.swift:147:13:147:13 | "..." | +| string.swift:147:14:147:14 | $interpolation | string.swift:147:14:147:14 | &... | +| string.swift:147:14:147:14 | &... | string.swift:147:13:147:13 | [post] | +| string.swift:147:14:147:14 | &... | string.swift:147:14:147:14 | [post] &... | +| string.swift:147:14:147:14 | &... | string.swift:147:15:147:15 | $interpolation | +| string.swift:147:14:147:14 | SSA phi($interpolation) | string.swift:147:14:147:14 | $interpolation | +| string.swift:147:14:147:14 | [post] &... | string.swift:147:15:147:15 | $interpolation | +| string.swift:147:15:147:15 | $interpolation | string.swift:147:15:147:15 | &... | +| string.swift:147:15:147:15 | &... | string.swift:147:15:147:15 | [post] &... | +| string.swift:147:15:147:15 | &... | string.swift:147:16:147:16 | [post] y | +| string.swift:147:15:147:15 | &... | string.swift:147:18:147:18 | $interpolation | +| string.swift:147:15:147:15 | [post] &... | string.swift:147:18:147:18 | $interpolation | +| string.swift:147:16:147:16 | [post] y | string.swift:149:27:149:27 | y | +| string.swift:147:16:147:16 | y | string.swift:147:15:147:15 | [post] &... | +| string.swift:147:16:147:16 | y | string.swift:147:16:147:16 | [post] y | +| string.swift:147:16:147:16 | y | string.swift:149:27:149:27 | y | +| string.swift:147:18:147:18 | | string.swift:147:18:147:18 | [post] | +| string.swift:147:18:147:18 | | string.swift:147:18:147:18 | [post] &... | +| string.swift:147:18:147:18 | $interpolation | string.swift:147:18:147:18 | &... | +| string.swift:147:18:147:18 | &... | string.swift:147:13:147:13 | TapExpr | +| string.swift:147:18:147:18 | &... | string.swift:147:18:147:18 | [post] | +| string.swift:147:18:147:18 | &... | string.swift:147:18:147:18 | [post] &... | +| string.swift:147:18:147:18 | [post] &... | string.swift:147:13:147:13 | TapExpr | | string.swift:149:13:149:13 | | string.swift:149:13:149:13 | [post] | | string.swift:149:13:149:13 | | string.swift:149:14:149:14 | [post] &... | | string.swift:149:13:149:13 | SSA def($interpolation) | string.swift:149:14:149:14 | SSA phi($interpolation) | @@ -1002,824 +1004,929 @@ | string.swift:149:15:149:15 | &... | string.swift:149:16:149:16 | [post] x | | string.swift:149:15:149:15 | &... | string.swift:149:18:149:18 | $interpolation | | string.swift:149:15:149:15 | [post] &... | string.swift:149:18:149:18 | $interpolation | +| string.swift:149:16:149:16 | [post] x | string.swift:151:27:151:27 | x | | string.swift:149:16:149:16 | x | string.swift:149:15:149:15 | [post] &... | | string.swift:149:16:149:16 | x | string.swift:149:16:149:16 | [post] x | -| string.swift:149:18:149:18 | | string.swift:149:18:149:18 | [post] | -| string.swift:149:18:149:18 | | string.swift:149:18:149:18 | [post] &... | +| string.swift:149:16:149:16 | x | string.swift:151:27:151:27 | x | +| string.swift:149:18:149:18 | hello | string.swift:149:18:149:18 | [post] hello | +| string.swift:149:18:149:18 | hello | string.swift:149:18:149:18 | [post] &... | | string.swift:149:18:149:18 | $interpolation | string.swift:149:18:149:18 | &... | -| string.swift:149:18:149:18 | &... | string.swift:149:13:149:13 | TapExpr | -| string.swift:149:18:149:18 | &... | string.swift:149:18:149:18 | [post] | +| string.swift:149:18:149:18 | &... | string.swift:149:18:149:18 | [post] hello | | string.swift:149:18:149:18 | &... | string.swift:149:18:149:18 | [post] &... | -| string.swift:149:18:149:18 | [post] &... | string.swift:149:13:149:13 | TapExpr | -| string.swift:155:7:155:7 | SSA def(clean) | string.swift:158:13:158:13 | clean | -| string.swift:155:15:155:15 | abcdef | string.swift:155:7:155:7 | SSA def(clean) | -| string.swift:156:7:156:7 | SSA def(tainted) | string.swift:159:13:159:13 | tainted | -| string.swift:156:17:156:25 | call to source2() | string.swift:156:7:156:7 | SSA def(tainted) | -| string.swift:158:13:158:13 | [post] clean | string.swift:161:13:161:13 | clean | -| string.swift:158:13:158:13 | clean | string.swift:161:13:161:13 | clean | -| string.swift:159:13:159:13 | [post] tainted | string.swift:162:21:162:21 | tainted | -| string.swift:159:13:159:13 | tainted | string.swift:162:21:162:21 | tainted | -| string.swift:161:13:161:13 | [post] clean | string.swift:161:21:161:21 | clean | -| string.swift:161:13:161:13 | clean | string.swift:161:13:161:21 | ... .+(_:_:) ... | -| string.swift:161:13:161:13 | clean | string.swift:161:21:161:21 | clean | -| string.swift:161:21:161:21 | [post] clean | string.swift:162:13:162:13 | clean | -| string.swift:161:21:161:21 | clean | string.swift:161:13:161:21 | ... .+(_:_:) ... | -| string.swift:161:21:161:21 | clean | string.swift:162:13:162:13 | clean | -| string.swift:162:13:162:13 | [post] clean | string.swift:163:23:163:23 | clean | -| string.swift:162:13:162:13 | clean | string.swift:162:13:162:21 | ... .+(_:_:) ... | -| string.swift:162:13:162:13 | clean | string.swift:163:23:163:23 | clean | -| string.swift:162:21:162:21 | [post] tainted | string.swift:163:13:163:13 | tainted | -| string.swift:162:21:162:21 | tainted | string.swift:162:13:162:21 | ... .+(_:_:) ... | -| string.swift:162:21:162:21 | tainted | string.swift:163:13:163:13 | tainted | -| string.swift:163:13:163:13 | [post] tainted | string.swift:164:13:164:13 | tainted | -| string.swift:163:13:163:13 | tainted | string.swift:163:13:163:23 | ... .+(_:_:) ... | -| string.swift:163:13:163:13 | tainted | string.swift:164:13:164:13 | tainted | -| string.swift:163:23:163:23 | [post] clean | string.swift:166:19:166:19 | clean | -| string.swift:163:23:163:23 | clean | string.swift:163:13:163:23 | ... .+(_:_:) ... | -| string.swift:163:23:163:23 | clean | string.swift:166:19:166:19 | clean | -| string.swift:164:13:164:13 | [post] tainted | string.swift:164:23:164:23 | tainted | -| string.swift:164:13:164:13 | tainted | string.swift:164:13:164:23 | ... .+(_:_:) ... | -| string.swift:164:13:164:13 | tainted | string.swift:164:23:164:23 | tainted | -| string.swift:164:23:164:23 | [post] tainted | string.swift:167:19:167:19 | tainted | -| string.swift:164:23:164:23 | tainted | string.swift:164:13:164:23 | ... .+(_:_:) ... | -| string.swift:164:23:164:23 | tainted | string.swift:167:19:167:19 | tainted | -| string.swift:166:13:166:13 | > | string.swift:166:13:166:19 | ... .+(_:_:) ... | -| string.swift:166:13:166:19 | ... .+(_:_:) ... | string.swift:166:13:166:27 | ... .+(_:_:) ... | -| string.swift:166:19:166:19 | [post] clean | string.swift:169:13:169:13 | clean | -| string.swift:166:19:166:19 | clean | string.swift:166:13:166:19 | ... .+(_:_:) ... | -| string.swift:166:19:166:19 | clean | string.swift:169:13:169:13 | clean | -| string.swift:166:27:166:27 | < | string.swift:166:13:166:27 | ... .+(_:_:) ... | -| string.swift:167:13:167:13 | > | string.swift:167:13:167:19 | ... .+(_:_:) ... | -| string.swift:167:13:167:19 | ... .+(_:_:) ... | string.swift:167:13:167:29 | ... .+(_:_:) ... | -| string.swift:167:19:167:19 | [post] tainted | string.swift:170:29:170:29 | tainted | -| string.swift:167:19:167:19 | tainted | string.swift:167:13:167:19 | ... .+(_:_:) ... | -| string.swift:167:19:167:19 | tainted | string.swift:170:29:170:29 | tainted | -| string.swift:167:29:167:29 | < | string.swift:167:13:167:29 | ... .+(_:_:) ... | -| string.swift:169:13:169:13 | [post] clean | string.swift:169:29:169:29 | clean | -| string.swift:169:13:169:13 | clean | string.swift:169:13:169:34 | call to appending(_:) | -| string.swift:169:13:169:13 | clean | string.swift:169:29:169:29 | clean | -| string.swift:169:29:169:29 | [post] clean | string.swift:170:13:170:13 | clean | -| string.swift:169:29:169:29 | clean | string.swift:169:13:169:34 | call to appending(_:) | -| string.swift:169:29:169:29 | clean | string.swift:170:13:170:13 | clean | -| string.swift:170:13:170:13 | [post] clean | string.swift:171:31:171:31 | clean | -| string.swift:170:13:170:13 | clean | string.swift:170:13:170:36 | call to appending(_:) | -| string.swift:170:13:170:13 | clean | string.swift:171:31:171:31 | clean | -| string.swift:170:29:170:29 | [post] tainted | string.swift:171:13:171:13 | tainted | -| string.swift:170:29:170:29 | tainted | string.swift:170:13:170:36 | call to appending(_:) | -| string.swift:170:29:170:29 | tainted | string.swift:171:13:171:13 | tainted | -| string.swift:171:13:171:13 | [post] tainted | string.swift:172:13:172:13 | tainted | -| string.swift:171:13:171:13 | tainted | string.swift:171:13:171:36 | call to appending(_:) | -| string.swift:171:13:171:13 | tainted | string.swift:172:13:172:13 | tainted | -| string.swift:171:31:171:31 | clean | string.swift:171:13:171:36 | call to appending(_:) | -| string.swift:172:13:172:13 | [post] tainted | string.swift:172:31:172:31 | tainted | -| string.swift:172:13:172:13 | tainted | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:172:13:172:13 | tainted | string.swift:172:31:172:31 | tainted | -| string.swift:172:31:172:31 | tainted | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:174:7:174:7 | SSA def(str) | string.swift:175:13:175:13 | str | -| string.swift:174:13:174:13 | abc | string.swift:174:7:174:7 | SSA def(str) | -| string.swift:175:13:175:13 | [post] str | string.swift:176:3:176:3 | str | -| string.swift:175:13:175:13 | str | string.swift:176:3:176:3 | str | -| string.swift:176:3:176:3 | &... | string.swift:177:13:177:13 | str | -| string.swift:176:3:176:3 | [post] &... | string.swift:177:13:177:13 | str | -| string.swift:176:3:176:3 | str | string.swift:176:3:176:3 | &... | -| string.swift:177:13:177:13 | [post] str | string.swift:178:3:178:3 | str | -| string.swift:177:13:177:13 | str | string.swift:178:3:178:3 | str | -| string.swift:178:3:178:3 | &... | string.swift:179:13:179:13 | str | -| string.swift:178:3:178:3 | [post] &... | string.swift:179:13:179:13 | str | -| string.swift:178:3:178:3 | str | string.swift:178:3:178:3 | &... | -| string.swift:181:7:181:7 | SSA def(str2) | string.swift:182:13:182:13 | str2 | -| string.swift:181:14:181:14 | abc | string.swift:181:7:181:7 | SSA def(str2) | -| string.swift:182:13:182:13 | [post] str2 | string.swift:183:3:183:3 | str2 | -| string.swift:182:13:182:13 | str2 | string.swift:183:3:183:3 | str2 | -| string.swift:183:3:183:3 | &... | string.swift:184:13:184:13 | str2 | -| string.swift:183:3:183:3 | [post] &... | string.swift:184:13:184:13 | str2 | -| string.swift:183:3:183:3 | str2 | string.swift:183:3:183:3 | &... | -| string.swift:183:15:183:15 | def | string.swift:183:3:183:3 | [post] &... | -| string.swift:184:13:184:13 | [post] str2 | string.swift:185:3:185:3 | str2 | -| string.swift:184:13:184:13 | str2 | string.swift:185:3:185:3 | str2 | -| string.swift:185:3:185:3 | &... | string.swift:186:13:186:13 | str2 | -| string.swift:185:3:185:3 | [post] &... | string.swift:186:13:186:13 | str2 | -| string.swift:185:3:185:3 | str2 | string.swift:185:3:185:3 | &... | -| string.swift:185:15:185:23 | call to source2() | string.swift:185:3:185:3 | [post] &... | -| string.swift:188:7:188:7 | SSA def(str3) | string.swift:189:13:189:13 | str3 | -| string.swift:188:14:188:14 | abc | string.swift:188:7:188:7 | SSA def(str3) | -| string.swift:189:13:189:13 | [post] str3 | string.swift:190:3:190:3 | str3 | -| string.swift:189:13:189:13 | str3 | string.swift:190:3:190:3 | str3 | -| string.swift:190:3:190:3 | &... | string.swift:191:13:191:13 | str3 | -| string.swift:190:3:190:3 | [post] &... | string.swift:191:13:191:13 | str3 | -| string.swift:190:3:190:3 | str3 | string.swift:190:3:190:3 | &... | -| string.swift:190:27:190:27 | def | string.swift:190:3:190:3 | [post] &... | -| string.swift:191:13:191:13 | [post] str3 | string.swift:192:3:192:3 | str3 | -| string.swift:191:13:191:13 | str3 | string.swift:192:3:192:3 | str3 | -| string.swift:192:3:192:3 | &... | string.swift:193:13:193:13 | str3 | -| string.swift:192:3:192:3 | [post] &... | string.swift:193:13:193:13 | str3 | -| string.swift:192:3:192:3 | str3 | string.swift:192:3:192:3 | &... | -| string.swift:192:27:192:35 | call to source2() | string.swift:192:3:192:3 | [post] &... | -| string.swift:195:7:195:7 | SSA def(str4) | string.swift:196:13:196:13 | str4 | -| string.swift:195:14:195:14 | abc | string.swift:195:7:195:7 | SSA def(str4) | -| string.swift:196:13:196:13 | [post] str4 | string.swift:197:3:197:3 | str4 | -| string.swift:196:13:196:13 | str4 | string.swift:197:3:197:3 | str4 | -| string.swift:197:3:197:3 | &... | string.swift:198:13:198:13 | str4 | -| string.swift:197:3:197:3 | [post] &... | string.swift:198:13:198:13 | str4 | -| string.swift:197:3:197:3 | str4 | string.swift:197:3:197:3 | &... | -| string.swift:197:14:197:14 | def | string.swift:197:3:197:3 | [post] &... | -| string.swift:198:13:198:13 | [post] str4 | string.swift:199:3:199:3 | str4 | -| string.swift:198:13:198:13 | str4 | string.swift:199:3:199:3 | str4 | -| string.swift:199:3:199:3 | &... | string.swift:200:13:200:13 | str4 | -| string.swift:199:3:199:3 | [post] &... | string.swift:200:13:200:13 | str4 | -| string.swift:199:3:199:3 | str4 | string.swift:199:3:199:3 | &... | -| string.swift:199:14:199:22 | call to source2() | string.swift:199:3:199:3 | [post] &... | -| string.swift:202:7:202:7 | SSA def(str5) | string.swift:203:13:203:13 | str5 | -| string.swift:202:14:202:14 | abc | string.swift:202:7:202:7 | SSA def(str5) | -| string.swift:203:13:203:13 | [post] str5 | string.swift:204:3:204:3 | str5 | -| string.swift:203:13:203:13 | str5 | string.swift:204:3:204:3 | str5 | -| string.swift:204:3:204:3 | &... | string.swift:204:38:204:38 | str5 | -| string.swift:204:3:204:3 | [post] &... | string.swift:204:38:204:38 | str5 | -| string.swift:204:3:204:3 | str5 | string.swift:204:3:204:3 | &... | -| string.swift:204:27:204:27 | abc | string.swift:204:3:204:3 | [post] &... | -| string.swift:204:38:204:38 | [post] str5 | string.swift:205:13:205:13 | str5 | -| string.swift:204:38:204:38 | str5 | string.swift:205:13:205:13 | str5 | -| string.swift:205:13:205:13 | [post] str5 | string.swift:206:3:206:3 | str5 | -| string.swift:205:13:205:13 | str5 | string.swift:206:3:206:3 | str5 | -| string.swift:206:3:206:3 | &... | string.swift:206:42:206:42 | str5 | -| string.swift:206:3:206:3 | [post] &... | string.swift:206:42:206:42 | str5 | -| string.swift:206:3:206:3 | str5 | string.swift:206:3:206:3 | &... | -| string.swift:206:27:206:35 | call to source2() | string.swift:206:3:206:3 | [post] &... | -| string.swift:206:42:206:42 | [post] str5 | string.swift:207:13:207:13 | str5 | -| string.swift:206:42:206:42 | str5 | string.swift:207:13:207:13 | str5 | -| string.swift:211:7:211:7 | SSA def(clean) | string.swift:215:20:215:20 | clean | -| string.swift:211:15:211:15 | | string.swift:211:7:211:7 | SSA def(clean) | -| string.swift:212:7:212:7 | SSA def(tainted) | string.swift:216:20:216:20 | tainted | -| string.swift:212:17:212:25 | call to source2() | string.swift:212:7:212:7 | SSA def(tainted) | -| string.swift:213:7:213:7 | SSA def(taintedInt) | string.swift:217:20:217:20 | taintedInt | -| string.swift:213:20:213:27 | call to source() | string.swift:213:7:213:7 | SSA def(taintedInt) | -| string.swift:215:20:215:20 | [post] clean | string.swift:227:31:227:31 | clean | -| string.swift:215:20:215:20 | clean | string.swift:215:13:215:25 | call to String.init(_:) | -| string.swift:215:20:215:20 | clean | string.swift:227:31:227:31 | clean | -| string.swift:216:20:216:20 | [post] tainted | string.swift:219:28:219:28 | tainted | -| string.swift:216:20:216:20 | tainted | string.swift:216:13:216:27 | call to String.init(_:) | -| string.swift:216:20:216:20 | tainted | string.swift:219:28:219:28 | tainted | -| string.swift:217:20:217:20 | [post] taintedInt | string.swift:225:46:225:46 | taintedInt | -| string.swift:217:20:217:20 | taintedInt | string.swift:217:13:217:30 | call to String.init(_:) | -| string.swift:217:20:217:20 | taintedInt | string.swift:225:46:225:46 | taintedInt | -| string.swift:219:28:219:28 | [post] tainted | string.swift:220:28:220:28 | tainted | -| string.swift:219:28:219:28 | tainted | string.swift:219:13:219:44 | call to String.init(format:_:) | -| string.swift:219:28:219:28 | tainted | string.swift:220:28:220:28 | tainted | -| string.swift:220:28:220:28 | [post] tainted | string.swift:221:28:221:28 | tainted | -| string.swift:220:28:220:28 | tainted | string.swift:220:13:220:50 | call to String.init(format:arguments:) | -| string.swift:220:28:220:28 | tainted | string.swift:221:28:221:28 | tainted | -| string.swift:220:48:220:49 | [...] | string.swift:220:13:220:50 | call to String.init(format:arguments:) | -| string.swift:221:28:221:28 | [post] tainted | string.swift:222:28:222:28 | tainted | -| string.swift:221:28:221:28 | tainted | string.swift:221:13:221:57 | call to String.init(format:locale:_:) | -| string.swift:221:28:221:28 | tainted | string.swift:222:28:222:28 | tainted | -| string.swift:222:28:222:28 | [post] tainted | string.swift:223:46:223:46 | tainted | -| string.swift:222:28:222:28 | tainted | string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | -| string.swift:222:28:222:28 | tainted | string.swift:223:46:223:46 | tainted | -| string.swift:223:46:223:46 | [post] tainted | string.swift:224:34:224:34 | tainted | -| string.swift:223:46:223:46 | tainted | string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | -| string.swift:223:46:223:46 | tainted | string.swift:224:34:224:34 | tainted | -| string.swift:223:55:223:61 | [...] | string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | -| string.swift:224:28:224:28 | %s | string.swift:224:13:224:41 | call to String.init(format:_:) | -| string.swift:224:34:224:34 | tainted | string.swift:228:31:228:31 | tainted | -| string.swift:225:28:225:28 | %i %i %i | string.swift:225:13:225:56 | call to String.init(format:_:) | -| string.swift:227:31:227:31 | [post] clean | string.swift:253:13:253:13 | clean | -| string.swift:227:31:227:31 | clean | string.swift:227:13:227:46 | call to String.init(repeating:count:) | -| string.swift:227:31:227:31 | clean | string.swift:253:13:253:13 | clean | -| string.swift:228:31:228:31 | [post] tainted | string.swift:230:13:230:13 | tainted | -| string.swift:228:31:228:31 | tainted | string.swift:228:13:228:48 | call to String.init(repeating:count:) | -| string.swift:228:31:228:31 | tainted | string.swift:230:13:230:13 | tainted | -| string.swift:230:13:230:13 | [post] tainted | string.swift:231:13:231:13 | tainted | -| string.swift:230:13:230:13 | tainted | string.swift:230:13:230:33 | call to dropFirst(_:) | -| string.swift:230:13:230:13 | tainted | string.swift:231:13:231:13 | tainted | -| string.swift:231:13:231:13 | [post] tainted | string.swift:232:13:232:13 | tainted | -| string.swift:231:13:231:13 | tainted | string.swift:231:13:231:32 | call to dropLast(_:) | -| string.swift:231:13:231:13 | tainted | string.swift:232:13:232:13 | tainted | -| string.swift:232:13:232:13 | [post] tainted | string.swift:232:37:232:37 | tainted | -| string.swift:232:13:232:13 | tainted | string.swift:232:13:232:55 | call to substring(from:) | -| string.swift:232:13:232:13 | tainted | string.swift:232:37:232:37 | tainted | -| string.swift:232:37:232:37 | [post] tainted | string.swift:234:13:234:13 | tainted | -| string.swift:232:37:232:37 | tainted | string.swift:234:13:234:13 | tainted | -| string.swift:234:13:234:13 | [post] tainted | string.swift:235:13:235:13 | tainted | -| string.swift:234:13:234:13 | tainted | string.swift:234:13:234:32 | call to lowercased() | -| string.swift:234:13:234:13 | tainted | string.swift:235:13:235:13 | tainted | +| string.swift:149:18:149:18 | &... | string.swift:149:26:149:26 | $interpolation | +| string.swift:149:18:149:18 | [post] &... | string.swift:149:26:149:26 | $interpolation | +| string.swift:149:26:149:26 | $interpolation | string.swift:149:26:149:26 | &... | +| string.swift:149:26:149:26 | &... | string.swift:149:26:149:26 | [post] &... | +| string.swift:149:26:149:26 | &... | string.swift:149:27:149:27 | [post] y | +| string.swift:149:26:149:26 | &... | string.swift:149:29:149:29 | $interpolation | +| string.swift:149:26:149:26 | [post] &... | string.swift:149:29:149:29 | $interpolation | +| string.swift:149:27:149:27 | [post] y | string.swift:151:16:151:16 | y | +| string.swift:149:27:149:27 | y | string.swift:149:26:149:26 | [post] &... | +| string.swift:149:27:149:27 | y | string.swift:149:27:149:27 | [post] y | +| string.swift:149:27:149:27 | y | string.swift:151:16:151:16 | y | +| string.swift:149:29:149:29 | | string.swift:149:29:149:29 | [post] | +| string.swift:149:29:149:29 | | string.swift:149:29:149:29 | [post] &... | +| string.swift:149:29:149:29 | $interpolation | string.swift:149:29:149:29 | &... | +| string.swift:149:29:149:29 | &... | string.swift:149:13:149:13 | TapExpr | +| string.swift:149:29:149:29 | &... | string.swift:149:29:149:29 | [post] | +| string.swift:149:29:149:29 | &... | string.swift:149:29:149:29 | [post] &... | +| string.swift:149:29:149:29 | [post] &... | string.swift:149:13:149:13 | TapExpr | +| string.swift:151:13:151:13 | | string.swift:151:13:151:13 | [post] | +| string.swift:151:13:151:13 | | string.swift:151:14:151:14 | [post] &... | +| string.swift:151:13:151:13 | SSA def($interpolation) | string.swift:151:14:151:14 | SSA phi($interpolation) | +| string.swift:151:13:151:13 | TapExpr | string.swift:151:13:151:13 | "..." | +| string.swift:151:14:151:14 | $interpolation | string.swift:151:14:151:14 | &... | +| string.swift:151:14:151:14 | &... | string.swift:151:13:151:13 | [post] | +| string.swift:151:14:151:14 | &... | string.swift:151:14:151:14 | [post] &... | +| string.swift:151:14:151:14 | &... | string.swift:151:15:151:15 | $interpolation | +| string.swift:151:14:151:14 | SSA phi($interpolation) | string.swift:151:14:151:14 | $interpolation | +| string.swift:151:14:151:14 | [post] &... | string.swift:151:15:151:15 | $interpolation | +| string.swift:151:15:151:15 | $interpolation | string.swift:151:15:151:15 | &... | +| string.swift:151:15:151:15 | &... | string.swift:151:15:151:15 | [post] &... | +| string.swift:151:15:151:15 | &... | string.swift:151:16:151:16 | [post] y | +| string.swift:151:15:151:15 | &... | string.swift:151:18:151:18 | $interpolation | +| string.swift:151:15:151:15 | [post] &... | string.swift:151:18:151:18 | $interpolation | +| string.swift:151:16:151:16 | y | string.swift:151:15:151:15 | [post] &... | +| string.swift:151:16:151:16 | y | string.swift:151:16:151:16 | [post] y | +| string.swift:151:18:151:18 | world | string.swift:151:18:151:18 | [post] world | +| string.swift:151:18:151:18 | world | string.swift:151:18:151:18 | [post] &... | +| string.swift:151:18:151:18 | $interpolation | string.swift:151:18:151:18 | &... | +| string.swift:151:18:151:18 | &... | string.swift:151:18:151:18 | [post] world | +| string.swift:151:18:151:18 | &... | string.swift:151:18:151:18 | [post] &... | +| string.swift:151:18:151:18 | &... | string.swift:151:26:151:26 | $interpolation | +| string.swift:151:18:151:18 | [post] &... | string.swift:151:26:151:26 | $interpolation | +| string.swift:151:26:151:26 | $interpolation | string.swift:151:26:151:26 | &... | +| string.swift:151:26:151:26 | &... | string.swift:151:26:151:26 | [post] &... | +| string.swift:151:26:151:26 | &... | string.swift:151:27:151:27 | [post] x | +| string.swift:151:26:151:26 | &... | string.swift:151:29:151:29 | $interpolation | +| string.swift:151:26:151:26 | [post] &... | string.swift:151:29:151:29 | $interpolation | +| string.swift:151:27:151:27 | x | string.swift:151:26:151:26 | [post] &... | +| string.swift:151:27:151:27 | x | string.swift:151:27:151:27 | [post] x | +| string.swift:151:29:151:29 | | string.swift:151:29:151:29 | [post] | +| string.swift:151:29:151:29 | | string.swift:151:29:151:29 | [post] &... | +| string.swift:151:29:151:29 | $interpolation | string.swift:151:29:151:29 | &... | +| string.swift:151:29:151:29 | &... | string.swift:151:13:151:13 | TapExpr | +| string.swift:151:29:151:29 | &... | string.swift:151:29:151:29 | [post] | +| string.swift:151:29:151:29 | &... | string.swift:151:29:151:29 | [post] &... | +| string.swift:151:29:151:29 | [post] &... | string.swift:151:13:151:13 | TapExpr | +| string.swift:153:3:153:7 | SSA def(x) | string.swift:154:16:154:16 | x | +| string.swift:153:7:153:7 | 0 | string.swift:153:3:153:7 | SSA def(x) | +| string.swift:154:13:154:13 | | string.swift:154:13:154:13 | [post] | +| string.swift:154:13:154:13 | | string.swift:154:14:154:14 | [post] &... | +| string.swift:154:13:154:13 | SSA def($interpolation) | string.swift:154:14:154:14 | SSA phi($interpolation) | +| string.swift:154:13:154:13 | TapExpr | string.swift:154:13:154:13 | "..." | +| string.swift:154:14:154:14 | $interpolation | string.swift:154:14:154:14 | &... | +| string.swift:154:14:154:14 | &... | string.swift:154:13:154:13 | [post] | +| string.swift:154:14:154:14 | &... | string.swift:154:14:154:14 | [post] &... | +| string.swift:154:14:154:14 | &... | string.swift:154:15:154:15 | $interpolation | +| string.swift:154:14:154:14 | SSA phi($interpolation) | string.swift:154:14:154:14 | $interpolation | +| string.swift:154:14:154:14 | [post] &... | string.swift:154:15:154:15 | $interpolation | +| string.swift:154:15:154:15 | $interpolation | string.swift:154:15:154:15 | &... | +| string.swift:154:15:154:15 | &... | string.swift:154:15:154:15 | [post] &... | +| string.swift:154:15:154:15 | &... | string.swift:154:16:154:16 | [post] x | +| string.swift:154:15:154:15 | &... | string.swift:154:18:154:18 | $interpolation | +| string.swift:154:15:154:15 | [post] &... | string.swift:154:18:154:18 | $interpolation | +| string.swift:154:16:154:16 | x | string.swift:154:15:154:15 | [post] &... | +| string.swift:154:16:154:16 | x | string.swift:154:16:154:16 | [post] x | +| string.swift:154:18:154:18 | | string.swift:154:18:154:18 | [post] | +| string.swift:154:18:154:18 | | string.swift:154:18:154:18 | [post] &... | +| string.swift:154:18:154:18 | $interpolation | string.swift:154:18:154:18 | &... | +| string.swift:154:18:154:18 | &... | string.swift:154:13:154:13 | TapExpr | +| string.swift:154:18:154:18 | &... | string.swift:154:18:154:18 | [post] | +| string.swift:154:18:154:18 | &... | string.swift:154:18:154:18 | [post] &... | +| string.swift:154:18:154:18 | [post] &... | string.swift:154:13:154:13 | TapExpr | +| string.swift:160:7:160:7 | SSA def(clean) | string.swift:163:13:163:13 | clean | +| string.swift:160:15:160:15 | abcdef | string.swift:160:7:160:7 | SSA def(clean) | +| string.swift:161:7:161:7 | SSA def(tainted) | string.swift:164:13:164:13 | tainted | +| string.swift:161:17:161:25 | call to source2() | string.swift:161:7:161:7 | SSA def(tainted) | +| string.swift:163:13:163:13 | [post] clean | string.swift:166:13:166:13 | clean | +| string.swift:163:13:163:13 | clean | string.swift:166:13:166:13 | clean | +| string.swift:164:13:164:13 | [post] tainted | string.swift:167:21:167:21 | tainted | +| string.swift:164:13:164:13 | tainted | string.swift:167:21:167:21 | tainted | +| string.swift:166:13:166:13 | [post] clean | string.swift:166:21:166:21 | clean | +| string.swift:166:13:166:13 | clean | string.swift:166:13:166:21 | ... .+(_:_:) ... | +| string.swift:166:13:166:13 | clean | string.swift:166:21:166:21 | clean | +| string.swift:166:21:166:21 | [post] clean | string.swift:167:13:167:13 | clean | +| string.swift:166:21:166:21 | clean | string.swift:166:13:166:21 | ... .+(_:_:) ... | +| string.swift:166:21:166:21 | clean | string.swift:167:13:167:13 | clean | +| string.swift:167:13:167:13 | [post] clean | string.swift:168:23:168:23 | clean | +| string.swift:167:13:167:13 | clean | string.swift:167:13:167:21 | ... .+(_:_:) ... | +| string.swift:167:13:167:13 | clean | string.swift:168:23:168:23 | clean | +| string.swift:167:21:167:21 | [post] tainted | string.swift:168:13:168:13 | tainted | +| string.swift:167:21:167:21 | tainted | string.swift:167:13:167:21 | ... .+(_:_:) ... | +| string.swift:167:21:167:21 | tainted | string.swift:168:13:168:13 | tainted | +| string.swift:168:13:168:13 | [post] tainted | string.swift:169:13:169:13 | tainted | +| string.swift:168:13:168:13 | tainted | string.swift:168:13:168:23 | ... .+(_:_:) ... | +| string.swift:168:13:168:13 | tainted | string.swift:169:13:169:13 | tainted | +| string.swift:168:23:168:23 | [post] clean | string.swift:171:19:171:19 | clean | +| string.swift:168:23:168:23 | clean | string.swift:168:13:168:23 | ... .+(_:_:) ... | +| string.swift:168:23:168:23 | clean | string.swift:171:19:171:19 | clean | +| string.swift:169:13:169:13 | [post] tainted | string.swift:169:23:169:23 | tainted | +| string.swift:169:13:169:13 | tainted | string.swift:169:13:169:23 | ... .+(_:_:) ... | +| string.swift:169:13:169:13 | tainted | string.swift:169:23:169:23 | tainted | +| string.swift:169:23:169:23 | [post] tainted | string.swift:172:19:172:19 | tainted | +| string.swift:169:23:169:23 | tainted | string.swift:169:13:169:23 | ... .+(_:_:) ... | +| string.swift:169:23:169:23 | tainted | string.swift:172:19:172:19 | tainted | +| string.swift:171:13:171:13 | > | string.swift:171:13:171:19 | ... .+(_:_:) ... | +| string.swift:171:13:171:19 | ... .+(_:_:) ... | string.swift:171:13:171:27 | ... .+(_:_:) ... | +| string.swift:171:19:171:19 | [post] clean | string.swift:174:13:174:13 | clean | +| string.swift:171:19:171:19 | clean | string.swift:171:13:171:19 | ... .+(_:_:) ... | +| string.swift:171:19:171:19 | clean | string.swift:174:13:174:13 | clean | +| string.swift:171:27:171:27 | < | string.swift:171:13:171:27 | ... .+(_:_:) ... | +| string.swift:172:13:172:13 | > | string.swift:172:13:172:19 | ... .+(_:_:) ... | +| string.swift:172:13:172:19 | ... .+(_:_:) ... | string.swift:172:13:172:29 | ... .+(_:_:) ... | +| string.swift:172:19:172:19 | [post] tainted | string.swift:175:29:175:29 | tainted | +| string.swift:172:19:172:19 | tainted | string.swift:172:13:172:19 | ... .+(_:_:) ... | +| string.swift:172:19:172:19 | tainted | string.swift:175:29:175:29 | tainted | +| string.swift:172:29:172:29 | < | string.swift:172:13:172:29 | ... .+(_:_:) ... | +| string.swift:174:13:174:13 | [post] clean | string.swift:174:29:174:29 | clean | +| string.swift:174:13:174:13 | clean | string.swift:174:13:174:34 | call to appending(_:) | +| string.swift:174:13:174:13 | clean | string.swift:174:29:174:29 | clean | +| string.swift:174:29:174:29 | [post] clean | string.swift:175:13:175:13 | clean | +| string.swift:174:29:174:29 | clean | string.swift:174:13:174:34 | call to appending(_:) | +| string.swift:174:29:174:29 | clean | string.swift:175:13:175:13 | clean | +| string.swift:175:13:175:13 | [post] clean | string.swift:176:31:176:31 | clean | +| string.swift:175:13:175:13 | clean | string.swift:175:13:175:36 | call to appending(_:) | +| string.swift:175:13:175:13 | clean | string.swift:176:31:176:31 | clean | +| string.swift:175:29:175:29 | [post] tainted | string.swift:176:13:176:13 | tainted | +| string.swift:175:29:175:29 | tainted | string.swift:175:13:175:36 | call to appending(_:) | +| string.swift:175:29:175:29 | tainted | string.swift:176:13:176:13 | tainted | +| string.swift:176:13:176:13 | [post] tainted | string.swift:177:13:177:13 | tainted | +| string.swift:176:13:176:13 | tainted | string.swift:176:13:176:36 | call to appending(_:) | +| string.swift:176:13:176:13 | tainted | string.swift:177:13:177:13 | tainted | +| string.swift:176:31:176:31 | clean | string.swift:176:13:176:36 | call to appending(_:) | +| string.swift:177:13:177:13 | [post] tainted | string.swift:177:31:177:31 | tainted | +| string.swift:177:13:177:13 | tainted | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:177:13:177:13 | tainted | string.swift:177:31:177:31 | tainted | +| string.swift:177:31:177:31 | tainted | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:179:7:179:7 | SSA def(str) | string.swift:180:13:180:13 | str | +| string.swift:179:13:179:13 | abc | string.swift:179:7:179:7 | SSA def(str) | +| string.swift:180:13:180:13 | [post] str | string.swift:181:3:181:3 | str | +| string.swift:180:13:180:13 | str | string.swift:181:3:181:3 | str | +| string.swift:181:3:181:3 | &... | string.swift:182:13:182:13 | str | +| string.swift:181:3:181:3 | [post] &... | string.swift:182:13:182:13 | str | +| string.swift:181:3:181:3 | str | string.swift:181:3:181:3 | &... | +| string.swift:182:13:182:13 | [post] str | string.swift:183:3:183:3 | str | +| string.swift:182:13:182:13 | str | string.swift:183:3:183:3 | str | +| string.swift:183:3:183:3 | &... | string.swift:184:13:184:13 | str | +| string.swift:183:3:183:3 | [post] &... | string.swift:184:13:184:13 | str | +| string.swift:183:3:183:3 | str | string.swift:183:3:183:3 | &... | +| string.swift:186:7:186:7 | SSA def(str2) | string.swift:187:13:187:13 | str2 | +| string.swift:186:14:186:14 | abc | string.swift:186:7:186:7 | SSA def(str2) | +| string.swift:187:13:187:13 | [post] str2 | string.swift:188:3:188:3 | str2 | +| string.swift:187:13:187:13 | str2 | string.swift:188:3:188:3 | str2 | +| string.swift:188:3:188:3 | &... | string.swift:189:13:189:13 | str2 | +| string.swift:188:3:188:3 | [post] &... | string.swift:189:13:189:13 | str2 | +| string.swift:188:3:188:3 | str2 | string.swift:188:3:188:3 | &... | +| string.swift:188:15:188:15 | def | string.swift:188:3:188:3 | [post] &... | +| string.swift:189:13:189:13 | [post] str2 | string.swift:190:3:190:3 | str2 | +| string.swift:189:13:189:13 | str2 | string.swift:190:3:190:3 | str2 | +| string.swift:190:3:190:3 | &... | string.swift:191:13:191:13 | str2 | +| string.swift:190:3:190:3 | [post] &... | string.swift:191:13:191:13 | str2 | +| string.swift:190:3:190:3 | str2 | string.swift:190:3:190:3 | &... | +| string.swift:190:15:190:23 | call to source2() | string.swift:190:3:190:3 | [post] &... | +| string.swift:193:7:193:7 | SSA def(str3) | string.swift:194:13:194:13 | str3 | +| string.swift:193:14:193:14 | abc | string.swift:193:7:193:7 | SSA def(str3) | +| string.swift:194:13:194:13 | [post] str3 | string.swift:195:3:195:3 | str3 | +| string.swift:194:13:194:13 | str3 | string.swift:195:3:195:3 | str3 | +| string.swift:195:3:195:3 | &... | string.swift:196:13:196:13 | str3 | +| string.swift:195:3:195:3 | [post] &... | string.swift:196:13:196:13 | str3 | +| string.swift:195:3:195:3 | str3 | string.swift:195:3:195:3 | &... | +| string.swift:195:27:195:27 | def | string.swift:195:3:195:3 | [post] &... | +| string.swift:196:13:196:13 | [post] str3 | string.swift:197:3:197:3 | str3 | +| string.swift:196:13:196:13 | str3 | string.swift:197:3:197:3 | str3 | +| string.swift:197:3:197:3 | &... | string.swift:198:13:198:13 | str3 | +| string.swift:197:3:197:3 | [post] &... | string.swift:198:13:198:13 | str3 | +| string.swift:197:3:197:3 | str3 | string.swift:197:3:197:3 | &... | +| string.swift:197:27:197:35 | call to source2() | string.swift:197:3:197:3 | [post] &... | +| string.swift:200:7:200:7 | SSA def(str4) | string.swift:201:13:201:13 | str4 | +| string.swift:200:14:200:14 | abc | string.swift:200:7:200:7 | SSA def(str4) | +| string.swift:201:13:201:13 | [post] str4 | string.swift:202:3:202:3 | str4 | +| string.swift:201:13:201:13 | str4 | string.swift:202:3:202:3 | str4 | +| string.swift:202:3:202:3 | &... | string.swift:203:13:203:13 | str4 | +| string.swift:202:3:202:3 | [post] &... | string.swift:203:13:203:13 | str4 | +| string.swift:202:3:202:3 | str4 | string.swift:202:3:202:3 | &... | +| string.swift:202:14:202:14 | def | string.swift:202:3:202:3 | [post] &... | +| string.swift:203:13:203:13 | [post] str4 | string.swift:204:3:204:3 | str4 | +| string.swift:203:13:203:13 | str4 | string.swift:204:3:204:3 | str4 | +| string.swift:204:3:204:3 | &... | string.swift:205:13:205:13 | str4 | +| string.swift:204:3:204:3 | [post] &... | string.swift:205:13:205:13 | str4 | +| string.swift:204:3:204:3 | str4 | string.swift:204:3:204:3 | &... | +| string.swift:204:14:204:22 | call to source2() | string.swift:204:3:204:3 | [post] &... | +| string.swift:207:7:207:7 | SSA def(str5) | string.swift:208:13:208:13 | str5 | +| string.swift:207:14:207:14 | abc | string.swift:207:7:207:7 | SSA def(str5) | +| string.swift:208:13:208:13 | [post] str5 | string.swift:209:3:209:3 | str5 | +| string.swift:208:13:208:13 | str5 | string.swift:209:3:209:3 | str5 | +| string.swift:209:3:209:3 | &... | string.swift:209:38:209:38 | str5 | +| string.swift:209:3:209:3 | [post] &... | string.swift:209:38:209:38 | str5 | +| string.swift:209:3:209:3 | str5 | string.swift:209:3:209:3 | &... | +| string.swift:209:27:209:27 | abc | string.swift:209:3:209:3 | [post] &... | +| string.swift:209:38:209:38 | [post] str5 | string.swift:210:13:210:13 | str5 | +| string.swift:209:38:209:38 | str5 | string.swift:210:13:210:13 | str5 | +| string.swift:210:13:210:13 | [post] str5 | string.swift:211:3:211:3 | str5 | +| string.swift:210:13:210:13 | str5 | string.swift:211:3:211:3 | str5 | +| string.swift:211:3:211:3 | &... | string.swift:211:42:211:42 | str5 | +| string.swift:211:3:211:3 | [post] &... | string.swift:211:42:211:42 | str5 | +| string.swift:211:3:211:3 | str5 | string.swift:211:3:211:3 | &... | +| string.swift:211:27:211:35 | call to source2() | string.swift:211:3:211:3 | [post] &... | +| string.swift:211:42:211:42 | [post] str5 | string.swift:212:13:212:13 | str5 | +| string.swift:211:42:211:42 | str5 | string.swift:212:13:212:13 | str5 | +| string.swift:216:7:216:7 | SSA def(clean) | string.swift:220:20:220:20 | clean | +| string.swift:216:15:216:15 | | string.swift:216:7:216:7 | SSA def(clean) | +| string.swift:217:7:217:7 | SSA def(tainted) | string.swift:221:20:221:20 | tainted | +| string.swift:217:17:217:25 | call to source2() | string.swift:217:7:217:7 | SSA def(tainted) | +| string.swift:218:7:218:7 | SSA def(taintedInt) | string.swift:222:20:222:20 | taintedInt | +| string.swift:218:20:218:27 | call to source() | string.swift:218:7:218:7 | SSA def(taintedInt) | +| string.swift:220:20:220:20 | [post] clean | string.swift:232:31:232:31 | clean | +| string.swift:220:20:220:20 | clean | string.swift:220:13:220:25 | call to String.init(_:) | +| string.swift:220:20:220:20 | clean | string.swift:232:31:232:31 | clean | +| string.swift:221:20:221:20 | [post] tainted | string.swift:224:28:224:28 | tainted | +| string.swift:221:20:221:20 | tainted | string.swift:221:13:221:27 | call to String.init(_:) | +| string.swift:221:20:221:20 | tainted | string.swift:224:28:224:28 | tainted | +| string.swift:222:20:222:20 | [post] taintedInt | string.swift:230:46:230:46 | taintedInt | +| string.swift:222:20:222:20 | taintedInt | string.swift:222:13:222:30 | call to String.init(_:) | +| string.swift:222:20:222:20 | taintedInt | string.swift:230:46:230:46 | taintedInt | +| string.swift:224:28:224:28 | [post] tainted | string.swift:225:28:225:28 | tainted | +| string.swift:224:28:224:28 | tainted | string.swift:224:13:224:44 | call to String.init(format:_:) | +| string.swift:224:28:224:28 | tainted | string.swift:225:28:225:28 | tainted | +| string.swift:225:28:225:28 | [post] tainted | string.swift:226:28:226:28 | tainted | +| string.swift:225:28:225:28 | tainted | string.swift:225:13:225:50 | call to String.init(format:arguments:) | +| string.swift:225:28:225:28 | tainted | string.swift:226:28:226:28 | tainted | +| string.swift:225:48:225:49 | [...] | string.swift:225:13:225:50 | call to String.init(format:arguments:) | +| string.swift:226:28:226:28 | [post] tainted | string.swift:227:28:227:28 | tainted | +| string.swift:226:28:226:28 | tainted | string.swift:226:13:226:57 | call to String.init(format:locale:_:) | +| string.swift:226:28:226:28 | tainted | string.swift:227:28:227:28 | tainted | +| string.swift:227:28:227:28 | [post] tainted | string.swift:228:46:228:46 | tainted | +| string.swift:227:28:227:28 | tainted | string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | +| string.swift:227:28:227:28 | tainted | string.swift:228:46:228:46 | tainted | +| string.swift:228:46:228:46 | [post] tainted | string.swift:229:34:229:34 | tainted | +| string.swift:228:46:228:46 | tainted | string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | +| string.swift:228:46:228:46 | tainted | string.swift:229:34:229:34 | tainted | +| string.swift:228:55:228:61 | [...] | string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | +| string.swift:229:28:229:28 | %s | string.swift:229:13:229:41 | call to String.init(format:_:) | +| string.swift:229:34:229:34 | tainted | string.swift:233:31:233:31 | tainted | +| string.swift:230:28:230:28 | %i %i %i | string.swift:230:13:230:56 | call to String.init(format:_:) | +| string.swift:232:31:232:31 | [post] clean | string.swift:258:13:258:13 | clean | +| string.swift:232:31:232:31 | clean | string.swift:232:13:232:46 | call to String.init(repeating:count:) | +| string.swift:232:31:232:31 | clean | string.swift:258:13:258:13 | clean | +| string.swift:233:31:233:31 | [post] tainted | string.swift:235:13:235:13 | tainted | +| string.swift:233:31:233:31 | tainted | string.swift:233:13:233:48 | call to String.init(repeating:count:) | +| string.swift:233:31:233:31 | tainted | string.swift:235:13:235:13 | tainted | | string.swift:235:13:235:13 | [post] tainted | string.swift:236:13:236:13 | tainted | -| string.swift:235:13:235:13 | tainted | string.swift:235:13:235:32 | call to uppercased() | +| string.swift:235:13:235:13 | tainted | string.swift:235:13:235:33 | call to dropFirst(_:) | | string.swift:235:13:235:13 | tainted | string.swift:236:13:236:13 | tainted | | string.swift:236:13:236:13 | [post] tainted | string.swift:237:13:237:13 | tainted | -| string.swift:236:13:236:13 | tainted | string.swift:236:13:236:41 | call to lowercased(with:) | +| string.swift:236:13:236:13 | tainted | string.swift:236:13:236:32 | call to dropLast(_:) | | string.swift:236:13:236:13 | tainted | string.swift:237:13:237:13 | tainted | -| string.swift:237:13:237:13 | [post] tainted | string.swift:238:13:238:13 | tainted | -| string.swift:237:13:237:13 | tainted | string.swift:237:13:237:41 | call to uppercased(with:) | -| string.swift:237:13:237:13 | tainted | string.swift:238:13:238:13 | tainted | -| string.swift:238:13:238:13 | [post] tainted | string.swift:239:13:239:13 | tainted | -| string.swift:238:13:238:13 | tainted | string.swift:238:13:238:42 | call to capitalized(with:) | -| string.swift:238:13:238:13 | tainted | string.swift:239:13:239:13 | tainted | -| string.swift:239:13:239:13 | [post] tainted | string.swift:241:13:241:13 | tainted | -| string.swift:239:13:239:13 | tainted | string.swift:239:13:239:30 | call to reversed() | -| string.swift:239:13:239:13 | tainted | string.swift:241:13:241:13 | tainted | +| string.swift:237:13:237:13 | [post] tainted | string.swift:237:37:237:37 | tainted | +| string.swift:237:13:237:13 | tainted | string.swift:237:13:237:55 | call to substring(from:) | +| string.swift:237:13:237:13 | tainted | string.swift:237:37:237:37 | tainted | +| string.swift:237:37:237:37 | [post] tainted | string.swift:239:13:239:13 | tainted | +| string.swift:237:37:237:37 | tainted | string.swift:239:13:239:13 | tainted | +| string.swift:239:13:239:13 | [post] tainted | string.swift:240:13:240:13 | tainted | +| string.swift:239:13:239:13 | tainted | string.swift:239:13:239:32 | call to lowercased() | +| string.swift:239:13:239:13 | tainted | string.swift:240:13:240:13 | tainted | +| string.swift:240:13:240:13 | [post] tainted | string.swift:241:13:241:13 | tainted | +| string.swift:240:13:240:13 | tainted | string.swift:240:13:240:32 | call to uppercased() | +| string.swift:240:13:240:13 | tainted | string.swift:241:13:241:13 | tainted | | string.swift:241:13:241:13 | [post] tainted | string.swift:242:13:242:13 | tainted | -| string.swift:241:13:241:13 | tainted | string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | +| string.swift:241:13:241:13 | tainted | string.swift:241:13:241:41 | call to lowercased(with:) | | string.swift:241:13:241:13 | tainted | string.swift:242:13:242:13 | tainted | -| string.swift:242:13:242:13 | [post] tainted | string.swift:245:13:245:13 | tainted | -| string.swift:242:13:242:13 | tainted | string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | -| string.swift:242:13:242:13 | tainted | string.swift:245:13:245:13 | tainted | -| string.swift:243:5:243:5 | SSA def(c) | string.swift:243:18:243:18 | c | -| string.swift:243:5:243:5 | c | string.swift:243:5:243:5 | SSA def(c) | -| string.swift:245:13:245:13 | [post] tainted | string.swift:246:13:246:13 | tainted | -| string.swift:245:13:245:13 | tainted | string.swift:245:13:245:68 | call to trimmingCharacters(in:) | -| string.swift:245:13:245:13 | tainted | string.swift:246:13:246:13 | tainted | +| string.swift:242:13:242:13 | [post] tainted | string.swift:243:13:243:13 | tainted | +| string.swift:242:13:242:13 | tainted | string.swift:242:13:242:41 | call to uppercased(with:) | +| string.swift:242:13:242:13 | tainted | string.swift:243:13:243:13 | tainted | +| string.swift:243:13:243:13 | [post] tainted | string.swift:244:13:244:13 | tainted | +| string.swift:243:13:243:13 | tainted | string.swift:243:13:243:42 | call to capitalized(with:) | +| string.swift:243:13:243:13 | tainted | string.swift:244:13:244:13 | tainted | +| string.swift:244:13:244:13 | [post] tainted | string.swift:246:13:246:13 | tainted | +| string.swift:244:13:244:13 | tainted | string.swift:244:13:244:30 | call to reversed() | +| string.swift:244:13:244:13 | tainted | string.swift:246:13:246:13 | tainted | | string.swift:246:13:246:13 | [post] tainted | string.swift:247:13:247:13 | tainted | -| string.swift:246:13:246:13 | tainted | string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | +| string.swift:246:13:246:13 | tainted | string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | | string.swift:246:13:246:13 | tainted | string.swift:247:13:247:13 | tainted | -| string.swift:246:52:246:52 | | string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | -| string.swift:247:13:247:13 | [post] tainted | string.swift:248:13:248:13 | tainted | -| string.swift:247:13:247:13 | tainted | string.swift:247:13:247:69 | call to components(separatedBy:) | -| string.swift:247:13:247:13 | tainted | string.swift:248:13:248:13 | tainted | -| string.swift:248:13:248:13 | [post] tainted | string.swift:249:13:249:13 | tainted | -| string.swift:248:13:248:13 | tainted | string.swift:248:13:248:69 | call to components(separatedBy:) | -| string.swift:248:13:248:13 | tainted | string.swift:249:13:249:13 | tainted | -| string.swift:248:13:248:69 | call to components(separatedBy:) | string.swift:248:13:248:72 | ...[...] | -| string.swift:249:13:249:13 | [post] tainted | string.swift:250:13:250:13 | tainted | -| string.swift:249:13:249:13 | tainted | string.swift:249:13:249:40 | call to folding(options:locale:) | -| string.swift:249:13:249:13 | tainted | string.swift:250:13:250:13 | tainted | +| string.swift:247:13:247:13 | [post] tainted | string.swift:250:13:250:13 | tainted | +| string.swift:247:13:247:13 | tainted | string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | +| string.swift:247:13:247:13 | tainted | string.swift:250:13:250:13 | tainted | +| string.swift:248:5:248:5 | SSA def(c) | string.swift:248:18:248:18 | c | +| string.swift:248:5:248:5 | c | string.swift:248:5:248:5 | SSA def(c) | | string.swift:250:13:250:13 | [post] tainted | string.swift:251:13:251:13 | tainted | -| string.swift:250:13:250:13 | tainted | string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | +| string.swift:250:13:250:13 | tainted | string.swift:250:13:250:68 | call to trimmingCharacters(in:) | | string.swift:250:13:250:13 | tainted | string.swift:251:13:251:13 | tainted | -| string.swift:251:13:251:13 | [post] tainted | string.swift:258:13:258:13 | tainted | -| string.swift:251:13:251:13 | tainted | string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() | -| string.swift:251:13:251:13 | tainted | string.swift:258:13:258:13 | tainted | -| string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() | string.swift:251:13:251:62 | ...[...] | -| string.swift:251:13:251:62 | ...[...] | string.swift:251:13:251:63 | ...! | -| string.swift:253:13:253:13 | [post] clean | string.swift:264:14:264:14 | clean | -| string.swift:253:13:253:13 | clean | string.swift:264:14:264:14 | clean | -| string.swift:254:5:254:5 | SSA def(line) | string.swift:255:15:255:15 | line | -| string.swift:254:5:254:5 | line | string.swift:254:5:254:5 | SSA def(line) | -| string.swift:254:11:254:11 | SSA def(stop) | string.swift:256:15:256:15 | stop | -| string.swift:254:11:254:11 | stop | string.swift:254:11:254:11 | SSA def(stop) | -| string.swift:258:13:258:13 | [post] tainted | string.swift:265:14:265:14 | tainted | -| string.swift:258:13:258:13 | tainted | string.swift:265:14:265:14 | tainted | +| string.swift:251:13:251:13 | [post] tainted | string.swift:252:13:252:13 | tainted | +| string.swift:251:13:251:13 | tainted | string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | +| string.swift:251:13:251:13 | tainted | string.swift:252:13:252:13 | tainted | +| string.swift:251:52:251:52 | | string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | +| string.swift:252:13:252:13 | [post] tainted | string.swift:253:13:253:13 | tainted | +| string.swift:252:13:252:13 | tainted | string.swift:252:13:252:69 | call to components(separatedBy:) | +| string.swift:252:13:252:13 | tainted | string.swift:253:13:253:13 | tainted | +| string.swift:253:13:253:13 | [post] tainted | string.swift:254:13:254:13 | tainted | +| string.swift:253:13:253:13 | tainted | string.swift:253:13:253:69 | call to components(separatedBy:) | +| string.swift:253:13:253:13 | tainted | string.swift:254:13:254:13 | tainted | +| string.swift:253:13:253:69 | call to components(separatedBy:) | string.swift:253:13:253:72 | ...[...] | +| string.swift:254:13:254:13 | [post] tainted | string.swift:255:13:255:13 | tainted | +| string.swift:254:13:254:13 | tainted | string.swift:254:13:254:40 | call to folding(options:locale:) | +| string.swift:254:13:254:13 | tainted | string.swift:255:13:255:13 | tainted | +| string.swift:255:13:255:13 | [post] tainted | string.swift:256:13:256:13 | tainted | +| string.swift:255:13:255:13 | tainted | string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | +| string.swift:255:13:255:13 | tainted | string.swift:256:13:256:13 | tainted | +| string.swift:256:13:256:13 | [post] tainted | string.swift:263:13:263:13 | tainted | +| string.swift:256:13:256:13 | tainted | string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() | +| string.swift:256:13:256:13 | tainted | string.swift:263:13:263:13 | tainted | +| string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() | string.swift:256:13:256:62 | ...[...] | +| string.swift:256:13:256:62 | ...[...] | string.swift:256:13:256:63 | ...! | +| string.swift:258:13:258:13 | [post] clean | string.swift:269:14:269:14 | clean | +| string.swift:258:13:258:13 | clean | string.swift:269:14:269:14 | clean | | string.swift:259:5:259:5 | SSA def(line) | string.swift:260:15:260:15 | line | | string.swift:259:5:259:5 | line | string.swift:259:5:259:5 | SSA def(line) | | string.swift:259:11:259:11 | SSA def(stop) | string.swift:261:15:261:15 | stop | | string.swift:259:11:259:11 | stop | string.swift:259:11:259:11 | SSA def(stop) | -| string.swift:264:13:264:26 | [...] | string.swift:264:13:264:35 | call to joined(separator:) | -| string.swift:264:14:264:14 | clean | string.swift:264:21:264:21 | clean | -| string.swift:264:21:264:21 | clean | string.swift:265:23:265:23 | clean | -| string.swift:264:34:264:34 | default separator | string.swift:264:13:264:35 | call to joined(separator:) | -| string.swift:265:13:265:28 | [...] | string.swift:265:13:265:37 | call to joined(separator:) | -| string.swift:265:14:265:14 | tainted | string.swift:266:21:266:21 | tainted | -| string.swift:265:23:265:23 | clean | string.swift:266:14:266:14 | clean | -| string.swift:265:36:265:36 | default separator | string.swift:265:13:265:37 | call to joined(separator:) | -| string.swift:266:13:266:28 | [...] | string.swift:266:13:266:37 | call to joined(separator:) | -| string.swift:266:14:266:14 | clean | string.swift:269:13:269:13 | clean | -| string.swift:266:21:266:21 | tainted | string.swift:267:14:267:14 | tainted | -| string.swift:266:36:266:36 | default separator | string.swift:266:13:266:37 | call to joined(separator:) | -| string.swift:267:13:267:30 | [...] | string.swift:267:13:267:39 | call to joined(separator:) | -| string.swift:267:14:267:14 | tainted | string.swift:267:23:267:23 | tainted | -| string.swift:267:23:267:23 | tainted | string.swift:270:13:270:13 | tainted | -| string.swift:267:38:267:38 | default separator | string.swift:267:13:267:39 | call to joined(separator:) | -| string.swift:269:13:269:13 | [post] clean | string.swift:271:13:271:13 | clean | -| string.swift:269:13:269:13 | clean | string.swift:269:13:269:19 | .description | -| string.swift:269:13:269:13 | clean | string.swift:271:13:271:13 | clean | -| string.swift:270:13:270:13 | [post] tainted | string.swift:272:13:272:13 | tainted | -| string.swift:270:13:270:13 | tainted | string.swift:270:13:270:21 | .description | -| string.swift:270:13:270:13 | tainted | string.swift:272:13:272:13 | tainted | -| string.swift:271:13:271:13 | [post] clean | string.swift:273:13:273:13 | clean | -| string.swift:271:13:271:13 | clean | string.swift:271:13:271:19 | .debugDescription | -| string.swift:271:13:271:13 | clean | string.swift:273:13:273:13 | clean | -| string.swift:272:13:272:13 | [post] tainted | string.swift:274:13:274:13 | tainted | -| string.swift:272:13:272:13 | tainted | string.swift:272:13:272:21 | .debugDescription | -| string.swift:272:13:272:13 | tainted | string.swift:274:13:274:13 | tainted | -| string.swift:273:13:273:13 | [post] clean | string.swift:275:13:275:13 | clean | -| string.swift:273:13:273:13 | clean | string.swift:273:13:273:19 | .utf8 | -| string.swift:273:13:273:13 | clean | string.swift:275:13:275:13 | clean | -| string.swift:274:13:274:13 | [post] tainted | string.swift:276:13:276:13 | tainted | -| string.swift:274:13:274:13 | tainted | string.swift:274:13:274:21 | .utf8 | -| string.swift:274:13:274:13 | tainted | string.swift:276:13:276:13 | tainted | -| string.swift:275:13:275:13 | [post] clean | string.swift:277:13:277:13 | clean | -| string.swift:275:13:275:13 | clean | string.swift:275:13:275:19 | .utf16 | -| string.swift:275:13:275:13 | clean | string.swift:277:13:277:13 | clean | -| string.swift:276:13:276:13 | [post] tainted | string.swift:278:13:278:13 | tainted | -| string.swift:276:13:276:13 | tainted | string.swift:276:13:276:21 | .utf16 | -| string.swift:276:13:276:13 | tainted | string.swift:278:13:278:13 | tainted | -| string.swift:277:13:277:13 | [post] clean | string.swift:279:13:279:13 | clean | -| string.swift:277:13:277:13 | clean | string.swift:277:13:277:19 | .unicodeScalars | -| string.swift:277:13:277:13 | clean | string.swift:279:13:279:13 | clean | -| string.swift:278:13:278:13 | [post] tainted | string.swift:280:13:280:13 | tainted | -| string.swift:278:13:278:13 | tainted | string.swift:278:13:278:21 | .unicodeScalars | -| string.swift:278:13:278:13 | tainted | string.swift:280:13:280:13 | tainted | -| string.swift:279:13:279:13 | [post] clean | string.swift:281:13:281:13 | clean | -| string.swift:279:13:279:13 | clean | string.swift:279:13:279:19 | .utf8CString | -| string.swift:279:13:279:13 | clean | string.swift:281:13:281:13 | clean | -| string.swift:280:13:280:13 | [post] tainted | string.swift:282:13:282:13 | tainted | -| string.swift:280:13:280:13 | tainted | string.swift:280:13:280:21 | .utf8CString | -| string.swift:280:13:280:13 | tainted | string.swift:282:13:282:13 | tainted | -| string.swift:281:13:281:13 | [post] clean | string.swift:283:13:283:13 | clean | -| string.swift:281:13:281:13 | clean | string.swift:281:13:281:19 | .lazy | -| string.swift:281:13:281:13 | clean | string.swift:283:13:283:13 | clean | -| string.swift:282:13:282:13 | [post] tainted | string.swift:284:13:284:13 | tainted | -| string.swift:282:13:282:13 | tainted | string.swift:282:13:282:21 | .lazy | -| string.swift:282:13:282:13 | tainted | string.swift:284:13:284:13 | tainted | -| string.swift:283:13:283:13 | [post] clean | string.swift:285:13:285:13 | clean | -| string.swift:283:13:283:13 | clean | string.swift:283:13:283:19 | .capitalized | -| string.swift:283:13:283:13 | clean | string.swift:285:13:285:13 | clean | -| string.swift:284:13:284:13 | [post] tainted | string.swift:286:13:286:13 | tainted | -| string.swift:284:13:284:13 | tainted | string.swift:284:13:284:21 | .capitalized | -| string.swift:284:13:284:13 | tainted | string.swift:286:13:286:13 | tainted | -| string.swift:285:13:285:13 | [post] clean | string.swift:287:13:287:13 | clean | -| string.swift:285:13:285:13 | clean | string.swift:285:13:285:19 | .localizedCapitalized | -| string.swift:285:13:285:13 | clean | string.swift:287:13:287:13 | clean | -| string.swift:286:13:286:13 | [post] tainted | string.swift:288:13:288:13 | tainted | -| string.swift:286:13:286:13 | tainted | string.swift:286:13:286:21 | .localizedCapitalized | -| string.swift:286:13:286:13 | tainted | string.swift:288:13:288:13 | tainted | -| string.swift:287:13:287:13 | [post] clean | string.swift:289:13:289:13 | clean | -| string.swift:287:13:287:13 | clean | string.swift:287:13:287:19 | .localizedLowercase | -| string.swift:287:13:287:13 | clean | string.swift:289:13:289:13 | clean | -| string.swift:288:13:288:13 | [post] tainted | string.swift:290:13:290:13 | tainted | -| string.swift:288:13:288:13 | tainted | string.swift:288:13:288:21 | .localizedLowercase | -| string.swift:288:13:288:13 | tainted | string.swift:290:13:290:13 | tainted | -| string.swift:289:13:289:13 | [post] clean | string.swift:291:13:291:13 | clean | -| string.swift:289:13:289:13 | clean | string.swift:289:13:289:19 | .localizedUppercase | -| string.swift:289:13:289:13 | clean | string.swift:291:13:291:13 | clean | -| string.swift:290:13:290:13 | [post] tainted | string.swift:292:13:292:13 | tainted | -| string.swift:290:13:290:13 | tainted | string.swift:290:13:290:21 | .localizedUppercase | -| string.swift:290:13:290:13 | tainted | string.swift:292:13:292:13 | tainted | -| string.swift:291:13:291:13 | [post] clean | string.swift:293:13:293:13 | clean | -| string.swift:291:13:291:13 | clean | string.swift:291:13:291:19 | .decomposedStringWithCanonicalMapping | -| string.swift:291:13:291:13 | clean | string.swift:293:13:293:13 | clean | -| string.swift:292:13:292:13 | [post] tainted | string.swift:294:13:294:13 | tainted | -| string.swift:292:13:292:13 | tainted | string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | -| string.swift:292:13:292:13 | tainted | string.swift:294:13:294:13 | tainted | -| string.swift:293:13:293:13 | [post] clean | string.swift:295:13:295:13 | clean | -| string.swift:293:13:293:13 | clean | string.swift:293:13:293:19 | .precomposedStringWithCompatibilityMapping | -| string.swift:293:13:293:13 | clean | string.swift:295:13:295:13 | clean | -| string.swift:294:13:294:13 | [post] tainted | string.swift:296:13:296:13 | tainted | -| string.swift:294:13:294:13 | tainted | string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | -| string.swift:294:13:294:13 | tainted | string.swift:296:13:296:13 | tainted | -| string.swift:295:13:295:13 | clean | string.swift:295:13:295:19 | .removingPercentEncoding | -| string.swift:295:13:295:19 | .removingPercentEncoding | string.swift:295:13:295:42 | ...! | -| string.swift:296:13:296:13 | tainted | string.swift:296:13:296:21 | .removingPercentEncoding | -| string.swift:296:13:296:21 | .removingPercentEncoding | string.swift:296:13:296:44 | ...! | -| string.swift:300:7:300:7 | SSA def(str1) | string.swift:301:13:301:13 | str1 | -| string.swift:300:14:300:22 | call to source2() | string.swift:300:7:300:7 | SSA def(str1) | -| string.swift:301:13:301:13 | [post] str1 | string.swift:302:13:302:13 | str1 | -| string.swift:301:13:301:13 | str1 | string.swift:302:13:302:13 | str1 | -| string.swift:302:13:302:13 | &... | string.swift:302:13:302:44 | call to remove(at:) | -| string.swift:302:13:302:13 | &... | string.swift:302:29:302:29 | str1 | -| string.swift:302:13:302:13 | [post] &... | string.swift:302:29:302:29 | str1 | -| string.swift:302:13:302:13 | str1 | string.swift:302:13:302:13 | &... | -| string.swift:302:29:302:29 | [post] str1 | string.swift:303:13:303:13 | str1 | -| string.swift:302:29:302:29 | str1 | string.swift:303:13:303:13 | str1 | -| string.swift:305:7:305:7 | SSA def(str2) | string.swift:306:13:306:13 | str2 | -| string.swift:305:14:305:22 | call to source2() | string.swift:305:7:305:7 | SSA def(str2) | -| string.swift:306:13:306:13 | [post] str2 | string.swift:307:3:307:3 | str2 | -| string.swift:306:13:306:13 | str2 | string.swift:307:3:307:3 | str2 | -| string.swift:307:3:307:3 | &... | string.swift:308:13:308:13 | str2 | -| string.swift:307:3:307:3 | [post] &... | string.swift:308:13:308:13 | str2 | -| string.swift:307:3:307:3 | str2 | string.swift:307:3:307:3 | &... | -| string.swift:310:7:310:7 | SSA def(str3) | string.swift:311:13:311:13 | str3 | -| string.swift:310:14:310:22 | call to source2() | string.swift:310:7:310:7 | SSA def(str3) | -| string.swift:311:13:311:13 | [post] str3 | string.swift:312:3:312:3 | str3 | -| string.swift:311:13:311:13 | str3 | string.swift:312:3:312:3 | str3 | -| string.swift:312:3:312:3 | &... | string.swift:313:13:313:13 | str3 | -| string.swift:312:3:312:3 | [post] &... | string.swift:313:13:313:13 | str3 | -| string.swift:312:3:312:3 | str3 | string.swift:312:3:312:3 | &... | -| string.swift:315:7:315:7 | SSA def(str4) | string.swift:316:13:316:13 | str4 | -| string.swift:315:14:315:22 | call to source2() | string.swift:315:7:315:7 | SSA def(str4) | -| string.swift:316:13:316:13 | [post] str4 | string.swift:317:13:317:13 | str4 | -| string.swift:316:13:316:13 | str4 | string.swift:317:13:317:13 | str4 | -| string.swift:317:13:317:13 | &... | string.swift:317:13:317:30 | call to removeFirst() | -| string.swift:317:13:317:13 | &... | string.swift:318:13:318:13 | str4 | -| string.swift:317:13:317:13 | [post] &... | string.swift:318:13:318:13 | str4 | -| string.swift:317:13:317:13 | str4 | string.swift:317:13:317:13 | &... | -| string.swift:318:13:318:13 | [post] str4 | string.swift:319:3:319:3 | str4 | -| string.swift:318:13:318:13 | str4 | string.swift:319:3:319:3 | str4 | -| string.swift:319:3:319:3 | &... | string.swift:320:13:320:13 | str4 | -| string.swift:319:3:319:3 | [post] &... | string.swift:320:13:320:13 | str4 | -| string.swift:319:3:319:3 | str4 | string.swift:319:3:319:3 | &... | -| string.swift:320:13:320:13 | [post] str4 | string.swift:321:13:321:13 | str4 | -| string.swift:320:13:320:13 | str4 | string.swift:321:13:321:13 | str4 | -| string.swift:321:13:321:13 | &... | string.swift:321:13:321:29 | call to removeLast() | -| string.swift:321:13:321:13 | &... | string.swift:322:13:322:13 | str4 | -| string.swift:321:13:321:13 | [post] &... | string.swift:322:13:322:13 | str4 | -| string.swift:321:13:321:13 | str4 | string.swift:321:13:321:13 | &... | -| string.swift:322:13:322:13 | [post] str4 | string.swift:323:3:323:3 | str4 | -| string.swift:322:13:322:13 | str4 | string.swift:323:3:323:3 | str4 | -| string.swift:323:3:323:3 | &... | string.swift:324:13:324:13 | str4 | -| string.swift:323:3:323:3 | [post] &... | string.swift:324:13:324:13 | str4 | -| string.swift:323:3:323:3 | str4 | string.swift:323:3:323:3 | &... | -| string.swift:326:7:326:7 | SSA def(str5) | string.swift:327:13:327:13 | str5 | -| string.swift:326:14:326:22 | call to source2() | string.swift:326:7:326:7 | SSA def(str5) | -| string.swift:327:13:327:13 | [post] str5 | string.swift:328:3:328:3 | str5 | -| string.swift:327:13:327:13 | str5 | string.swift:328:3:328:3 | str5 | -| string.swift:328:3:328:3 | &... | string.swift:328:23:328:23 | str5 | -| string.swift:328:3:328:3 | [post] &... | string.swift:328:23:328:23 | str5 | -| string.swift:328:3:328:3 | str5 | string.swift:328:3:328:3 | &... | -| string.swift:328:23:328:23 | [post] str5 | string.swift:328:43:328:43 | str5 | -| string.swift:328:23:328:23 | str5 | string.swift:328:43:328:43 | str5 | -| string.swift:328:43:328:43 | [post] str5 | string.swift:328:54:328:54 | str5 | -| string.swift:328:43:328:43 | str5 | string.swift:328:54:328:54 | str5 | -| string.swift:328:54:328:54 | [post] str5 | string.swift:329:13:329:13 | str5 | -| string.swift:328:54:328:54 | str5 | string.swift:329:13:329:13 | str5 | -| string.swift:331:7:331:7 | SSA def(str6) | string.swift:332:13:332:13 | str6 | -| string.swift:331:14:331:22 | call to source2() | string.swift:331:7:331:7 | SSA def(str6) | -| string.swift:332:13:332:13 | [post] str6 | string.swift:333:3:333:3 | str6 | -| string.swift:332:13:332:13 | str6 | string.swift:333:3:333:3 | str6 | -| string.swift:333:3:333:3 | &... | string.swift:334:13:334:13 | str6 | -| string.swift:333:3:333:3 | [post] &... | string.swift:334:13:334:13 | str6 | -| string.swift:333:3:333:3 | str6 | string.swift:333:3:333:3 | &... | -| string.swift:337:38:337:38 | | string.swift:337:33:337:40 | call to Data.init(_:) | -| string.swift:340:7:340:7 | SSA def(stringClean) | string.swift:343:12:343:12 | stringClean | -| string.swift:340:21:340:74 | call to String.init(data:encoding:) | string.swift:340:7:340:7 | SSA def(stringClean) | -| string.swift:340:34:340:41 | call to Data.init(_:) | string.swift:340:21:340:74 | call to String.init(data:encoding:) | -| string.swift:340:39:340:39 | | string.swift:340:34:340:41 | call to Data.init(_:) | -| string.swift:341:7:341:7 | SSA def(stringTainted) | string.swift:344:12:344:12 | stringTainted | -| string.swift:341:23:341:77 | call to String.init(data:encoding:) | string.swift:341:7:341:7 | SSA def(stringTainted) | -| string.swift:341:36:341:44 | call to source3() | string.swift:341:23:341:77 | call to String.init(data:encoding:) | -| string.swift:343:12:343:12 | stringClean | string.swift:343:12:343:23 | ...! | -| string.swift:344:12:344:12 | stringTainted | string.swift:344:12:344:25 | ...! | -| string.swift:346:30:346:37 | call to Data.init(_:) | string.swift:346:13:346:53 | call to String.init(decoding:as:) | -| string.swift:346:35:346:35 | | string.swift:346:30:346:37 | call to Data.init(_:) | -| string.swift:347:30:347:38 | call to source3() | string.swift:347:13:347:54 | call to String.init(decoding:as:) | -| string.swift:351:7:351:7 | SSA def(clean) | string.swift:354:3:354:3 | clean | -| string.swift:351:15:351:15 | | string.swift:351:7:351:7 | SSA def(clean) | -| string.swift:352:7:352:7 | SSA def(tainted) | string.swift:359:3:359:3 | tainted | -| string.swift:352:17:352:25 | call to source2() | string.swift:352:7:352:7 | SSA def(tainted) | -| string.swift:354:3:354:3 | &... | string.swift:365:3:365:3 | clean | -| string.swift:354:3:354:3 | [post] &... | string.swift:365:3:365:3 | clean | -| string.swift:354:3:354:3 | clean | string.swift:354:3:354:3 | &... | -| string.swift:355:5:355:5 | SSA def(buffer) | string.swift:356:15:356:15 | buffer | -| string.swift:355:5:355:5 | buffer | string.swift:355:5:355:5 | SSA def(buffer) | -| string.swift:356:15:356:15 | buffer | string.swift:357:15:357:15 | buffer | -| string.swift:357:15:357:22 | .baseAddress | string.swift:357:15:357:33 | ...! | -| string.swift:359:3:359:3 | &... | string.swift:369:3:369:3 | tainted | -| string.swift:359:3:359:3 | [post] &... | string.swift:369:3:369:3 | tainted | -| string.swift:359:3:359:3 | tainted | string.swift:359:3:359:3 | &... | -| string.swift:360:5:360:5 | SSA def(buffer) | string.swift:361:15:361:15 | buffer | -| string.swift:360:5:360:5 | buffer | string.swift:360:5:360:5 | SSA def(buffer) | -| string.swift:361:15:361:15 | buffer | string.swift:362:15:362:15 | buffer | -| string.swift:362:15:362:22 | .baseAddress | string.swift:362:15:362:33 | ...! | -| string.swift:365:3:365:3 | [post] clean | string.swift:373:3:373:3 | clean | -| string.swift:365:3:365:3 | clean | string.swift:373:3:373:3 | clean | -| string.swift:366:5:366:5 | SSA def(ptr) | string.swift:367:15:367:15 | ptr | -| string.swift:366:5:366:5 | ptr | string.swift:366:5:366:5 | SSA def(ptr) | -| string.swift:369:3:369:3 | [post] tainted | string.swift:377:3:377:3 | tainted | -| string.swift:369:3:369:3 | tainted | string.swift:377:3:377:3 | tainted | -| string.swift:370:5:370:5 | SSA def(ptr) | string.swift:371:15:371:15 | ptr | -| string.swift:370:5:370:5 | ptr | string.swift:370:5:370:5 | SSA def(ptr) | -| string.swift:373:3:373:3 | [post] clean | string.swift:382:22:382:22 | clean | -| string.swift:373:3:373:3 | clean | string.swift:382:22:382:22 | clean | -| string.swift:374:5:374:5 | SSA def(ptr) | string.swift:375:15:375:15 | ptr | -| string.swift:374:5:374:5 | ptr | string.swift:374:5:374:5 | SSA def(ptr) | -| string.swift:377:3:377:3 | [post] tainted | string.swift:389:22:389:22 | tainted | -| string.swift:377:3:377:3 | tainted | string.swift:389:22:389:22 | tainted | -| string.swift:378:5:378:5 | SSA def(ptr) | string.swift:379:15:379:15 | ptr | -| string.swift:378:5:378:5 | ptr | string.swift:378:5:378:5 | SSA def(ptr) | -| string.swift:382:7:382:7 | SSA def(arrayString1) | string.swift:383:13:383:13 | arrayString1 | -| string.swift:382:22:382:22 | [post] clean | string.swift:397:3:397:3 | clean | -| string.swift:382:22:382:22 | clean | string.swift:382:22:382:63 | call to cString(using:) | -| string.swift:382:22:382:22 | clean | string.swift:397:3:397:3 | clean | -| string.swift:382:22:382:63 | call to cString(using:) | string.swift:382:22:382:64 | ...! | -| string.swift:382:22:382:64 | ...! | string.swift:382:7:382:7 | SSA def(arrayString1) | -| string.swift:383:13:383:13 | arrayString1 | string.swift:384:3:384:3 | arrayString1 | -| string.swift:384:3:384:3 | [post] arrayString1 | string.swift:391:3:391:3 | arrayString1 | -| string.swift:384:3:384:3 | arrayString1 | string.swift:391:3:391:3 | arrayString1 | -| string.swift:385:5:385:5 | SSA def(buffer) | string.swift:386:15:386:15 | buffer | -| string.swift:385:5:385:5 | buffer | string.swift:385:5:385:5 | SSA def(buffer) | -| string.swift:386:15:386:15 | buffer | string.swift:387:31:387:31 | buffer | -| string.swift:387:31:387:38 | .baseAddress | string.swift:387:31:387:49 | ...! | -| string.swift:387:31:387:49 | ...! | string.swift:387:15:387:50 | call to String.init(cString:) | -| string.swift:389:7:389:7 | SSA def(arrayString2) | string.swift:390:13:390:13 | arrayString2 | -| string.swift:389:22:389:22 | [post] tainted | string.swift:408:3:408:3 | tainted | -| string.swift:389:22:389:22 | tainted | string.swift:389:22:389:65 | call to cString(using:) | -| string.swift:389:22:389:22 | tainted | string.swift:408:3:408:3 | tainted | -| string.swift:389:22:389:65 | call to cString(using:) | string.swift:389:22:389:66 | ...! | -| string.swift:389:22:389:66 | ...! | string.swift:389:7:389:7 | SSA def(arrayString2) | -| string.swift:392:5:392:5 | SSA def(buffer) | string.swift:393:15:393:15 | buffer | -| string.swift:392:5:392:5 | buffer | string.swift:392:5:392:5 | SSA def(buffer) | -| string.swift:393:15:393:15 | buffer | string.swift:394:31:394:31 | buffer | -| string.swift:394:31:394:38 | .baseAddress | string.swift:394:31:394:49 | ...! | -| string.swift:394:31:394:49 | ...! | string.swift:394:15:394:50 | call to String.init(cString:) | -| string.swift:397:3:397:3 | [post] clean | string.swift:420:3:420:3 | clean | -| string.swift:397:3:397:3 | clean | string.swift:420:3:420:3 | clean | -| string.swift:398:5:398:5 | SSA def(ptr) | string.swift:399:15:399:15 | ptr | -| string.swift:398:5:398:5 | ptr | string.swift:398:5:398:5 | SSA def(ptr) | -| string.swift:399:15:399:15 | ptr | string.swift:400:38:400:38 | ptr | -| string.swift:400:38:400:38 | ptr | string.swift:400:15:400:41 | call to String.init(platformString:) | -| string.swift:400:38:400:38 | ptr | string.swift:402:45:402:45 | ptr | -| string.swift:402:9:402:9 | SSA def(buffer) | string.swift:403:29:403:29 | buffer | -| string.swift:402:18:402:59 | call to UnsafeBufferPointer.init(start:count:) | string.swift:402:9:402:9 | SSA def(buffer) | -| string.swift:403:9:403:9 | SSA def(arrayString) | string.swift:405:15:405:15 | arrayString | -| string.swift:403:23:403:35 | call to Array.init(_:) | string.swift:403:9:403:9 | SSA def(arrayString) | -| string.swift:403:29:403:29 | buffer | string.swift:404:15:404:15 | buffer | -| string.swift:405:15:405:15 | arrayString | string.swift:406:38:406:38 | arrayString | -| string.swift:406:38:406:38 | arrayString | string.swift:406:15:406:49 | call to String.init(platformString:) | -| string.swift:408:3:408:3 | [post] tainted | string.swift:425:3:425:3 | tainted | -| string.swift:408:3:408:3 | tainted | string.swift:425:3:425:3 | tainted | -| string.swift:409:5:409:5 | SSA def(ptr) | string.swift:410:15:410:15 | ptr | -| string.swift:409:5:409:5 | ptr | string.swift:409:5:409:5 | SSA def(ptr) | -| string.swift:410:15:410:15 | ptr | string.swift:411:38:411:38 | ptr | -| string.swift:411:38:411:38 | ptr | string.swift:411:15:411:41 | call to String.init(platformString:) | -| string.swift:411:38:411:38 | ptr | string.swift:413:45:413:45 | ptr | -| string.swift:413:9:413:9 | SSA def(buffer) | string.swift:414:29:414:29 | buffer | -| string.swift:413:18:413:59 | call to UnsafeBufferPointer.init(start:count:) | string.swift:413:9:413:9 | SSA def(buffer) | -| string.swift:414:9:414:9 | SSA def(arrayString) | string.swift:416:15:416:15 | arrayString | -| string.swift:414:23:414:35 | call to Array.init(_:) | string.swift:414:9:414:9 | SSA def(arrayString) | -| string.swift:414:29:414:29 | buffer | string.swift:415:15:415:15 | buffer | -| string.swift:416:15:416:15 | arrayString | string.swift:417:38:417:38 | arrayString | -| string.swift:417:38:417:38 | arrayString | string.swift:417:15:417:49 | call to String.init(platformString:) | -| string.swift:421:5:421:5 | SSA def(ptr) | string.swift:422:15:422:15 | ptr | -| string.swift:421:5:421:5 | ptr | string.swift:421:5:421:5 | SSA def(ptr) | -| string.swift:422:15:422:15 | ptr | string.swift:423:15:423:15 | ptr | -| string.swift:423:15:423:19 | .baseAddress | string.swift:423:15:423:30 | ...! | -| string.swift:426:5:426:5 | SSA def(ptr) | string.swift:427:15:427:15 | ptr | -| string.swift:426:5:426:5 | ptr | string.swift:426:5:426:5 | SSA def(ptr) | -| string.swift:427:15:427:15 | ptr | string.swift:428:15:428:15 | ptr | -| string.swift:428:15:428:19 | .baseAddress | string.swift:428:15:428:30 | ...! | -| string.swift:435:7:435:31 | SSA def(cleanUInt8Values) | string.swift:455:27:455:27 | cleanUInt8Values | -| string.swift:435:35:435:55 | [...] | string.swift:435:7:435:31 | SSA def(cleanUInt8Values) | -| string.swift:436:7:436:7 | SSA def(taintedUInt8Values) | string.swift:456:27:456:27 | taintedUInt8Values | -| string.swift:436:28:436:36 | call to source4() | string.swift:436:7:436:7 | SSA def(taintedUInt8Values) | -| string.swift:439:6:439:46 | SSA def(buffer) | string.swift:440:17:440:17 | buffer | -| string.swift:439:6:439:46 | buffer | string.swift:439:6:439:46 | SSA def(buffer) | -| string.swift:440:17:440:17 | buffer | string.swift:441:15:441:15 | buffer | -| string.swift:441:15:441:15 | [post] buffer | string.swift:442:17:442:17 | buffer | -| string.swift:441:15:441:15 | buffer | string.swift:442:17:442:17 | buffer | -| string.swift:447:6:447:46 | SSA def(buffer) | string.swift:448:17:448:17 | buffer | -| string.swift:447:6:447:46 | buffer | string.swift:447:6:447:46 | SSA def(buffer) | -| string.swift:448:17:448:17 | buffer | string.swift:449:15:449:15 | buffer | -| string.swift:449:15:449:15 | [post] buffer | string.swift:450:17:450:17 | buffer | -| string.swift:449:15:449:15 | buffer | string.swift:450:17:450:17 | buffer | -| string.swift:455:13:455:75 | call to String.init(bytes:encoding:) | string.swift:455:13:455:76 | ...! | -| string.swift:455:27:455:27 | cleanUInt8Values | string.swift:455:13:455:75 | call to String.init(bytes:encoding:) | -| string.swift:455:27:455:27 | cleanUInt8Values | string.swift:458:29:458:29 | cleanUInt8Values | -| string.swift:456:13:456:77 | call to String.init(bytes:encoding:) | string.swift:456:13:456:78 | ...! | -| string.swift:456:27:456:27 | taintedUInt8Values | string.swift:456:13:456:77 | call to String.init(bytes:encoding:) | -| string.swift:456:27:456:27 | taintedUInt8Values | string.swift:459:29:459:29 | taintedUInt8Values | -| string.swift:458:29:458:29 | cleanUInt8Values | string.swift:458:13:458:45 | call to String.init(cString:) | -| string.swift:458:29:458:29 | cleanUInt8Values | string.swift:461:8:461:8 | cleanUInt8Values | -| string.swift:459:29:459:29 | taintedUInt8Values | string.swift:459:13:459:47 | call to String.init(cString:) | -| string.swift:459:29:459:29 | taintedUInt8Values | string.swift:467:8:467:8 | taintedUInt8Values | -| string.swift:461:8:461:8 | [post] cleanUInt8Values | string.swift:474:8:474:8 | cleanUInt8Values | -| string.swift:461:8:461:8 | cleanUInt8Values | string.swift:474:8:474:8 | cleanUInt8Values | -| string.swift:461:8:466:4 | call to withUnsafeBufferPointer(_:) | string.swift:461:3:466:4 | try! ... | -| string.swift:462:6:462:39 | SSA def(buffer) | string.swift:463:15:463:15 | buffer | -| string.swift:462:6:462:39 | buffer | string.swift:462:6:462:39 | SSA def(buffer) | -| string.swift:463:15:463:15 | buffer | string.swift:464:15:464:15 | buffer | -| string.swift:464:15:464:15 | [post] buffer | string.swift:465:31:465:31 | buffer | -| string.swift:464:15:464:15 | buffer | string.swift:465:31:465:31 | buffer | -| string.swift:464:15:464:22 | .baseAddress | string.swift:464:15:464:33 | ...! | -| string.swift:465:31:465:38 | .baseAddress | string.swift:465:31:465:49 | ...! | -| string.swift:465:31:465:49 | ...! | string.swift:465:15:465:50 | call to String.init(cString:) | -| string.swift:467:8:467:8 | [post] taintedUInt8Values | string.swift:480:8:480:8 | taintedUInt8Values | -| string.swift:467:8:467:8 | taintedUInt8Values | string.swift:480:8:480:8 | taintedUInt8Values | -| string.swift:467:8:472:4 | call to withUnsafeBufferPointer(_:) | string.swift:467:3:472:4 | try! ... | -| string.swift:468:6:468:39 | SSA def(buffer) | string.swift:469:15:469:15 | buffer | -| string.swift:468:6:468:39 | buffer | string.swift:468:6:468:39 | SSA def(buffer) | -| string.swift:469:15:469:15 | buffer | string.swift:470:15:470:15 | buffer | -| string.swift:470:15:470:15 | [post] buffer | string.swift:471:31:471:31 | buffer | -| string.swift:470:15:470:15 | buffer | string.swift:471:31:471:31 | buffer | -| string.swift:470:15:470:22 | .baseAddress | string.swift:470:15:470:33 | ...! | -| string.swift:471:31:471:38 | .baseAddress | string.swift:471:31:471:49 | ...! | -| string.swift:471:31:471:49 | ...! | string.swift:471:15:471:50 | call to String.init(cString:) | -| string.swift:474:8:474:8 | cleanUInt8Values | string.swift:474:8:474:8 | &... | -| string.swift:474:8:479:4 | call to withUnsafeMutableBytes(_:) | string.swift:474:3:479:4 | try! ... | -| string.swift:475:6:475:14 | SSA def(buffer) | string.swift:476:15:476:15 | buffer | -| string.swift:475:6:475:14 | buffer | string.swift:475:6:475:14 | SSA def(buffer) | -| string.swift:476:15:476:15 | [post] buffer | string.swift:477:15:477:15 | buffer | -| string.swift:476:15:476:15 | buffer | string.swift:477:15:477:15 | buffer | -| string.swift:477:15:477:15 | [post] buffer | string.swift:478:35:478:35 | buffer | -| string.swift:477:15:477:15 | buffer | string.swift:478:35:478:35 | buffer | -| string.swift:477:15:477:22 | .baseAddress | string.swift:477:15:477:33 | ...! | -| string.swift:478:15:478:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | string.swift:478:15:478:130 | ...! | -| string.swift:478:35:478:35 | [post] buffer | string.swift:478:64:478:64 | buffer | -| string.swift:478:35:478:35 | buffer | string.swift:478:64:478:64 | buffer | -| string.swift:478:35:478:42 | .baseAddress | string.swift:478:35:478:53 | ...! | -| string.swift:480:8:480:8 | taintedUInt8Values | string.swift:480:8:480:8 | &... | -| string.swift:480:8:485:4 | call to withUnsafeMutableBytes(_:) | string.swift:480:3:485:4 | try! ... | -| string.swift:481:6:481:14 | SSA def(buffer) | string.swift:482:15:482:15 | buffer | -| string.swift:481:6:481:14 | buffer | string.swift:481:6:481:14 | SSA def(buffer) | -| string.swift:482:15:482:15 | [post] buffer | string.swift:483:15:483:15 | buffer | -| string.swift:482:15:482:15 | buffer | string.swift:483:15:483:15 | buffer | -| string.swift:483:15:483:15 | [post] buffer | string.swift:484:35:484:35 | buffer | -| string.swift:483:15:483:15 | buffer | string.swift:484:35:484:35 | buffer | -| string.swift:483:15:483:22 | .baseAddress | string.swift:483:15:483:33 | ...! | -| string.swift:484:15:484:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | string.swift:484:15:484:130 | ...! | -| string.swift:484:35:484:35 | [post] buffer | string.swift:484:64:484:64 | buffer | -| string.swift:484:35:484:35 | buffer | string.swift:484:64:484:64 | buffer | -| string.swift:484:35:484:42 | .baseAddress | string.swift:484:35:484:53 | ...! | -| string.swift:491:7:491:31 | SSA def(cleanCCharValues) | string.swift:494:3:494:3 | cleanCCharValues | -| string.swift:491:35:491:55 | [...] | string.swift:491:7:491:31 | SSA def(cleanCCharValues) | -| string.swift:492:7:492:33 | SSA def(taintedCCharValues) | string.swift:502:3:502:3 | taintedCCharValues | -| string.swift:492:37:492:45 | call to source5() | string.swift:492:7:492:33 | SSA def(taintedCCharValues) | -| string.swift:494:3:494:3 | [post] cleanCCharValues | string.swift:511:29:511:29 | cleanCCharValues | -| string.swift:494:3:494:3 | cleanCCharValues | string.swift:511:29:511:29 | cleanCCharValues | -| string.swift:495:5:495:5 | SSA def(ptr) | string.swift:496:15:496:15 | ptr | -| string.swift:495:5:495:5 | ptr | string.swift:495:5:495:5 | SSA def(ptr) | -| string.swift:496:15:496:15 | ptr | string.swift:497:15:497:15 | ptr | -| string.swift:497:15:497:15 | [post] ptr | string.swift:498:34:498:34 | ptr | -| string.swift:497:15:497:15 | ptr | string.swift:498:34:498:34 | ptr | -| string.swift:497:15:497:19 | .baseAddress | string.swift:497:15:497:30 | ...! | -| string.swift:498:15:498:50 | call to String.init(utf8String:) | string.swift:498:15:498:51 | ...! | -| string.swift:498:34:498:34 | [post] ptr | string.swift:499:38:499:38 | ptr | -| string.swift:498:34:498:34 | ptr | string.swift:499:38:499:38 | ptr | -| string.swift:498:34:498:38 | .baseAddress | string.swift:498:34:498:49 | ...! | -| string.swift:498:34:498:49 | ...! | string.swift:498:15:498:50 | call to String.init(utf8String:) | -| string.swift:499:15:499:54 | call to String.init(validatingUTF8:) | string.swift:499:15:499:55 | ...! | -| string.swift:499:38:499:38 | [post] ptr | string.swift:500:31:500:31 | ptr | -| string.swift:499:38:499:38 | ptr | string.swift:500:31:500:31 | ptr | -| string.swift:499:38:499:42 | .baseAddress | string.swift:499:38:499:53 | ...! | -| string.swift:499:38:499:53 | ...! | string.swift:499:15:499:54 | call to String.init(validatingUTF8:) | -| string.swift:500:31:500:35 | .baseAddress | string.swift:500:31:500:46 | ...! | -| string.swift:500:31:500:46 | ...! | string.swift:500:15:500:47 | call to String.init(cString:) | -| string.swift:502:3:502:3 | [post] taintedCCharValues | string.swift:512:29:512:29 | taintedCCharValues | -| string.swift:502:3:502:3 | taintedCCharValues | string.swift:512:29:512:29 | taintedCCharValues | -| string.swift:503:5:503:5 | SSA def(ptr) | string.swift:504:15:504:15 | ptr | -| string.swift:503:5:503:5 | ptr | string.swift:503:5:503:5 | SSA def(ptr) | -| string.swift:504:15:504:15 | ptr | string.swift:505:15:505:15 | ptr | -| string.swift:505:15:505:15 | [post] ptr | string.swift:506:34:506:34 | ptr | -| string.swift:505:15:505:15 | ptr | string.swift:506:34:506:34 | ptr | -| string.swift:505:15:505:19 | .baseAddress | string.swift:505:15:505:30 | ...! | -| string.swift:506:15:506:50 | call to String.init(utf8String:) | string.swift:506:15:506:51 | ...! | -| string.swift:506:34:506:34 | [post] ptr | string.swift:507:38:507:38 | ptr | -| string.swift:506:34:506:34 | ptr | string.swift:507:38:507:38 | ptr | -| string.swift:506:34:506:38 | .baseAddress | string.swift:506:34:506:49 | ...! | -| string.swift:506:34:506:49 | ...! | string.swift:506:15:506:50 | call to String.init(utf8String:) | -| string.swift:507:15:507:54 | call to String.init(validatingUTF8:) | string.swift:507:15:507:55 | ...! | -| string.swift:507:38:507:38 | [post] ptr | string.swift:508:31:508:31 | ptr | -| string.swift:507:38:507:38 | ptr | string.swift:508:31:508:31 | ptr | -| string.swift:507:38:507:42 | .baseAddress | string.swift:507:38:507:53 | ...! | -| string.swift:507:38:507:53 | ...! | string.swift:507:15:507:54 | call to String.init(validatingUTF8:) | -| string.swift:508:31:508:35 | .baseAddress | string.swift:508:31:508:46 | ...! | -| string.swift:508:31:508:46 | ...! | string.swift:508:15:508:47 | call to String.init(cString:) | -| string.swift:511:29:511:29 | cleanCCharValues | string.swift:511:13:511:45 | call to String.init(cString:) | -| string.swift:512:29:512:29 | taintedCCharValues | string.swift:512:13:512:47 | call to String.init(cString:) | -| string.swift:518:7:518:35 | SSA def(cleanUnicharValues) | string.swift:521:3:521:3 | cleanUnicharValues | -| string.swift:518:39:518:59 | [...] | string.swift:518:7:518:35 | SSA def(cleanUnicharValues) | -| string.swift:519:7:519:37 | SSA def(taintedUnicharValues) | string.swift:528:3:528:3 | taintedUnicharValues | -| string.swift:519:41:519:49 | call to source6() | string.swift:519:7:519:37 | SSA def(taintedUnicharValues) | -| string.swift:522:5:522:5 | SSA def(ptr) | string.swift:523:15:523:15 | ptr | -| string.swift:522:5:522:5 | ptr | string.swift:522:5:522:5 | SSA def(ptr) | -| string.swift:523:15:523:15 | ptr | string.swift:524:15:524:15 | ptr | -| string.swift:524:15:524:15 | [post] ptr | string.swift:525:38:525:38 | ptr | -| string.swift:524:15:524:15 | ptr | string.swift:525:38:525:38 | ptr | -| string.swift:524:15:524:19 | .baseAddress | string.swift:524:15:524:30 | ...! | -| string.swift:525:38:525:38 | [post] ptr | string.swift:525:63:525:63 | ptr | -| string.swift:525:38:525:38 | ptr | string.swift:525:63:525:63 | ptr | -| string.swift:525:38:525:42 | .baseAddress | string.swift:525:38:525:53 | ...! | -| string.swift:525:38:525:53 | ...! | string.swift:525:15:525:72 | call to String.init(utf16CodeUnits:count:) | -| string.swift:525:63:525:63 | [post] ptr | string.swift:526:44:526:44 | ptr | -| string.swift:525:63:525:63 | ptr | string.swift:526:44:526:44 | ptr | -| string.swift:526:44:526:44 | [post] ptr | string.swift:526:69:526:69 | ptr | -| string.swift:526:44:526:44 | ptr | string.swift:526:69:526:69 | ptr | -| string.swift:526:44:526:48 | .baseAddress | string.swift:526:44:526:59 | ...! | -| string.swift:526:44:526:59 | ...! | string.swift:526:15:526:99 | call to String.init(utf16CodeUnitsNoCopy:count:freeWhenDone:) | -| string.swift:529:5:529:5 | SSA def(ptr) | string.swift:530:15:530:15 | ptr | -| string.swift:529:5:529:5 | ptr | string.swift:529:5:529:5 | SSA def(ptr) | -| string.swift:530:15:530:15 | ptr | string.swift:531:15:531:15 | ptr | -| string.swift:531:15:531:15 | [post] ptr | string.swift:532:38:532:38 | ptr | -| string.swift:531:15:531:15 | ptr | string.swift:532:38:532:38 | ptr | -| string.swift:531:15:531:19 | .baseAddress | string.swift:531:15:531:30 | ...! | -| string.swift:532:38:532:38 | [post] ptr | string.swift:532:63:532:63 | ptr | -| string.swift:532:38:532:38 | ptr | string.swift:532:63:532:63 | ptr | -| string.swift:532:38:532:42 | .baseAddress | string.swift:532:38:532:53 | ...! | -| string.swift:532:38:532:53 | ...! | string.swift:532:15:532:72 | call to String.init(utf16CodeUnits:count:) | -| string.swift:532:63:532:63 | [post] ptr | string.swift:533:44:533:44 | ptr | -| string.swift:532:63:532:63 | ptr | string.swift:533:44:533:44 | ptr | -| string.swift:533:44:533:44 | [post] ptr | string.swift:533:69:533:69 | ptr | -| string.swift:533:44:533:44 | ptr | string.swift:533:69:533:69 | ptr | -| string.swift:533:44:533:48 | .baseAddress | string.swift:533:44:533:59 | ...! | -| string.swift:533:44:533:59 | ...! | string.swift:533:15:533:99 | call to String.init(utf16CodeUnitsNoCopy:count:freeWhenDone:) | -| string.swift:540:7:540:7 | SSA def(tainted) | string.swift:544:14:544:14 | tainted | -| string.swift:540:17:540:25 | call to source2() | string.swift:540:7:540:7 | SSA def(tainted) | -| string.swift:544:7:544:7 | SSA def(sub1) | string.swift:545:13:545:13 | sub1 | -| string.swift:544:14:544:14 | [post] tainted | string.swift:544:22:544:22 | tainted | -| string.swift:544:14:544:14 | tainted | string.swift:544:14:544:61 | ...[...] | -| string.swift:544:14:544:14 | tainted | string.swift:544:22:544:22 | tainted | -| string.swift:544:14:544:61 | ...[...] | string.swift:544:7:544:7 | SSA def(sub1) | -| string.swift:544:22:544:22 | [post] tainted | string.swift:544:45:544:45 | tainted | -| string.swift:544:22:544:22 | tainted | string.swift:544:45:544:45 | tainted | -| string.swift:544:45:544:45 | [post] tainted | string.swift:548:14:548:14 | tainted | -| string.swift:544:45:544:45 | tainted | string.swift:548:14:548:14 | tainted | -| string.swift:545:13:545:13 | [post] sub1 | string.swift:546:20:546:20 | sub1 | -| string.swift:545:13:545:13 | sub1 | string.swift:546:20:546:20 | sub1 | -| string.swift:546:20:546:20 | sub1 | string.swift:546:13:546:24 | call to String.init(_:) | -| string.swift:548:7:548:7 | SSA def(sub2) | string.swift:549:13:549:13 | sub2 | -| string.swift:548:14:548:14 | [post] tainted | string.swift:552:14:552:14 | tainted | -| string.swift:548:14:548:14 | tainted | string.swift:548:14:548:31 | call to prefix(_:) | -| string.swift:548:14:548:14 | tainted | string.swift:552:14:552:14 | tainted | -| string.swift:548:14:548:31 | call to prefix(_:) | string.swift:548:7:548:7 | SSA def(sub2) | -| string.swift:549:13:549:13 | sub2 | string.swift:550:20:550:20 | sub2 | -| string.swift:550:20:550:20 | sub2 | string.swift:550:13:550:24 | call to String.init(_:) | -| string.swift:552:7:552:7 | SSA def(sub3) | string.swift:553:13:553:13 | sub3 | -| string.swift:552:14:552:14 | [post] tainted | string.swift:552:38:552:38 | tainted | -| string.swift:552:14:552:14 | tainted | string.swift:552:14:552:54 | call to prefix(through:) | -| string.swift:552:14:552:14 | tainted | string.swift:552:38:552:38 | tainted | -| string.swift:552:14:552:54 | call to prefix(through:) | string.swift:552:7:552:7 | SSA def(sub3) | -| string.swift:552:38:552:38 | [post] tainted | string.swift:556:14:556:14 | tainted | -| string.swift:552:38:552:38 | tainted | string.swift:556:14:556:14 | tainted | -| string.swift:553:13:553:13 | sub3 | string.swift:554:20:554:20 | sub3 | -| string.swift:554:20:554:20 | sub3 | string.swift:554:13:554:24 | call to String.init(_:) | -| string.swift:556:7:556:7 | SSA def(sub4) | string.swift:557:13:557:13 | sub4 | -| string.swift:556:14:556:14 | [post] tainted | string.swift:556:35:556:35 | tainted | -| string.swift:556:14:556:14 | tainted | string.swift:556:14:556:51 | call to prefix(upTo:) | -| string.swift:556:14:556:14 | tainted | string.swift:556:35:556:35 | tainted | -| string.swift:556:14:556:51 | call to prefix(upTo:) | string.swift:556:7:556:7 | SSA def(sub4) | -| string.swift:556:35:556:35 | [post] tainted | string.swift:560:14:560:14 | tainted | -| string.swift:556:35:556:35 | tainted | string.swift:560:14:560:14 | tainted | -| string.swift:557:13:557:13 | sub4 | string.swift:558:20:558:20 | sub4 | -| string.swift:558:20:558:20 | sub4 | string.swift:558:13:558:24 | call to String.init(_:) | -| string.swift:560:7:560:7 | SSA def(sub5) | string.swift:561:13:561:13 | sub5 | -| string.swift:560:14:560:14 | [post] tainted | string.swift:564:14:564:14 | tainted | -| string.swift:560:14:560:14 | tainted | string.swift:560:14:560:31 | call to suffix(_:) | -| string.swift:560:14:560:14 | tainted | string.swift:564:14:564:14 | tainted | -| string.swift:560:14:560:31 | call to suffix(_:) | string.swift:560:7:560:7 | SSA def(sub5) | -| string.swift:561:13:561:13 | sub5 | string.swift:562:20:562:20 | sub5 | -| string.swift:562:20:562:20 | sub5 | string.swift:562:13:562:24 | call to String.init(_:) | -| string.swift:564:7:564:7 | SSA def(sub6) | string.swift:565:13:565:13 | sub6 | -| string.swift:564:14:564:14 | [post] tainted | string.swift:564:35:564:35 | tainted | -| string.swift:564:14:564:14 | tainted | string.swift:564:14:564:53 | call to suffix(from:) | -| string.swift:564:14:564:14 | tainted | string.swift:564:35:564:35 | tainted | -| string.swift:564:14:564:53 | call to suffix(from:) | string.swift:564:7:564:7 | SSA def(sub6) | -| string.swift:565:13:565:13 | sub6 | string.swift:566:20:566:20 | sub6 | -| string.swift:566:20:566:20 | sub6 | string.swift:566:13:566:24 | call to String.init(_:) | -| string.swift:570:7:570:7 | SSA def(clean) | string.swift:573:13:573:13 | clean | -| string.swift:570:15:570:26 | call to FilePath.init(_:) | string.swift:570:7:570:7 | SSA def(clean) | -| string.swift:571:7:571:7 | SSA def(tainted) | string.swift:574:13:574:13 | tainted | -| string.swift:571:17:571:35 | call to FilePath.init(_:) | string.swift:571:7:571:7 | SSA def(tainted) | -| string.swift:573:13:573:13 | [post] clean | string.swift:585:11:585:11 | clean | -| string.swift:573:13:573:13 | clean | string.swift:585:11:585:11 | clean | -| string.swift:574:13:574:13 | [post] tainted | string.swift:576:13:576:13 | tainted | -| string.swift:574:13:574:13 | tainted | string.swift:576:13:576:13 | tainted | -| string.swift:576:13:576:13 | [post] tainted | string.swift:577:13:577:13 | tainted | -| string.swift:576:13:576:13 | tainted | string.swift:577:13:577:13 | tainted | -| string.swift:576:13:576:21 | .extension | string.swift:576:13:576:30 | ...! | -| string.swift:577:13:577:13 | [post] tainted | string.swift:578:13:578:13 | tainted | -| string.swift:577:13:577:13 | tainted | string.swift:578:13:578:13 | tainted | -| string.swift:577:13:577:21 | .stem | string.swift:577:13:577:25 | ...! | -| string.swift:578:13:578:13 | [post] tainted | string.swift:579:13:579:13 | tainted | -| string.swift:578:13:578:13 | tainted | string.swift:579:13:579:13 | tainted | -| string.swift:579:13:579:13 | [post] tainted | string.swift:580:13:580:13 | tainted | -| string.swift:579:13:579:13 | tainted | string.swift:580:13:580:13 | tainted | -| string.swift:580:13:580:13 | [post] tainted | string.swift:582:30:582:30 | tainted | -| string.swift:580:13:580:13 | tainted | string.swift:582:30:582:30 | tainted | -| string.swift:582:30:582:30 | [post] tainted | string.swift:583:32:583:32 | tainted | -| string.swift:582:30:582:30 | tainted | string.swift:582:13:582:37 | call to String.init(decoding:) | -| string.swift:582:30:582:30 | tainted | string.swift:583:32:583:32 | tainted | -| string.swift:583:13:583:39 | call to String.init(validating:) | string.swift:583:13:583:40 | ...! | -| string.swift:583:32:583:32 | [post] tainted | string.swift:589:11:589:11 | tainted | -| string.swift:583:32:583:32 | tainted | string.swift:583:13:583:39 | call to String.init(validating:) | -| string.swift:583:32:583:32 | tainted | string.swift:589:11:589:11 | tainted | -| string.swift:585:11:585:11 | [post] clean | string.swift:594:11:594:11 | clean | -| string.swift:585:11:585:11 | clean | string.swift:594:11:594:11 | clean | -| string.swift:586:5:586:5 | SSA def(ptr) | string.swift:587:15:587:15 | ptr | -| string.swift:586:5:586:5 | ptr | string.swift:586:5:586:5 | SSA def(ptr) | -| string.swift:589:11:589:11 | [post] tainted | string.swift:600:11:600:11 | tainted | -| string.swift:589:11:589:11 | tainted | string.swift:600:11:600:11 | tainted | -| string.swift:590:5:590:5 | SSA def(ptr) | string.swift:591:15:591:15 | ptr | -| string.swift:590:5:590:5 | ptr | string.swift:590:5:590:5 | SSA def(ptr) | -| string.swift:594:11:594:11 | [post] clean | string.swift:614:13:614:13 | clean | -| string.swift:594:11:594:11 | clean | string.swift:614:13:614:13 | clean | -| string.swift:595:5:595:5 | SSA def(ptr) | string.swift:596:15:596:15 | ptr | -| string.swift:595:5:595:5 | ptr | string.swift:595:5:595:5 | SSA def(ptr) | -| string.swift:596:15:596:15 | ptr | string.swift:597:38:597:38 | ptr | -| string.swift:597:38:597:38 | ptr | string.swift:597:15:597:41 | call to String.init(platformString:) | -| string.swift:597:38:597:38 | ptr | string.swift:598:48:598:48 | ptr | -| string.swift:598:15:598:51 | call to String.init(validatingPlatformString:) | string.swift:598:15:598:52 | ...! | -| string.swift:598:48:598:48 | ptr | string.swift:598:15:598:51 | call to String.init(validatingPlatformString:) | -| string.swift:600:11:600:11 | [post] tainted | string.swift:616:13:616:13 | tainted | -| string.swift:600:11:600:11 | tainted | string.swift:616:13:616:13 | tainted | -| string.swift:601:5:601:5 | SSA def(ptr) | string.swift:602:15:602:15 | ptr | -| string.swift:601:5:601:5 | ptr | string.swift:601:5:601:5 | SSA def(ptr) | -| string.swift:602:15:602:15 | ptr | string.swift:603:38:603:38 | ptr | -| string.swift:603:38:603:38 | ptr | string.swift:603:15:603:41 | call to String.init(platformString:) | -| string.swift:603:38:603:38 | ptr | string.swift:604:48:604:48 | ptr | -| string.swift:604:15:604:51 | call to String.init(validatingPlatformString:) | string.swift:604:15:604:52 | ...! | -| string.swift:604:48:604:48 | ptr | string.swift:604:15:604:51 | call to String.init(validatingPlatformString:) | -| string.swift:607:7:607:7 | SSA def(fp1) | string.swift:608:13:608:13 | fp1 | -| string.swift:607:13:607:24 | call to FilePath.init(_:) | string.swift:607:7:607:7 | SSA def(fp1) | -| string.swift:608:13:608:13 | [post] fp1 | string.swift:609:3:609:3 | fp1 | -| string.swift:608:13:608:13 | fp1 | string.swift:609:3:609:3 | fp1 | -| string.swift:609:3:609:3 | &... | string.swift:610:13:610:13 | fp1 | -| string.swift:609:3:609:3 | [post] &... | string.swift:610:13:610:13 | fp1 | -| string.swift:609:3:609:3 | fp1 | string.swift:609:3:609:3 | &... | -| string.swift:610:13:610:13 | [post] fp1 | string.swift:611:3:611:3 | fp1 | -| string.swift:610:13:610:13 | fp1 | string.swift:611:3:611:3 | fp1 | -| string.swift:611:3:611:3 | &... | string.swift:612:13:612:13 | fp1 | -| string.swift:611:3:611:3 | [post] &... | string.swift:612:13:612:13 | fp1 | -| string.swift:611:3:611:3 | fp1 | string.swift:611:3:611:3 | &... | -| string.swift:614:13:614:13 | [post] clean | string.swift:615:13:615:13 | clean | -| string.swift:614:13:614:13 | clean | string.swift:615:13:615:13 | clean | -| string.swift:616:13:616:13 | [post] tainted | string.swift:617:13:617:13 | tainted | -| string.swift:616:13:616:13 | tainted | string.swift:617:13:617:13 | tainted | -| string.swift:621:20:621:20 | 0 | string.swift:621:13:621:21 | call to String.init(_:) | -| string.swift:622:20:622:27 | call to source() | string.swift:622:13:622:28 | call to String.init(_:) | -| string.swift:625:32:625:32 | 0 | string.swift:625:13:625:33 | call to String.init(describing:) | -| string.swift:626:32:626:39 | call to source() | string.swift:626:13:626:40 | call to String.init(describing:) | -| string.swift:628:13:628:22 | call to Self.init(_:) | string.swift:628:13:628:23 | ...! | -| string.swift:629:13:629:26 | call to Self.init(_:) | string.swift:629:13:629:27 | ...! | -| string.swift:633:7:633:7 | SSA def(tainted) | string.swift:637:13:637:13 | tainted | -| string.swift:633:17:633:25 | call to source2() | string.swift:633:7:633:7 | SSA def(tainted) | +| string.swift:263:13:263:13 | [post] tainted | string.swift:270:14:270:14 | tainted | +| string.swift:263:13:263:13 | tainted | string.swift:270:14:270:14 | tainted | +| string.swift:264:5:264:5 | SSA def(line) | string.swift:265:15:265:15 | line | +| string.swift:264:5:264:5 | line | string.swift:264:5:264:5 | SSA def(line) | +| string.swift:264:11:264:11 | SSA def(stop) | string.swift:266:15:266:15 | stop | +| string.swift:264:11:264:11 | stop | string.swift:264:11:264:11 | SSA def(stop) | +| string.swift:269:13:269:26 | [...] | string.swift:269:13:269:35 | call to joined(separator:) | +| string.swift:269:14:269:14 | clean | string.swift:269:21:269:21 | clean | +| string.swift:269:21:269:21 | clean | string.swift:270:23:270:23 | clean | +| string.swift:269:34:269:34 | default separator | string.swift:269:13:269:35 | call to joined(separator:) | +| string.swift:270:13:270:28 | [...] | string.swift:270:13:270:37 | call to joined(separator:) | +| string.swift:270:14:270:14 | tainted | string.swift:271:21:271:21 | tainted | +| string.swift:270:23:270:23 | clean | string.swift:271:14:271:14 | clean | +| string.swift:270:36:270:36 | default separator | string.swift:270:13:270:37 | call to joined(separator:) | +| string.swift:271:13:271:28 | [...] | string.swift:271:13:271:37 | call to joined(separator:) | +| string.swift:271:14:271:14 | clean | string.swift:274:13:274:13 | clean | +| string.swift:271:21:271:21 | tainted | string.swift:272:14:272:14 | tainted | +| string.swift:271:36:271:36 | default separator | string.swift:271:13:271:37 | call to joined(separator:) | +| string.swift:272:13:272:30 | [...] | string.swift:272:13:272:39 | call to joined(separator:) | +| string.swift:272:14:272:14 | tainted | string.swift:272:23:272:23 | tainted | +| string.swift:272:23:272:23 | tainted | string.swift:275:13:275:13 | tainted | +| string.swift:272:38:272:38 | default separator | string.swift:272:13:272:39 | call to joined(separator:) | +| string.swift:274:13:274:13 | [post] clean | string.swift:276:13:276:13 | clean | +| string.swift:274:13:274:13 | clean | string.swift:274:13:274:19 | .description | +| string.swift:274:13:274:13 | clean | string.swift:276:13:276:13 | clean | +| string.swift:275:13:275:13 | [post] tainted | string.swift:277:13:277:13 | tainted | +| string.swift:275:13:275:13 | tainted | string.swift:275:13:275:21 | .description | +| string.swift:275:13:275:13 | tainted | string.swift:277:13:277:13 | tainted | +| string.swift:276:13:276:13 | [post] clean | string.swift:278:13:278:13 | clean | +| string.swift:276:13:276:13 | clean | string.swift:276:13:276:19 | .debugDescription | +| string.swift:276:13:276:13 | clean | string.swift:278:13:278:13 | clean | +| string.swift:277:13:277:13 | [post] tainted | string.swift:279:13:279:13 | tainted | +| string.swift:277:13:277:13 | tainted | string.swift:277:13:277:21 | .debugDescription | +| string.swift:277:13:277:13 | tainted | string.swift:279:13:279:13 | tainted | +| string.swift:278:13:278:13 | [post] clean | string.swift:280:13:280:13 | clean | +| string.swift:278:13:278:13 | clean | string.swift:278:13:278:19 | .utf8 | +| string.swift:278:13:278:13 | clean | string.swift:280:13:280:13 | clean | +| string.swift:279:13:279:13 | [post] tainted | string.swift:281:13:281:13 | tainted | +| string.swift:279:13:279:13 | tainted | string.swift:279:13:279:21 | .utf8 | +| string.swift:279:13:279:13 | tainted | string.swift:281:13:281:13 | tainted | +| string.swift:280:13:280:13 | [post] clean | string.swift:282:13:282:13 | clean | +| string.swift:280:13:280:13 | clean | string.swift:280:13:280:19 | .utf16 | +| string.swift:280:13:280:13 | clean | string.swift:282:13:282:13 | clean | +| string.swift:281:13:281:13 | [post] tainted | string.swift:283:13:283:13 | tainted | +| string.swift:281:13:281:13 | tainted | string.swift:281:13:281:21 | .utf16 | +| string.swift:281:13:281:13 | tainted | string.swift:283:13:283:13 | tainted | +| string.swift:282:13:282:13 | [post] clean | string.swift:284:13:284:13 | clean | +| string.swift:282:13:282:13 | clean | string.swift:282:13:282:19 | .unicodeScalars | +| string.swift:282:13:282:13 | clean | string.swift:284:13:284:13 | clean | +| string.swift:283:13:283:13 | [post] tainted | string.swift:285:13:285:13 | tainted | +| string.swift:283:13:283:13 | tainted | string.swift:283:13:283:21 | .unicodeScalars | +| string.swift:283:13:283:13 | tainted | string.swift:285:13:285:13 | tainted | +| string.swift:284:13:284:13 | [post] clean | string.swift:286:13:286:13 | clean | +| string.swift:284:13:284:13 | clean | string.swift:284:13:284:19 | .utf8CString | +| string.swift:284:13:284:13 | clean | string.swift:286:13:286:13 | clean | +| string.swift:285:13:285:13 | [post] tainted | string.swift:287:13:287:13 | tainted | +| string.swift:285:13:285:13 | tainted | string.swift:285:13:285:21 | .utf8CString | +| string.swift:285:13:285:13 | tainted | string.swift:287:13:287:13 | tainted | +| string.swift:286:13:286:13 | [post] clean | string.swift:288:13:288:13 | clean | +| string.swift:286:13:286:13 | clean | string.swift:286:13:286:19 | .lazy | +| string.swift:286:13:286:13 | clean | string.swift:288:13:288:13 | clean | +| string.swift:287:13:287:13 | [post] tainted | string.swift:289:13:289:13 | tainted | +| string.swift:287:13:287:13 | tainted | string.swift:287:13:287:21 | .lazy | +| string.swift:287:13:287:13 | tainted | string.swift:289:13:289:13 | tainted | +| string.swift:288:13:288:13 | [post] clean | string.swift:290:13:290:13 | clean | +| string.swift:288:13:288:13 | clean | string.swift:288:13:288:19 | .capitalized | +| string.swift:288:13:288:13 | clean | string.swift:290:13:290:13 | clean | +| string.swift:289:13:289:13 | [post] tainted | string.swift:291:13:291:13 | tainted | +| string.swift:289:13:289:13 | tainted | string.swift:289:13:289:21 | .capitalized | +| string.swift:289:13:289:13 | tainted | string.swift:291:13:291:13 | tainted | +| string.swift:290:13:290:13 | [post] clean | string.swift:292:13:292:13 | clean | +| string.swift:290:13:290:13 | clean | string.swift:290:13:290:19 | .localizedCapitalized | +| string.swift:290:13:290:13 | clean | string.swift:292:13:292:13 | clean | +| string.swift:291:13:291:13 | [post] tainted | string.swift:293:13:293:13 | tainted | +| string.swift:291:13:291:13 | tainted | string.swift:291:13:291:21 | .localizedCapitalized | +| string.swift:291:13:291:13 | tainted | string.swift:293:13:293:13 | tainted | +| string.swift:292:13:292:13 | [post] clean | string.swift:294:13:294:13 | clean | +| string.swift:292:13:292:13 | clean | string.swift:292:13:292:19 | .localizedLowercase | +| string.swift:292:13:292:13 | clean | string.swift:294:13:294:13 | clean | +| string.swift:293:13:293:13 | [post] tainted | string.swift:295:13:295:13 | tainted | +| string.swift:293:13:293:13 | tainted | string.swift:293:13:293:21 | .localizedLowercase | +| string.swift:293:13:293:13 | tainted | string.swift:295:13:295:13 | tainted | +| string.swift:294:13:294:13 | [post] clean | string.swift:296:13:296:13 | clean | +| string.swift:294:13:294:13 | clean | string.swift:294:13:294:19 | .localizedUppercase | +| string.swift:294:13:294:13 | clean | string.swift:296:13:296:13 | clean | +| string.swift:295:13:295:13 | [post] tainted | string.swift:297:13:297:13 | tainted | +| string.swift:295:13:295:13 | tainted | string.swift:295:13:295:21 | .localizedUppercase | +| string.swift:295:13:295:13 | tainted | string.swift:297:13:297:13 | tainted | +| string.swift:296:13:296:13 | [post] clean | string.swift:298:13:298:13 | clean | +| string.swift:296:13:296:13 | clean | string.swift:296:13:296:19 | .decomposedStringWithCanonicalMapping | +| string.swift:296:13:296:13 | clean | string.swift:298:13:298:13 | clean | +| string.swift:297:13:297:13 | [post] tainted | string.swift:299:13:299:13 | tainted | +| string.swift:297:13:297:13 | tainted | string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | +| string.swift:297:13:297:13 | tainted | string.swift:299:13:299:13 | tainted | +| string.swift:298:13:298:13 | [post] clean | string.swift:300:13:300:13 | clean | +| string.swift:298:13:298:13 | clean | string.swift:298:13:298:19 | .precomposedStringWithCompatibilityMapping | +| string.swift:298:13:298:13 | clean | string.swift:300:13:300:13 | clean | +| string.swift:299:13:299:13 | [post] tainted | string.swift:301:13:301:13 | tainted | +| string.swift:299:13:299:13 | tainted | string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | +| string.swift:299:13:299:13 | tainted | string.swift:301:13:301:13 | tainted | +| string.swift:300:13:300:13 | [post] clean | string.swift:303:13:303:13 | clean | +| string.swift:300:13:300:13 | clean | string.swift:300:13:300:19 | .removingPercentEncoding | +| string.swift:300:13:300:13 | clean | string.swift:303:13:303:13 | clean | +| string.swift:300:13:300:19 | .removingPercentEncoding | string.swift:300:13:300:42 | ...! | +| string.swift:301:13:301:13 | [post] tainted | string.swift:304:13:304:13 | tainted | +| string.swift:301:13:301:13 | tainted | string.swift:301:13:301:21 | .removingPercentEncoding | +| string.swift:301:13:301:13 | tainted | string.swift:304:13:304:13 | tainted | +| string.swift:301:13:301:21 | .removingPercentEncoding | string.swift:301:13:301:44 | ...! | +| string.swift:303:13:303:13 | [post] clean | string.swift:305:13:305:13 | clean | +| string.swift:303:13:303:13 | clean | string.swift:303:13:303:58 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:303:13:303:13 | clean | string.swift:305:13:305:13 | clean | +| string.swift:303:55:303:55 | b | string.swift:303:13:303:58 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:304:13:304:13 | tainted | string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:304:57:304:57 | b | string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:13:305:13 | clean | string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:55:305:63 | call to source2() | string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:309:7:309:7 | SSA def(str1) | string.swift:310:13:310:13 | str1 | +| string.swift:309:14:309:22 | call to source2() | string.swift:309:7:309:7 | SSA def(str1) | +| string.swift:310:13:310:13 | [post] str1 | string.swift:311:13:311:13 | str1 | +| string.swift:310:13:310:13 | str1 | string.swift:311:13:311:13 | str1 | +| string.swift:311:13:311:13 | &... | string.swift:311:13:311:44 | call to remove(at:) | +| string.swift:311:13:311:13 | &... | string.swift:311:29:311:29 | str1 | +| string.swift:311:13:311:13 | [post] &... | string.swift:311:29:311:29 | str1 | +| string.swift:311:13:311:13 | str1 | string.swift:311:13:311:13 | &... | +| string.swift:311:29:311:29 | [post] str1 | string.swift:312:13:312:13 | str1 | +| string.swift:311:29:311:29 | str1 | string.swift:312:13:312:13 | str1 | +| string.swift:314:7:314:7 | SSA def(str2) | string.swift:315:13:315:13 | str2 | +| string.swift:314:14:314:22 | call to source2() | string.swift:314:7:314:7 | SSA def(str2) | +| string.swift:315:13:315:13 | [post] str2 | string.swift:316:3:316:3 | str2 | +| string.swift:315:13:315:13 | str2 | string.swift:316:3:316:3 | str2 | +| string.swift:316:3:316:3 | &... | string.swift:317:13:317:13 | str2 | +| string.swift:316:3:316:3 | [post] &... | string.swift:317:13:317:13 | str2 | +| string.swift:316:3:316:3 | str2 | string.swift:316:3:316:3 | &... | +| string.swift:319:7:319:7 | SSA def(str3) | string.swift:320:13:320:13 | str3 | +| string.swift:319:14:319:22 | call to source2() | string.swift:319:7:319:7 | SSA def(str3) | +| string.swift:320:13:320:13 | [post] str3 | string.swift:321:3:321:3 | str3 | +| string.swift:320:13:320:13 | str3 | string.swift:321:3:321:3 | str3 | +| string.swift:321:3:321:3 | &... | string.swift:322:13:322:13 | str3 | +| string.swift:321:3:321:3 | [post] &... | string.swift:322:13:322:13 | str3 | +| string.swift:321:3:321:3 | str3 | string.swift:321:3:321:3 | &... | +| string.swift:324:7:324:7 | SSA def(str4) | string.swift:325:13:325:13 | str4 | +| string.swift:324:14:324:22 | call to source2() | string.swift:324:7:324:7 | SSA def(str4) | +| string.swift:325:13:325:13 | [post] str4 | string.swift:326:13:326:13 | str4 | +| string.swift:325:13:325:13 | str4 | string.swift:326:13:326:13 | str4 | +| string.swift:326:13:326:13 | &... | string.swift:326:13:326:30 | call to removeFirst() | +| string.swift:326:13:326:13 | &... | string.swift:327:13:327:13 | str4 | +| string.swift:326:13:326:13 | [post] &... | string.swift:327:13:327:13 | str4 | +| string.swift:326:13:326:13 | str4 | string.swift:326:13:326:13 | &... | +| string.swift:327:13:327:13 | [post] str4 | string.swift:328:3:328:3 | str4 | +| string.swift:327:13:327:13 | str4 | string.swift:328:3:328:3 | str4 | +| string.swift:328:3:328:3 | &... | string.swift:329:13:329:13 | str4 | +| string.swift:328:3:328:3 | [post] &... | string.swift:329:13:329:13 | str4 | +| string.swift:328:3:328:3 | str4 | string.swift:328:3:328:3 | &... | +| string.swift:329:13:329:13 | [post] str4 | string.swift:330:13:330:13 | str4 | +| string.swift:329:13:329:13 | str4 | string.swift:330:13:330:13 | str4 | +| string.swift:330:13:330:13 | &... | string.swift:330:13:330:29 | call to removeLast() | +| string.swift:330:13:330:13 | &... | string.swift:331:13:331:13 | str4 | +| string.swift:330:13:330:13 | [post] &... | string.swift:331:13:331:13 | str4 | +| string.swift:330:13:330:13 | str4 | string.swift:330:13:330:13 | &... | +| string.swift:331:13:331:13 | [post] str4 | string.swift:332:3:332:3 | str4 | +| string.swift:331:13:331:13 | str4 | string.swift:332:3:332:3 | str4 | +| string.swift:332:3:332:3 | &... | string.swift:333:13:333:13 | str4 | +| string.swift:332:3:332:3 | [post] &... | string.swift:333:13:333:13 | str4 | +| string.swift:332:3:332:3 | str4 | string.swift:332:3:332:3 | &... | +| string.swift:335:7:335:7 | SSA def(str5) | string.swift:336:13:336:13 | str5 | +| string.swift:335:14:335:22 | call to source2() | string.swift:335:7:335:7 | SSA def(str5) | +| string.swift:336:13:336:13 | [post] str5 | string.swift:337:3:337:3 | str5 | +| string.swift:336:13:336:13 | str5 | string.swift:337:3:337:3 | str5 | +| string.swift:337:3:337:3 | &... | string.swift:337:23:337:23 | str5 | +| string.swift:337:3:337:3 | [post] &... | string.swift:337:23:337:23 | str5 | +| string.swift:337:3:337:3 | str5 | string.swift:337:3:337:3 | &... | +| string.swift:337:23:337:23 | [post] str5 | string.swift:337:43:337:43 | str5 | +| string.swift:337:23:337:23 | str5 | string.swift:337:43:337:43 | str5 | +| string.swift:337:43:337:43 | [post] str5 | string.swift:337:54:337:54 | str5 | +| string.swift:337:43:337:43 | str5 | string.swift:337:54:337:54 | str5 | +| string.swift:337:54:337:54 | [post] str5 | string.swift:338:13:338:13 | str5 | +| string.swift:337:54:337:54 | str5 | string.swift:338:13:338:13 | str5 | +| string.swift:340:7:340:7 | SSA def(str6) | string.swift:341:13:341:13 | str6 | +| string.swift:340:14:340:22 | call to source2() | string.swift:340:7:340:7 | SSA def(str6) | +| string.swift:341:13:341:13 | [post] str6 | string.swift:342:3:342:3 | str6 | +| string.swift:341:13:341:13 | str6 | string.swift:342:3:342:3 | str6 | +| string.swift:342:3:342:3 | &... | string.swift:343:13:343:13 | str6 | +| string.swift:342:3:342:3 | [post] &... | string.swift:343:13:343:13 | str6 | +| string.swift:342:3:342:3 | str6 | string.swift:342:3:342:3 | &... | +| string.swift:345:7:345:7 | SSA def(str7) | string.swift:346:13:346:13 | str7 | +| string.swift:345:14:345:14 | | string.swift:345:7:345:7 | SSA def(str7) | +| string.swift:346:13:346:13 | [post] str7 | string.swift:347:3:347:3 | str7 | +| string.swift:346:13:346:13 | str7 | string.swift:347:3:347:3 | str7 | +| string.swift:347:3:347:3 | &... | string.swift:348:13:348:13 | str7 | +| string.swift:347:3:347:3 | [post] &... | string.swift:348:13:348:13 | str7 | +| string.swift:347:3:347:3 | str7 | string.swift:347:3:347:3 | &... | +| string.swift:347:25:347:25 | nil | string.swift:347:24:347:53 | ...! | +| string.swift:347:62:347:70 | call to source2() | string.swift:347:3:347:3 | [post] &... | +| string.swift:351:38:351:38 | | string.swift:351:33:351:40 | call to Data.init(_:) | +| string.swift:354:7:354:7 | SSA def(stringClean) | string.swift:357:12:357:12 | stringClean | +| string.swift:354:21:354:74 | call to String.init(data:encoding:) | string.swift:354:7:354:7 | SSA def(stringClean) | +| string.swift:354:34:354:41 | call to Data.init(_:) | string.swift:354:21:354:74 | call to String.init(data:encoding:) | +| string.swift:354:39:354:39 | | string.swift:354:34:354:41 | call to Data.init(_:) | +| string.swift:355:7:355:7 | SSA def(stringTainted) | string.swift:358:12:358:12 | stringTainted | +| string.swift:355:23:355:77 | call to String.init(data:encoding:) | string.swift:355:7:355:7 | SSA def(stringTainted) | +| string.swift:355:36:355:44 | call to source3() | string.swift:355:23:355:77 | call to String.init(data:encoding:) | +| string.swift:357:12:357:12 | stringClean | string.swift:357:12:357:23 | ...! | +| string.swift:358:12:358:12 | stringTainted | string.swift:358:12:358:25 | ...! | +| string.swift:360:30:360:37 | call to Data.init(_:) | string.swift:360:13:360:53 | call to String.init(decoding:as:) | +| string.swift:360:35:360:35 | | string.swift:360:30:360:37 | call to Data.init(_:) | +| string.swift:361:30:361:38 | call to source3() | string.swift:361:13:361:54 | call to String.init(decoding:as:) | +| string.swift:365:7:365:7 | SSA def(clean) | string.swift:368:3:368:3 | clean | +| string.swift:365:15:365:15 | | string.swift:365:7:365:7 | SSA def(clean) | +| string.swift:366:7:366:7 | SSA def(tainted) | string.swift:373:3:373:3 | tainted | +| string.swift:366:17:366:25 | call to source2() | string.swift:366:7:366:7 | SSA def(tainted) | +| string.swift:368:3:368:3 | &... | string.swift:379:3:379:3 | clean | +| string.swift:368:3:368:3 | [post] &... | string.swift:379:3:379:3 | clean | +| string.swift:368:3:368:3 | clean | string.swift:368:3:368:3 | &... | +| string.swift:369:5:369:5 | SSA def(buffer) | string.swift:370:15:370:15 | buffer | +| string.swift:369:5:369:5 | buffer | string.swift:369:5:369:5 | SSA def(buffer) | +| string.swift:370:15:370:15 | buffer | string.swift:371:15:371:15 | buffer | +| string.swift:371:15:371:22 | .baseAddress | string.swift:371:15:371:33 | ...! | +| string.swift:373:3:373:3 | &... | string.swift:383:3:383:3 | tainted | +| string.swift:373:3:373:3 | [post] &... | string.swift:383:3:383:3 | tainted | +| string.swift:373:3:373:3 | tainted | string.swift:373:3:373:3 | &... | +| string.swift:374:5:374:5 | SSA def(buffer) | string.swift:375:15:375:15 | buffer | +| string.swift:374:5:374:5 | buffer | string.swift:374:5:374:5 | SSA def(buffer) | +| string.swift:375:15:375:15 | buffer | string.swift:376:15:376:15 | buffer | +| string.swift:376:15:376:22 | .baseAddress | string.swift:376:15:376:33 | ...! | +| string.swift:379:3:379:3 | [post] clean | string.swift:387:3:387:3 | clean | +| string.swift:379:3:379:3 | clean | string.swift:387:3:387:3 | clean | +| string.swift:380:5:380:5 | SSA def(ptr) | string.swift:381:15:381:15 | ptr | +| string.swift:380:5:380:5 | ptr | string.swift:380:5:380:5 | SSA def(ptr) | +| string.swift:383:3:383:3 | [post] tainted | string.swift:391:3:391:3 | tainted | +| string.swift:383:3:383:3 | tainted | string.swift:391:3:391:3 | tainted | +| string.swift:384:5:384:5 | SSA def(ptr) | string.swift:385:15:385:15 | ptr | +| string.swift:384:5:384:5 | ptr | string.swift:384:5:384:5 | SSA def(ptr) | +| string.swift:387:3:387:3 | [post] clean | string.swift:396:22:396:22 | clean | +| string.swift:387:3:387:3 | clean | string.swift:396:22:396:22 | clean | +| string.swift:388:5:388:5 | SSA def(ptr) | string.swift:389:15:389:15 | ptr | +| string.swift:388:5:388:5 | ptr | string.swift:388:5:388:5 | SSA def(ptr) | +| string.swift:391:3:391:3 | [post] tainted | string.swift:403:22:403:22 | tainted | +| string.swift:391:3:391:3 | tainted | string.swift:403:22:403:22 | tainted | +| string.swift:392:5:392:5 | SSA def(ptr) | string.swift:393:15:393:15 | ptr | +| string.swift:392:5:392:5 | ptr | string.swift:392:5:392:5 | SSA def(ptr) | +| string.swift:396:7:396:7 | SSA def(arrayString1) | string.swift:397:13:397:13 | arrayString1 | +| string.swift:396:22:396:22 | [post] clean | string.swift:411:3:411:3 | clean | +| string.swift:396:22:396:22 | clean | string.swift:396:22:396:63 | call to cString(using:) | +| string.swift:396:22:396:22 | clean | string.swift:411:3:411:3 | clean | +| string.swift:396:22:396:63 | call to cString(using:) | string.swift:396:22:396:64 | ...! | +| string.swift:396:22:396:64 | ...! | string.swift:396:7:396:7 | SSA def(arrayString1) | +| string.swift:397:13:397:13 | arrayString1 | string.swift:398:3:398:3 | arrayString1 | +| string.swift:398:3:398:3 | [post] arrayString1 | string.swift:405:3:405:3 | arrayString1 | +| string.swift:398:3:398:3 | arrayString1 | string.swift:405:3:405:3 | arrayString1 | +| string.swift:399:5:399:5 | SSA def(buffer) | string.swift:400:15:400:15 | buffer | +| string.swift:399:5:399:5 | buffer | string.swift:399:5:399:5 | SSA def(buffer) | +| string.swift:400:15:400:15 | buffer | string.swift:401:31:401:31 | buffer | +| string.swift:401:31:401:38 | .baseAddress | string.swift:401:31:401:49 | ...! | +| string.swift:401:31:401:49 | ...! | string.swift:401:15:401:50 | call to String.init(cString:) | +| string.swift:403:7:403:7 | SSA def(arrayString2) | string.swift:404:13:404:13 | arrayString2 | +| string.swift:403:22:403:22 | [post] tainted | string.swift:422:3:422:3 | tainted | +| string.swift:403:22:403:22 | tainted | string.swift:403:22:403:65 | call to cString(using:) | +| string.swift:403:22:403:22 | tainted | string.swift:422:3:422:3 | tainted | +| string.swift:403:22:403:65 | call to cString(using:) | string.swift:403:22:403:66 | ...! | +| string.swift:403:22:403:66 | ...! | string.swift:403:7:403:7 | SSA def(arrayString2) | +| string.swift:406:5:406:5 | SSA def(buffer) | string.swift:407:15:407:15 | buffer | +| string.swift:406:5:406:5 | buffer | string.swift:406:5:406:5 | SSA def(buffer) | +| string.swift:407:15:407:15 | buffer | string.swift:408:31:408:31 | buffer | +| string.swift:408:31:408:38 | .baseAddress | string.swift:408:31:408:49 | ...! | +| string.swift:408:31:408:49 | ...! | string.swift:408:15:408:50 | call to String.init(cString:) | +| string.swift:411:3:411:3 | [post] clean | string.swift:434:3:434:3 | clean | +| string.swift:411:3:411:3 | clean | string.swift:434:3:434:3 | clean | +| string.swift:412:5:412:5 | SSA def(ptr) | string.swift:413:15:413:15 | ptr | +| string.swift:412:5:412:5 | ptr | string.swift:412:5:412:5 | SSA def(ptr) | +| string.swift:413:15:413:15 | ptr | string.swift:414:38:414:38 | ptr | +| string.swift:414:38:414:38 | ptr | string.swift:414:15:414:41 | call to String.init(platformString:) | +| string.swift:414:38:414:38 | ptr | string.swift:416:45:416:45 | ptr | +| string.swift:416:9:416:9 | SSA def(buffer) | string.swift:417:29:417:29 | buffer | +| string.swift:416:18:416:59 | call to UnsafeBufferPointer.init(start:count:) | string.swift:416:9:416:9 | SSA def(buffer) | +| string.swift:417:9:417:9 | SSA def(arrayString) | string.swift:419:15:419:15 | arrayString | +| string.swift:417:23:417:35 | call to Array.init(_:) | string.swift:417:9:417:9 | SSA def(arrayString) | +| string.swift:417:29:417:29 | buffer | string.swift:418:15:418:15 | buffer | +| string.swift:419:15:419:15 | arrayString | string.swift:420:38:420:38 | arrayString | +| string.swift:420:38:420:38 | arrayString | string.swift:420:15:420:49 | call to String.init(platformString:) | +| string.swift:422:3:422:3 | [post] tainted | string.swift:439:3:439:3 | tainted | +| string.swift:422:3:422:3 | tainted | string.swift:439:3:439:3 | tainted | +| string.swift:423:5:423:5 | SSA def(ptr) | string.swift:424:15:424:15 | ptr | +| string.swift:423:5:423:5 | ptr | string.swift:423:5:423:5 | SSA def(ptr) | +| string.swift:424:15:424:15 | ptr | string.swift:425:38:425:38 | ptr | +| string.swift:425:38:425:38 | ptr | string.swift:425:15:425:41 | call to String.init(platformString:) | +| string.swift:425:38:425:38 | ptr | string.swift:427:45:427:45 | ptr | +| string.swift:427:9:427:9 | SSA def(buffer) | string.swift:428:29:428:29 | buffer | +| string.swift:427:18:427:59 | call to UnsafeBufferPointer.init(start:count:) | string.swift:427:9:427:9 | SSA def(buffer) | +| string.swift:428:9:428:9 | SSA def(arrayString) | string.swift:430:15:430:15 | arrayString | +| string.swift:428:23:428:35 | call to Array.init(_:) | string.swift:428:9:428:9 | SSA def(arrayString) | +| string.swift:428:29:428:29 | buffer | string.swift:429:15:429:15 | buffer | +| string.swift:430:15:430:15 | arrayString | string.swift:431:38:431:38 | arrayString | +| string.swift:431:38:431:38 | arrayString | string.swift:431:15:431:49 | call to String.init(platformString:) | +| string.swift:435:5:435:5 | SSA def(ptr) | string.swift:436:15:436:15 | ptr | +| string.swift:435:5:435:5 | ptr | string.swift:435:5:435:5 | SSA def(ptr) | +| string.swift:436:15:436:15 | ptr | string.swift:437:15:437:15 | ptr | +| string.swift:437:15:437:19 | .baseAddress | string.swift:437:15:437:30 | ...! | +| string.swift:440:5:440:5 | SSA def(ptr) | string.swift:441:15:441:15 | ptr | +| string.swift:440:5:440:5 | ptr | string.swift:440:5:440:5 | SSA def(ptr) | +| string.swift:441:15:441:15 | ptr | string.swift:442:15:442:15 | ptr | +| string.swift:442:15:442:19 | .baseAddress | string.swift:442:15:442:30 | ...! | +| string.swift:449:7:449:31 | SSA def(cleanUInt8Values) | string.swift:469:27:469:27 | cleanUInt8Values | +| string.swift:449:35:449:55 | [...] | string.swift:449:7:449:31 | SSA def(cleanUInt8Values) | +| string.swift:450:7:450:7 | SSA def(taintedUInt8Values) | string.swift:470:27:470:27 | taintedUInt8Values | +| string.swift:450:28:450:36 | call to source4() | string.swift:450:7:450:7 | SSA def(taintedUInt8Values) | +| string.swift:453:6:453:46 | SSA def(buffer) | string.swift:454:17:454:17 | buffer | +| string.swift:453:6:453:46 | buffer | string.swift:453:6:453:46 | SSA def(buffer) | +| string.swift:454:17:454:17 | buffer | string.swift:455:15:455:15 | buffer | +| string.swift:455:15:455:15 | [post] buffer | string.swift:456:17:456:17 | buffer | +| string.swift:455:15:455:15 | buffer | string.swift:456:17:456:17 | buffer | +| string.swift:461:6:461:46 | SSA def(buffer) | string.swift:462:17:462:17 | buffer | +| string.swift:461:6:461:46 | buffer | string.swift:461:6:461:46 | SSA def(buffer) | +| string.swift:462:17:462:17 | buffer | string.swift:463:15:463:15 | buffer | +| string.swift:463:15:463:15 | [post] buffer | string.swift:464:17:464:17 | buffer | +| string.swift:463:15:463:15 | buffer | string.swift:464:17:464:17 | buffer | +| string.swift:469:13:469:75 | call to String.init(bytes:encoding:) | string.swift:469:13:469:76 | ...! | +| string.swift:469:27:469:27 | cleanUInt8Values | string.swift:469:13:469:75 | call to String.init(bytes:encoding:) | +| string.swift:469:27:469:27 | cleanUInt8Values | string.swift:472:29:472:29 | cleanUInt8Values | +| string.swift:470:13:470:77 | call to String.init(bytes:encoding:) | string.swift:470:13:470:78 | ...! | +| string.swift:470:27:470:27 | taintedUInt8Values | string.swift:470:13:470:77 | call to String.init(bytes:encoding:) | +| string.swift:470:27:470:27 | taintedUInt8Values | string.swift:473:29:473:29 | taintedUInt8Values | +| string.swift:472:29:472:29 | cleanUInt8Values | string.swift:472:13:472:45 | call to String.init(cString:) | +| string.swift:472:29:472:29 | cleanUInt8Values | string.swift:475:8:475:8 | cleanUInt8Values | +| string.swift:473:29:473:29 | taintedUInt8Values | string.swift:473:13:473:47 | call to String.init(cString:) | +| string.swift:473:29:473:29 | taintedUInt8Values | string.swift:481:8:481:8 | taintedUInt8Values | +| string.swift:475:8:475:8 | [post] cleanUInt8Values | string.swift:488:8:488:8 | cleanUInt8Values | +| string.swift:475:8:475:8 | cleanUInt8Values | string.swift:488:8:488:8 | cleanUInt8Values | +| string.swift:475:8:480:4 | call to withUnsafeBufferPointer(_:) | string.swift:475:3:480:4 | try! ... | +| string.swift:476:6:476:39 | SSA def(buffer) | string.swift:477:15:477:15 | buffer | +| string.swift:476:6:476:39 | buffer | string.swift:476:6:476:39 | SSA def(buffer) | +| string.swift:477:15:477:15 | buffer | string.swift:478:15:478:15 | buffer | +| string.swift:478:15:478:15 | [post] buffer | string.swift:479:31:479:31 | buffer | +| string.swift:478:15:478:15 | buffer | string.swift:479:31:479:31 | buffer | +| string.swift:478:15:478:22 | .baseAddress | string.swift:478:15:478:33 | ...! | +| string.swift:479:31:479:38 | .baseAddress | string.swift:479:31:479:49 | ...! | +| string.swift:479:31:479:49 | ...! | string.swift:479:15:479:50 | call to String.init(cString:) | +| string.swift:481:8:481:8 | [post] taintedUInt8Values | string.swift:494:8:494:8 | taintedUInt8Values | +| string.swift:481:8:481:8 | taintedUInt8Values | string.swift:494:8:494:8 | taintedUInt8Values | +| string.swift:481:8:486:4 | call to withUnsafeBufferPointer(_:) | string.swift:481:3:486:4 | try! ... | +| string.swift:482:6:482:39 | SSA def(buffer) | string.swift:483:15:483:15 | buffer | +| string.swift:482:6:482:39 | buffer | string.swift:482:6:482:39 | SSA def(buffer) | +| string.swift:483:15:483:15 | buffer | string.swift:484:15:484:15 | buffer | +| string.swift:484:15:484:15 | [post] buffer | string.swift:485:31:485:31 | buffer | +| string.swift:484:15:484:15 | buffer | string.swift:485:31:485:31 | buffer | +| string.swift:484:15:484:22 | .baseAddress | string.swift:484:15:484:33 | ...! | +| string.swift:485:31:485:38 | .baseAddress | string.swift:485:31:485:49 | ...! | +| string.swift:485:31:485:49 | ...! | string.swift:485:15:485:50 | call to String.init(cString:) | +| string.swift:488:8:488:8 | cleanUInt8Values | string.swift:488:8:488:8 | &... | +| string.swift:488:8:493:4 | call to withUnsafeMutableBytes(_:) | string.swift:488:3:493:4 | try! ... | +| string.swift:489:6:489:14 | SSA def(buffer) | string.swift:490:15:490:15 | buffer | +| string.swift:489:6:489:14 | buffer | string.swift:489:6:489:14 | SSA def(buffer) | +| string.swift:490:15:490:15 | [post] buffer | string.swift:491:15:491:15 | buffer | +| string.swift:490:15:490:15 | buffer | string.swift:491:15:491:15 | buffer | +| string.swift:491:15:491:15 | [post] buffer | string.swift:492:35:492:35 | buffer | +| string.swift:491:15:491:15 | buffer | string.swift:492:35:492:35 | buffer | +| string.swift:491:15:491:22 | .baseAddress | string.swift:491:15:491:33 | ...! | +| string.swift:492:15:492:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | string.swift:492:15:492:130 | ...! | +| string.swift:492:35:492:35 | [post] buffer | string.swift:492:64:492:64 | buffer | +| string.swift:492:35:492:35 | buffer | string.swift:492:64:492:64 | buffer | +| string.swift:492:35:492:42 | .baseAddress | string.swift:492:35:492:53 | ...! | +| string.swift:492:35:492:53 | ...! | string.swift:492:15:492:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | +| string.swift:494:8:494:8 | taintedUInt8Values | string.swift:494:8:494:8 | &... | +| string.swift:494:8:499:4 | call to withUnsafeMutableBytes(_:) | string.swift:494:3:499:4 | try! ... | +| string.swift:495:6:495:14 | SSA def(buffer) | string.swift:496:15:496:15 | buffer | +| string.swift:495:6:495:14 | buffer | string.swift:495:6:495:14 | SSA def(buffer) | +| string.swift:496:15:496:15 | [post] buffer | string.swift:497:15:497:15 | buffer | +| string.swift:496:15:496:15 | buffer | string.swift:497:15:497:15 | buffer | +| string.swift:497:15:497:15 | [post] buffer | string.swift:498:35:498:35 | buffer | +| string.swift:497:15:497:15 | buffer | string.swift:498:35:498:35 | buffer | +| string.swift:497:15:497:22 | .baseAddress | string.swift:497:15:497:33 | ...! | +| string.swift:498:15:498:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | string.swift:498:15:498:130 | ...! | +| string.swift:498:35:498:35 | [post] buffer | string.swift:498:64:498:64 | buffer | +| string.swift:498:35:498:35 | buffer | string.swift:498:64:498:64 | buffer | +| string.swift:498:35:498:42 | .baseAddress | string.swift:498:35:498:53 | ...! | +| string.swift:498:35:498:53 | ...! | string.swift:498:15:498:129 | call to String.init(bytesNoCopy:length:encoding:freeWhenDone:) | +| string.swift:505:7:505:31 | SSA def(cleanCCharValues) | string.swift:508:3:508:3 | cleanCCharValues | +| string.swift:505:35:505:55 | [...] | string.swift:505:7:505:31 | SSA def(cleanCCharValues) | +| string.swift:506:7:506:33 | SSA def(taintedCCharValues) | string.swift:516:3:516:3 | taintedCCharValues | +| string.swift:506:37:506:45 | call to source5() | string.swift:506:7:506:33 | SSA def(taintedCCharValues) | +| string.swift:508:3:508:3 | [post] cleanCCharValues | string.swift:525:29:525:29 | cleanCCharValues | +| string.swift:508:3:508:3 | cleanCCharValues | string.swift:525:29:525:29 | cleanCCharValues | +| string.swift:509:5:509:5 | SSA def(ptr) | string.swift:510:15:510:15 | ptr | +| string.swift:509:5:509:5 | ptr | string.swift:509:5:509:5 | SSA def(ptr) | +| string.swift:510:15:510:15 | ptr | string.swift:511:15:511:15 | ptr | +| string.swift:511:15:511:15 | [post] ptr | string.swift:512:34:512:34 | ptr | +| string.swift:511:15:511:15 | ptr | string.swift:512:34:512:34 | ptr | +| string.swift:511:15:511:19 | .baseAddress | string.swift:511:15:511:30 | ...! | +| string.swift:512:15:512:50 | call to String.init(utf8String:) | string.swift:512:15:512:51 | ...! | +| string.swift:512:34:512:34 | [post] ptr | string.swift:513:38:513:38 | ptr | +| string.swift:512:34:512:34 | ptr | string.swift:513:38:513:38 | ptr | +| string.swift:512:34:512:38 | .baseAddress | string.swift:512:34:512:49 | ...! | +| string.swift:512:34:512:49 | ...! | string.swift:512:15:512:50 | call to String.init(utf8String:) | +| string.swift:513:15:513:54 | call to String.init(validatingUTF8:) | string.swift:513:15:513:55 | ...! | +| string.swift:513:38:513:38 | [post] ptr | string.swift:514:31:514:31 | ptr | +| string.swift:513:38:513:38 | ptr | string.swift:514:31:514:31 | ptr | +| string.swift:513:38:513:42 | .baseAddress | string.swift:513:38:513:53 | ...! | +| string.swift:513:38:513:53 | ...! | string.swift:513:15:513:54 | call to String.init(validatingUTF8:) | +| string.swift:514:31:514:35 | .baseAddress | string.swift:514:31:514:46 | ...! | +| string.swift:514:31:514:46 | ...! | string.swift:514:15:514:47 | call to String.init(cString:) | +| string.swift:516:3:516:3 | [post] taintedCCharValues | string.swift:526:29:526:29 | taintedCCharValues | +| string.swift:516:3:516:3 | taintedCCharValues | string.swift:526:29:526:29 | taintedCCharValues | +| string.swift:517:5:517:5 | SSA def(ptr) | string.swift:518:15:518:15 | ptr | +| string.swift:517:5:517:5 | ptr | string.swift:517:5:517:5 | SSA def(ptr) | +| string.swift:518:15:518:15 | ptr | string.swift:519:15:519:15 | ptr | +| string.swift:519:15:519:15 | [post] ptr | string.swift:520:34:520:34 | ptr | +| string.swift:519:15:519:15 | ptr | string.swift:520:34:520:34 | ptr | +| string.swift:519:15:519:19 | .baseAddress | string.swift:519:15:519:30 | ...! | +| string.swift:520:15:520:50 | call to String.init(utf8String:) | string.swift:520:15:520:51 | ...! | +| string.swift:520:34:520:34 | [post] ptr | string.swift:521:38:521:38 | ptr | +| string.swift:520:34:520:34 | ptr | string.swift:521:38:521:38 | ptr | +| string.swift:520:34:520:38 | .baseAddress | string.swift:520:34:520:49 | ...! | +| string.swift:520:34:520:49 | ...! | string.swift:520:15:520:50 | call to String.init(utf8String:) | +| string.swift:521:15:521:54 | call to String.init(validatingUTF8:) | string.swift:521:15:521:55 | ...! | +| string.swift:521:38:521:38 | [post] ptr | string.swift:522:31:522:31 | ptr | +| string.swift:521:38:521:38 | ptr | string.swift:522:31:522:31 | ptr | +| string.swift:521:38:521:42 | .baseAddress | string.swift:521:38:521:53 | ...! | +| string.swift:521:38:521:53 | ...! | string.swift:521:15:521:54 | call to String.init(validatingUTF8:) | +| string.swift:522:31:522:35 | .baseAddress | string.swift:522:31:522:46 | ...! | +| string.swift:522:31:522:46 | ...! | string.swift:522:15:522:47 | call to String.init(cString:) | +| string.swift:525:29:525:29 | cleanCCharValues | string.swift:525:13:525:45 | call to String.init(cString:) | +| string.swift:526:29:526:29 | taintedCCharValues | string.swift:526:13:526:47 | call to String.init(cString:) | +| string.swift:532:7:532:35 | SSA def(cleanUnicharValues) | string.swift:535:3:535:3 | cleanUnicharValues | +| string.swift:532:39:532:59 | [...] | string.swift:532:7:532:35 | SSA def(cleanUnicharValues) | +| string.swift:533:7:533:37 | SSA def(taintedUnicharValues) | string.swift:542:3:542:3 | taintedUnicharValues | +| string.swift:533:41:533:49 | call to source6() | string.swift:533:7:533:37 | SSA def(taintedUnicharValues) | +| string.swift:536:5:536:5 | SSA def(ptr) | string.swift:537:15:537:15 | ptr | +| string.swift:536:5:536:5 | ptr | string.swift:536:5:536:5 | SSA def(ptr) | +| string.swift:537:15:537:15 | ptr | string.swift:538:15:538:15 | ptr | +| string.swift:538:15:538:15 | [post] ptr | string.swift:539:38:539:38 | ptr | +| string.swift:538:15:538:15 | ptr | string.swift:539:38:539:38 | ptr | +| string.swift:538:15:538:19 | .baseAddress | string.swift:538:15:538:30 | ...! | +| string.swift:539:38:539:38 | [post] ptr | string.swift:539:63:539:63 | ptr | +| string.swift:539:38:539:38 | ptr | string.swift:539:63:539:63 | ptr | +| string.swift:539:38:539:42 | .baseAddress | string.swift:539:38:539:53 | ...! | +| string.swift:539:38:539:53 | ...! | string.swift:539:15:539:72 | call to String.init(utf16CodeUnits:count:) | +| string.swift:539:63:539:63 | [post] ptr | string.swift:540:44:540:44 | ptr | +| string.swift:539:63:539:63 | ptr | string.swift:540:44:540:44 | ptr | +| string.swift:540:44:540:44 | [post] ptr | string.swift:540:69:540:69 | ptr | +| string.swift:540:44:540:44 | ptr | string.swift:540:69:540:69 | ptr | +| string.swift:540:44:540:48 | .baseAddress | string.swift:540:44:540:59 | ...! | +| string.swift:540:44:540:59 | ...! | string.swift:540:15:540:99 | call to String.init(utf16CodeUnitsNoCopy:count:freeWhenDone:) | +| string.swift:543:5:543:5 | SSA def(ptr) | string.swift:544:15:544:15 | ptr | +| string.swift:543:5:543:5 | ptr | string.swift:543:5:543:5 | SSA def(ptr) | +| string.swift:544:15:544:15 | ptr | string.swift:545:15:545:15 | ptr | +| string.swift:545:15:545:15 | [post] ptr | string.swift:546:38:546:38 | ptr | +| string.swift:545:15:545:15 | ptr | string.swift:546:38:546:38 | ptr | +| string.swift:545:15:545:19 | .baseAddress | string.swift:545:15:545:30 | ...! | +| string.swift:546:38:546:38 | [post] ptr | string.swift:546:63:546:63 | ptr | +| string.swift:546:38:546:38 | ptr | string.swift:546:63:546:63 | ptr | +| string.swift:546:38:546:42 | .baseAddress | string.swift:546:38:546:53 | ...! | +| string.swift:546:38:546:53 | ...! | string.swift:546:15:546:72 | call to String.init(utf16CodeUnits:count:) | +| string.swift:546:63:546:63 | [post] ptr | string.swift:547:44:547:44 | ptr | +| string.swift:546:63:546:63 | ptr | string.swift:547:44:547:44 | ptr | +| string.swift:547:44:547:44 | [post] ptr | string.swift:547:69:547:69 | ptr | +| string.swift:547:44:547:44 | ptr | string.swift:547:69:547:69 | ptr | +| string.swift:547:44:547:48 | .baseAddress | string.swift:547:44:547:59 | ...! | +| string.swift:547:44:547:59 | ...! | string.swift:547:15:547:99 | call to String.init(utf16CodeUnitsNoCopy:count:freeWhenDone:) | +| string.swift:554:7:554:7 | SSA def(tainted) | string.swift:558:14:558:14 | tainted | +| string.swift:554:17:554:25 | call to source2() | string.swift:554:7:554:7 | SSA def(tainted) | +| string.swift:558:7:558:7 | SSA def(sub1) | string.swift:559:13:559:13 | sub1 | +| string.swift:558:14:558:14 | [post] tainted | string.swift:558:22:558:22 | tainted | +| string.swift:558:14:558:14 | tainted | string.swift:558:14:558:61 | ...[...] | +| string.swift:558:14:558:14 | tainted | string.swift:558:22:558:22 | tainted | +| string.swift:558:14:558:61 | ...[...] | string.swift:558:7:558:7 | SSA def(sub1) | +| string.swift:558:22:558:22 | [post] tainted | string.swift:558:45:558:45 | tainted | +| string.swift:558:22:558:22 | tainted | string.swift:558:45:558:45 | tainted | +| string.swift:558:45:558:45 | [post] tainted | string.swift:562:14:562:14 | tainted | +| string.swift:558:45:558:45 | tainted | string.swift:562:14:562:14 | tainted | +| string.swift:559:13:559:13 | [post] sub1 | string.swift:560:20:560:20 | sub1 | +| string.swift:559:13:559:13 | sub1 | string.swift:560:20:560:20 | sub1 | +| string.swift:560:20:560:20 | sub1 | string.swift:560:13:560:24 | call to String.init(_:) | +| string.swift:562:7:562:7 | SSA def(sub2) | string.swift:563:13:563:13 | sub2 | +| string.swift:562:14:562:14 | [post] tainted | string.swift:566:14:566:14 | tainted | +| string.swift:562:14:562:14 | tainted | string.swift:562:14:562:31 | call to prefix(_:) | +| string.swift:562:14:562:14 | tainted | string.swift:566:14:566:14 | tainted | +| string.swift:562:14:562:31 | call to prefix(_:) | string.swift:562:7:562:7 | SSA def(sub2) | +| string.swift:563:13:563:13 | sub2 | string.swift:564:20:564:20 | sub2 | +| string.swift:564:20:564:20 | sub2 | string.swift:564:13:564:24 | call to String.init(_:) | +| string.swift:566:7:566:7 | SSA def(sub3) | string.swift:567:13:567:13 | sub3 | +| string.swift:566:14:566:14 | [post] tainted | string.swift:566:38:566:38 | tainted | +| string.swift:566:14:566:14 | tainted | string.swift:566:14:566:54 | call to prefix(through:) | +| string.swift:566:14:566:14 | tainted | string.swift:566:38:566:38 | tainted | +| string.swift:566:14:566:54 | call to prefix(through:) | string.swift:566:7:566:7 | SSA def(sub3) | +| string.swift:566:38:566:38 | [post] tainted | string.swift:570:14:570:14 | tainted | +| string.swift:566:38:566:38 | tainted | string.swift:570:14:570:14 | tainted | +| string.swift:567:13:567:13 | sub3 | string.swift:568:20:568:20 | sub3 | +| string.swift:568:20:568:20 | sub3 | string.swift:568:13:568:24 | call to String.init(_:) | +| string.swift:570:7:570:7 | SSA def(sub4) | string.swift:571:13:571:13 | sub4 | +| string.swift:570:14:570:14 | [post] tainted | string.swift:570:35:570:35 | tainted | +| string.swift:570:14:570:14 | tainted | string.swift:570:14:570:51 | call to prefix(upTo:) | +| string.swift:570:14:570:14 | tainted | string.swift:570:35:570:35 | tainted | +| string.swift:570:14:570:51 | call to prefix(upTo:) | string.swift:570:7:570:7 | SSA def(sub4) | +| string.swift:570:35:570:35 | [post] tainted | string.swift:574:14:574:14 | tainted | +| string.swift:570:35:570:35 | tainted | string.swift:574:14:574:14 | tainted | +| string.swift:571:13:571:13 | sub4 | string.swift:572:20:572:20 | sub4 | +| string.swift:572:20:572:20 | sub4 | string.swift:572:13:572:24 | call to String.init(_:) | +| string.swift:574:7:574:7 | SSA def(sub5) | string.swift:575:13:575:13 | sub5 | +| string.swift:574:14:574:14 | [post] tainted | string.swift:578:14:578:14 | tainted | +| string.swift:574:14:574:14 | tainted | string.swift:574:14:574:31 | call to suffix(_:) | +| string.swift:574:14:574:14 | tainted | string.swift:578:14:578:14 | tainted | +| string.swift:574:14:574:31 | call to suffix(_:) | string.swift:574:7:574:7 | SSA def(sub5) | +| string.swift:575:13:575:13 | sub5 | string.swift:576:20:576:20 | sub5 | +| string.swift:576:20:576:20 | sub5 | string.swift:576:13:576:24 | call to String.init(_:) | +| string.swift:578:7:578:7 | SSA def(sub6) | string.swift:579:13:579:13 | sub6 | +| string.swift:578:14:578:14 | [post] tainted | string.swift:578:35:578:35 | tainted | +| string.swift:578:14:578:14 | tainted | string.swift:578:14:578:53 | call to suffix(from:) | +| string.swift:578:14:578:14 | tainted | string.swift:578:35:578:35 | tainted | +| string.swift:578:14:578:53 | call to suffix(from:) | string.swift:578:7:578:7 | SSA def(sub6) | +| string.swift:579:13:579:13 | sub6 | string.swift:580:20:580:20 | sub6 | +| string.swift:580:20:580:20 | sub6 | string.swift:580:13:580:24 | call to String.init(_:) | +| string.swift:584:7:584:7 | SSA def(clean) | string.swift:587:13:587:13 | clean | +| string.swift:584:15:584:26 | call to FilePath.init(_:) | string.swift:584:7:584:7 | SSA def(clean) | +| string.swift:585:7:585:7 | SSA def(tainted) | string.swift:588:13:588:13 | tainted | +| string.swift:585:17:585:35 | call to FilePath.init(_:) | string.swift:585:7:585:7 | SSA def(tainted) | +| string.swift:587:13:587:13 | [post] clean | string.swift:599:11:599:11 | clean | +| string.swift:587:13:587:13 | clean | string.swift:599:11:599:11 | clean | +| string.swift:588:13:588:13 | [post] tainted | string.swift:590:13:590:13 | tainted | +| string.swift:588:13:588:13 | tainted | string.swift:590:13:590:13 | tainted | +| string.swift:590:13:590:13 | [post] tainted | string.swift:591:13:591:13 | tainted | +| string.swift:590:13:590:13 | tainted | string.swift:591:13:591:13 | tainted | +| string.swift:590:13:590:21 | .extension | string.swift:590:13:590:30 | ...! | +| string.swift:591:13:591:13 | [post] tainted | string.swift:592:13:592:13 | tainted | +| string.swift:591:13:591:13 | tainted | string.swift:592:13:592:13 | tainted | +| string.swift:591:13:591:21 | .stem | string.swift:591:13:591:25 | ...! | +| string.swift:592:13:592:13 | [post] tainted | string.swift:593:13:593:13 | tainted | +| string.swift:592:13:592:13 | tainted | string.swift:593:13:593:13 | tainted | +| string.swift:593:13:593:13 | [post] tainted | string.swift:594:13:594:13 | tainted | +| string.swift:593:13:593:13 | tainted | string.swift:594:13:594:13 | tainted | +| string.swift:594:13:594:13 | [post] tainted | string.swift:596:30:596:30 | tainted | +| string.swift:594:13:594:13 | tainted | string.swift:596:30:596:30 | tainted | +| string.swift:596:30:596:30 | [post] tainted | string.swift:597:32:597:32 | tainted | +| string.swift:596:30:596:30 | tainted | string.swift:596:13:596:37 | call to String.init(decoding:) | +| string.swift:596:30:596:30 | tainted | string.swift:597:32:597:32 | tainted | +| string.swift:597:13:597:39 | call to String.init(validating:) | string.swift:597:13:597:40 | ...! | +| string.swift:597:32:597:32 | [post] tainted | string.swift:603:11:603:11 | tainted | +| string.swift:597:32:597:32 | tainted | string.swift:597:13:597:39 | call to String.init(validating:) | +| string.swift:597:32:597:32 | tainted | string.swift:603:11:603:11 | tainted | +| string.swift:599:11:599:11 | [post] clean | string.swift:608:11:608:11 | clean | +| string.swift:599:11:599:11 | clean | string.swift:608:11:608:11 | clean | +| string.swift:600:5:600:5 | SSA def(ptr) | string.swift:601:15:601:15 | ptr | +| string.swift:600:5:600:5 | ptr | string.swift:600:5:600:5 | SSA def(ptr) | +| string.swift:603:11:603:11 | [post] tainted | string.swift:614:11:614:11 | tainted | +| string.swift:603:11:603:11 | tainted | string.swift:614:11:614:11 | tainted | +| string.swift:604:5:604:5 | SSA def(ptr) | string.swift:605:15:605:15 | ptr | +| string.swift:604:5:604:5 | ptr | string.swift:604:5:604:5 | SSA def(ptr) | +| string.swift:608:11:608:11 | [post] clean | string.swift:628:13:628:13 | clean | +| string.swift:608:11:608:11 | clean | string.swift:628:13:628:13 | clean | +| string.swift:609:5:609:5 | SSA def(ptr) | string.swift:610:15:610:15 | ptr | +| string.swift:609:5:609:5 | ptr | string.swift:609:5:609:5 | SSA def(ptr) | +| string.swift:610:15:610:15 | ptr | string.swift:611:38:611:38 | ptr | +| string.swift:611:38:611:38 | ptr | string.swift:611:15:611:41 | call to String.init(platformString:) | +| string.swift:611:38:611:38 | ptr | string.swift:612:48:612:48 | ptr | +| string.swift:612:15:612:51 | call to String.init(validatingPlatformString:) | string.swift:612:15:612:52 | ...! | +| string.swift:612:48:612:48 | ptr | string.swift:612:15:612:51 | call to String.init(validatingPlatformString:) | +| string.swift:614:11:614:11 | [post] tainted | string.swift:630:13:630:13 | tainted | +| string.swift:614:11:614:11 | tainted | string.swift:630:13:630:13 | tainted | +| string.swift:615:5:615:5 | SSA def(ptr) | string.swift:616:15:616:15 | ptr | +| string.swift:615:5:615:5 | ptr | string.swift:615:5:615:5 | SSA def(ptr) | +| string.swift:616:15:616:15 | ptr | string.swift:617:38:617:38 | ptr | +| string.swift:617:38:617:38 | ptr | string.swift:617:15:617:41 | call to String.init(platformString:) | +| string.swift:617:38:617:38 | ptr | string.swift:618:48:618:48 | ptr | +| string.swift:618:15:618:51 | call to String.init(validatingPlatformString:) | string.swift:618:15:618:52 | ...! | +| string.swift:618:48:618:48 | ptr | string.swift:618:15:618:51 | call to String.init(validatingPlatformString:) | +| string.swift:621:7:621:7 | SSA def(fp1) | string.swift:622:13:622:13 | fp1 | +| string.swift:621:13:621:24 | call to FilePath.init(_:) | string.swift:621:7:621:7 | SSA def(fp1) | +| string.swift:622:13:622:13 | [post] fp1 | string.swift:623:3:623:3 | fp1 | +| string.swift:622:13:622:13 | fp1 | string.swift:623:3:623:3 | fp1 | +| string.swift:623:3:623:3 | &... | string.swift:624:13:624:13 | fp1 | +| string.swift:623:3:623:3 | [post] &... | string.swift:624:13:624:13 | fp1 | +| string.swift:623:3:623:3 | fp1 | string.swift:623:3:623:3 | &... | +| string.swift:624:13:624:13 | [post] fp1 | string.swift:625:3:625:3 | fp1 | +| string.swift:624:13:624:13 | fp1 | string.swift:625:3:625:3 | fp1 | +| string.swift:625:3:625:3 | &... | string.swift:626:13:626:13 | fp1 | +| string.swift:625:3:625:3 | [post] &... | string.swift:626:13:626:13 | fp1 | +| string.swift:625:3:625:3 | fp1 | string.swift:625:3:625:3 | &... | +| string.swift:628:13:628:13 | [post] clean | string.swift:629:13:629:13 | clean | +| string.swift:628:13:628:13 | clean | string.swift:629:13:629:13 | clean | +| string.swift:630:13:630:13 | [post] tainted | string.swift:631:13:631:13 | tainted | +| string.swift:630:13:630:13 | tainted | string.swift:631:13:631:13 | tainted | +| string.swift:635:20:635:20 | 0 | string.swift:635:13:635:21 | call to String.init(_:) | +| string.swift:636:20:636:27 | call to source() | string.swift:636:13:636:28 | call to String.init(_:) | +| string.swift:639:32:639:32 | 0 | string.swift:639:13:639:33 | call to String.init(describing:) | +| string.swift:640:32:640:39 | call to source() | string.swift:640:13:640:40 | call to String.init(describing:) | +| string.swift:642:13:642:22 | call to Self.init(_:) | string.swift:642:13:642:23 | ...! | +| string.swift:643:13:643:26 | call to Self.init(_:) | string.swift:643:13:643:27 | ...! | +| string.swift:647:7:647:7 | SSA def(tainted) | string.swift:651:13:651:13 | tainted | +| string.swift:647:17:647:25 | call to source2() | string.swift:647:7:647:7 | SSA def(tainted) | | subscript.swift:1:7:1:7 | SSA def(self) | subscript.swift:1:7:1:7 | self[return] | | subscript.swift:1:7:1:7 | SSA def(self) | subscript.swift:1:7:1:7 | self[return] | | subscript.swift:1:7:1:7 | self | subscript.swift:1:7:1:7 | SSA def(self) | diff --git a/swift/ql/test/library-tests/dataflow/taint/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/Taint.expected index 462ad33a929..1ea47a03460 100644 --- a/swift/ql/test/library-tests/dataflow/taint/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/Taint.expected @@ -331,6 +331,17 @@ edges | nsmutabledata.swift:48:33:48:40 | call to source() : | nsmutabledata.swift:49:15:49:37 | .mutableBytes | | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 : | nsmutabledata.swift:13:9:13:9 | self : | | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 : | nsmutabledata.swift:49:15:49:37 | .mutableBytes | +| simple.swift:12:17:12:24 | call to source() : | simple.swift:12:13:12:24 | ... .+(_:_:) ... | +| simple.swift:13:13:13:20 | call to source() : | simple.swift:13:13:13:24 | ... .+(_:_:) ... | +| simple.swift:14:17:14:24 | call to source() : | simple.swift:14:13:14:24 | ... .-(_:_:) ... | +| simple.swift:15:13:15:20 | call to source() : | simple.swift:15:13:15:24 | ... .-(_:_:) ... | +| simple.swift:16:17:16:24 | call to source() : | simple.swift:16:13:16:24 | ... .*(_:_:) ... | +| simple.swift:17:13:17:20 | call to source() : | simple.swift:17:13:17:24 | ... .*(_:_:) ... | +| simple.swift:18:19:18:26 | call to source() : | simple.swift:18:13:18:26 | ... ./(_:_:) ... | +| simple.swift:19:13:19:20 | call to source() : | simple.swift:19:13:19:24 | ... ./(_:_:) ... | +| simple.swift:20:19:20:26 | call to source() : | simple.swift:20:13:20:26 | ... .%(_:_:) ... | +| simple.swift:21:13:21:20 | call to source() : | simple.swift:21:13:21:24 | ... .%(_:_:) ... | +| simple.swift:23:14:23:21 | call to source() : | simple.swift:23:13:23:21 | call to -(_:) | | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(data:encoding:) : | | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:_:) : | | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:arguments:) : | @@ -338,250 +349,262 @@ edges | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:locale:arguments:) : | | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in localizedStringWithFormat(_:_:) : | | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(bytes:encoding:) : | -| string.swift:98:3:98:63 | [summary param] this in lowercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased(with:) : | -| string.swift:99:3:99:63 | [summary param] this in uppercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased(with:) : | -| string.swift:100:3:100:64 | [summary param] this in capitalized(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in capitalized(with:) : | -| string.swift:101:3:101:64 | [summary param] this in substring(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in substring(from:) : | -| string.swift:102:3:102:71 | [summary param] this in trimmingCharacters(in:) : | file://:0:0:0:0 | [summary] to write: return (return) in trimmingCharacters(in:) : | -| string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | -| string.swift:103:3:103:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | -| string.swift:104:3:104:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | file://:0:0:0:0 | [summary] to write: return (return) in padding(toLength:withPad:startingAt:) : | -| string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | -| string.swift:106:3:106:92 | [summary param] this in folding(options:locale:) : | file://:0:0:0:0 | [summary] to write: return (return) in folding(options:locale:) : | -| string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | -| string.swift:108:3:108:74 | [summary param] this in cString(using:) : | file://:0:0:0:0 | [summary] to write: return (return) in cString(using:) : | -| string.swift:109:8:109:8 | self : | string.swift:109:3:109:79 | self[return] : | -| string.swift:132:11:132:18 | call to source() : | string.swift:134:13:134:13 | "..." | -| string.swift:132:11:132:18 | call to source() : | string.swift:136:13:136:13 | "..." | -| string.swift:132:11:132:18 | call to source() : | string.swift:138:13:138:13 | "..." | -| string.swift:132:11:132:18 | call to source() : | string.swift:144:13:144:13 | "..." | -| string.swift:132:11:132:18 | call to source() : | string.swift:146:13:146:13 | "..." | -| string.swift:156:17:156:25 | call to source2() : | string.swift:159:13:159:13 | tainted | -| string.swift:156:17:156:25 | call to source2() : | string.swift:162:13:162:21 | ... .+(_:_:) ... | -| string.swift:156:17:156:25 | call to source2() : | string.swift:163:13:163:23 | ... .+(_:_:) ... | -| string.swift:156:17:156:25 | call to source2() : | string.swift:164:13:164:23 | ... .+(_:_:) ... | -| string.swift:156:17:156:25 | call to source2() : | string.swift:167:13:167:29 | ... .+(_:_:) ... | -| string.swift:156:17:156:25 | call to source2() : | string.swift:170:29:170:29 | tainted : | -| string.swift:156:17:156:25 | call to source2() : | string.swift:171:13:171:13 | tainted : | -| string.swift:156:17:156:25 | call to source2() : | string.swift:172:13:172:13 | tainted : | -| string.swift:156:17:156:25 | call to source2() : | string.swift:172:31:172:31 | tainted : | -| string.swift:170:29:170:29 | tainted : | string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | -| string.swift:170:29:170:29 | tainted : | string.swift:170:13:170:36 | call to appending(_:) | -| string.swift:171:13:171:13 | tainted : | string.swift:103:3:103:82 | [summary param] this in appending(_:) : | -| string.swift:171:13:171:13 | tainted : | string.swift:171:13:171:36 | call to appending(_:) | -| string.swift:172:13:172:13 | tainted : | string.swift:103:3:103:82 | [summary param] this in appending(_:) : | -| string.swift:172:13:172:13 | tainted : | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:172:31:172:31 | tainted : | string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | -| string.swift:172:31:172:31 | tainted : | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:185:3:185:3 | [post] &... : | string.swift:186:13:186:13 | str2 | -| string.swift:185:15:185:23 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(_:) : | -| string.swift:185:15:185:23 | call to source2() : | string.swift:185:3:185:3 | [post] &... : | -| string.swift:192:3:192:3 | [post] &... : | string.swift:193:13:193:13 | str3 | -| string.swift:192:27:192:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(contentsOf:) : | -| string.swift:192:27:192:35 | call to source2() : | string.swift:192:3:192:3 | [post] &... : | -| string.swift:199:3:199:3 | [post] &... : | string.swift:200:13:200:13 | str4 | -| string.swift:199:14:199:22 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in write(_:) : | -| string.swift:199:14:199:22 | call to source2() : | string.swift:199:3:199:3 | [post] &... : | -| string.swift:206:3:206:3 | [post] &... : | string.swift:207:13:207:13 | str5 | -| string.swift:206:27:206:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in insert(contentsOf:at:) : | -| string.swift:206:27:206:35 | call to source2() : | string.swift:206:3:206:3 | [post] &... : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:216:20:216:20 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:219:28:219:28 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:220:28:220:28 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:221:28:221:28 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:222:28:222:28 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:223:46:223:46 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:228:31:228:31 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:230:13:230:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:231:13:231:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:232:13:232:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:234:13:234:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:235:13:235:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:236:13:236:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:237:13:237:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:238:13:238:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:239:13:239:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:241:13:241:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:242:13:242:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:245:13:245:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:246:13:246:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:247:13:247:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:248:13:248:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:249:13:249:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:250:13:250:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:251:13:251:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:258:13:258:13 | tainted : | -| string.swift:212:17:212:25 | call to source2() : | string.swift:270:13:270:21 | .description | -| string.swift:212:17:212:25 | call to source2() : | string.swift:272:13:272:21 | .debugDescription | -| string.swift:212:17:212:25 | call to source2() : | string.swift:274:13:274:21 | .utf8 | -| string.swift:212:17:212:25 | call to source2() : | string.swift:276:13:276:21 | .utf16 | -| string.swift:212:17:212:25 | call to source2() : | string.swift:278:13:278:21 | .unicodeScalars | -| string.swift:212:17:212:25 | call to source2() : | string.swift:280:13:280:21 | .utf8CString | -| string.swift:212:17:212:25 | call to source2() : | string.swift:282:13:282:21 | .lazy | -| string.swift:212:17:212:25 | call to source2() : | string.swift:284:13:284:21 | .capitalized | -| string.swift:212:17:212:25 | call to source2() : | string.swift:286:13:286:21 | .localizedCapitalized | -| string.swift:212:17:212:25 | call to source2() : | string.swift:288:13:288:21 | .localizedLowercase | -| string.swift:212:17:212:25 | call to source2() : | string.swift:290:13:290:21 | .localizedUppercase | -| string.swift:212:17:212:25 | call to source2() : | string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | -| string.swift:212:17:212:25 | call to source2() : | string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | -| string.swift:212:17:212:25 | call to source2() : | string.swift:296:13:296:44 | ...! | -| string.swift:213:20:213:27 | call to source() : | string.swift:217:20:217:20 | taintedInt : | -| string.swift:216:20:216:20 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:216:20:216:20 | tainted : | string.swift:216:13:216:27 | call to String.init(_:) | -| string.swift:217:20:217:20 | taintedInt : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:217:20:217:20 | taintedInt : | string.swift:217:13:217:30 | call to String.init(_:) | -| string.swift:219:28:219:28 | tainted : | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | -| string.swift:219:28:219:28 | tainted : | string.swift:219:13:219:44 | call to String.init(format:_:) | -| string.swift:220:28:220:28 | tainted : | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | -| string.swift:220:28:220:28 | tainted : | string.swift:220:13:220:50 | call to String.init(format:arguments:) | -| string.swift:221:28:221:28 | tainted : | string.swift:66:3:66:75 | [summary param] 0 in String.init(format:locale:_:) : | -| string.swift:221:28:221:28 | tainted : | string.swift:221:13:221:57 | call to String.init(format:locale:_:) | -| string.swift:222:28:222:28 | tainted : | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | -| string.swift:222:28:222:28 | tainted : | string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | -| string.swift:223:46:223:46 | tainted : | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | -| string.swift:223:46:223:46 | tainted : | string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | -| string.swift:228:31:228:31 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(repeating:count:) : | -| string.swift:228:31:228:31 | tainted : | string.swift:228:13:228:48 | call to String.init(repeating:count:) | -| string.swift:230:13:230:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropFirst(_:) : | -| string.swift:230:13:230:13 | tainted : | string.swift:230:13:230:33 | call to dropFirst(_:) | -| string.swift:231:13:231:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropLast(_:) : | -| string.swift:231:13:231:13 | tainted : | string.swift:231:13:231:32 | call to dropLast(_:) | -| string.swift:232:13:232:13 | tainted : | string.swift:101:3:101:64 | [summary param] this in substring(from:) : | -| string.swift:232:13:232:13 | tainted : | string.swift:232:13:232:55 | call to substring(from:) | -| string.swift:234:13:234:13 | tainted : | file://:0:0:0:0 | [summary param] this in lowercased() : | -| string.swift:234:13:234:13 | tainted : | string.swift:234:13:234:32 | call to lowercased() | -| string.swift:235:13:235:13 | tainted : | file://:0:0:0:0 | [summary param] this in uppercased() : | -| string.swift:235:13:235:13 | tainted : | string.swift:235:13:235:32 | call to uppercased() | -| string.swift:236:13:236:13 | tainted : | string.swift:98:3:98:63 | [summary param] this in lowercased(with:) : | -| string.swift:236:13:236:13 | tainted : | string.swift:236:13:236:41 | call to lowercased(with:) | -| string.swift:237:13:237:13 | tainted : | string.swift:99:3:99:63 | [summary param] this in uppercased(with:) : | -| string.swift:237:13:237:13 | tainted : | string.swift:237:13:237:41 | call to uppercased(with:) | -| string.swift:238:13:238:13 | tainted : | string.swift:100:3:100:64 | [summary param] this in capitalized(with:) : | -| string.swift:238:13:238:13 | tainted : | string.swift:238:13:238:42 | call to capitalized(with:) | -| string.swift:239:13:239:13 | tainted : | file://:0:0:0:0 | [summary param] this in reversed() : | -| string.swift:239:13:239:13 | tainted : | string.swift:239:13:239:30 | call to reversed() | -| string.swift:241:13:241:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(separator:maxSplits:omittingEmptySubsequences:) : | -| string.swift:241:13:241:13 | tainted : | string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | -| string.swift:242:13:242:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | -| string.swift:242:13:242:13 | tainted : | string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | -| string.swift:245:13:245:13 | tainted : | string.swift:102:3:102:71 | [summary param] this in trimmingCharacters(in:) : | -| string.swift:245:13:245:13 | tainted : | string.swift:245:13:245:68 | call to trimmingCharacters(in:) | -| string.swift:246:13:246:13 | tainted : | string.swift:104:3:104:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | -| string.swift:246:13:246:13 | tainted : | string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | -| string.swift:247:13:247:13 | tainted : | string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | -| string.swift:247:13:247:13 | tainted : | string.swift:247:13:247:69 | call to components(separatedBy:) | -| string.swift:248:13:248:13 | tainted : | string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | -| string.swift:248:13:248:13 | tainted : | string.swift:248:13:248:69 | call to components(separatedBy:) : | -| string.swift:248:13:248:69 | call to components(separatedBy:) : | string.swift:248:13:248:72 | ...[...] | -| string.swift:249:13:249:13 | tainted : | string.swift:106:3:106:92 | [summary param] this in folding(options:locale:) : | -| string.swift:249:13:249:13 | tainted : | string.swift:249:13:249:40 | call to folding(options:locale:) | -| string.swift:250:13:250:13 | tainted : | string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | -| string.swift:250:13:250:13 | tainted : | string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | -| string.swift:251:13:251:13 | tainted : | string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | -| string.swift:251:13:251:13 | tainted : | string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() : | -| string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() : | string.swift:251:13:251:63 | ...! | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:270:13:270:21 | .description | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:272:13:272:21 | .debugDescription | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:274:13:274:21 | .utf8 | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:276:13:276:21 | .utf16 | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:278:13:278:21 | .unicodeScalars | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:280:13:280:21 | .utf8CString | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:282:13:282:21 | .lazy | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:284:13:284:21 | .capitalized | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:286:13:286:21 | .localizedCapitalized | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:288:13:288:21 | .localizedLowercase | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:290:13:290:21 | .localizedUppercase | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | -| string.swift:258:13:258:13 | [post] tainted : | string.swift:296:13:296:44 | ...! | -| string.swift:258:13:258:13 | tainted : | string.swift:109:8:109:8 | self : | -| string.swift:258:13:258:13 | tainted : | string.swift:258:13:258:13 | [post] tainted : | -| string.swift:300:14:300:22 | call to source2() : | string.swift:301:13:301:13 | str1 | -| string.swift:300:14:300:22 | call to source2() : | string.swift:302:13:302:13 | &... : | -| string.swift:300:14:300:22 | call to source2() : | string.swift:303:13:303:13 | str1 | -| string.swift:302:13:302:13 | &... : | file://:0:0:0:0 | [summary param] this in remove(at:) : | -| string.swift:302:13:302:13 | &... : | string.swift:302:13:302:44 | call to remove(at:) | -| string.swift:305:14:305:22 | call to source2() : | string.swift:306:13:306:13 | str2 | -| string.swift:305:14:305:22 | call to source2() : | string.swift:308:13:308:13 | str2 | -| string.swift:310:14:310:22 | call to source2() : | string.swift:311:13:311:13 | str3 | -| string.swift:310:14:310:22 | call to source2() : | string.swift:313:13:313:13 | str3 | -| string.swift:315:14:315:22 | call to source2() : | string.swift:316:13:316:13 | str4 | -| string.swift:315:14:315:22 | call to source2() : | string.swift:317:13:317:13 | &... : | -| string.swift:315:14:315:22 | call to source2() : | string.swift:318:13:318:13 | str4 | -| string.swift:315:14:315:22 | call to source2() : | string.swift:320:13:320:13 | str4 | -| string.swift:315:14:315:22 | call to source2() : | string.swift:321:13:321:13 | &... : | -| string.swift:315:14:315:22 | call to source2() : | string.swift:322:13:322:13 | str4 | -| string.swift:315:14:315:22 | call to source2() : | string.swift:324:13:324:13 | str4 | -| string.swift:317:13:317:13 | &... : | file://:0:0:0:0 | [summary param] this in removeFirst() : | -| string.swift:317:13:317:13 | &... : | string.swift:317:13:317:30 | call to removeFirst() | -| string.swift:321:13:321:13 | &... : | file://:0:0:0:0 | [summary param] this in removeLast() : | -| string.swift:321:13:321:13 | &... : | string.swift:321:13:321:29 | call to removeLast() | -| string.swift:326:14:326:22 | call to source2() : | string.swift:327:13:327:13 | str5 | -| string.swift:326:14:326:22 | call to source2() : | string.swift:329:13:329:13 | str5 | -| string.swift:331:14:331:22 | call to source2() : | string.swift:332:13:332:13 | str6 | -| string.swift:331:14:331:22 | call to source2() : | string.swift:334:13:334:13 | str6 | -| string.swift:341:23:341:77 | call to String.init(data:encoding:) : | string.swift:344:12:344:25 | ...! | -| string.swift:341:36:341:44 | call to source3() : | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | -| string.swift:341:36:341:44 | call to source3() : | string.swift:341:23:341:77 | call to String.init(data:encoding:) : | -| string.swift:347:30:347:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | -| string.swift:347:30:347:38 | call to source3() : | string.swift:347:13:347:54 | call to String.init(decoding:as:) | -| string.swift:352:17:352:25 | call to source2() : | string.swift:389:22:389:22 | tainted : | -| string.swift:389:22:389:22 | tainted : | string.swift:108:3:108:74 | [summary param] this in cString(using:) : | -| string.swift:389:22:389:22 | tainted : | string.swift:389:22:389:65 | call to cString(using:) : | -| string.swift:389:22:389:65 | call to cString(using:) : | string.swift:390:13:390:13 | arrayString2 | -| string.swift:436:28:436:36 | call to source4() : | string.swift:456:27:456:27 | taintedUInt8Values : | -| string.swift:436:28:436:36 | call to source4() : | string.swift:459:29:459:29 | taintedUInt8Values : | -| string.swift:456:13:456:77 | call to String.init(bytes:encoding:) : | string.swift:456:13:456:78 | ...! | -| string.swift:456:27:456:27 | taintedUInt8Values : | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | -| string.swift:456:27:456:27 | taintedUInt8Values : | string.swift:456:13:456:77 | call to String.init(bytes:encoding:) : | -| string.swift:459:29:459:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | -| string.swift:459:29:459:29 | taintedUInt8Values : | string.swift:459:13:459:47 | call to String.init(cString:) | -| string.swift:492:37:492:45 | call to source5() : | string.swift:512:29:512:29 | taintedCCharValues : | -| string.swift:512:29:512:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | -| string.swift:512:29:512:29 | taintedCCharValues : | string.swift:512:13:512:47 | call to String.init(cString:) | -| string.swift:540:17:540:25 | call to source2() : | string.swift:545:13:545:13 | sub1 | -| string.swift:540:17:540:25 | call to source2() : | string.swift:546:20:546:20 | sub1 : | -| string.swift:540:17:540:25 | call to source2() : | string.swift:548:14:548:14 | tainted : | -| string.swift:540:17:540:25 | call to source2() : | string.swift:552:14:552:14 | tainted : | -| string.swift:540:17:540:25 | call to source2() : | string.swift:556:14:556:14 | tainted : | -| string.swift:540:17:540:25 | call to source2() : | string.swift:560:14:560:14 | tainted : | -| string.swift:540:17:540:25 | call to source2() : | string.swift:564:14:564:14 | tainted : | -| string.swift:546:20:546:20 | sub1 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:546:20:546:20 | sub1 : | string.swift:546:13:546:24 | call to String.init(_:) | -| string.swift:548:14:548:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(_:) : | -| string.swift:548:14:548:14 | tainted : | string.swift:548:14:548:31 | call to prefix(_:) : | -| string.swift:548:14:548:31 | call to prefix(_:) : | string.swift:549:13:549:13 | sub2 | -| string.swift:548:14:548:31 | call to prefix(_:) : | string.swift:550:20:550:20 | sub2 : | -| string.swift:550:20:550:20 | sub2 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:550:20:550:20 | sub2 : | string.swift:550:13:550:24 | call to String.init(_:) | -| string.swift:552:14:552:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(through:) : | -| string.swift:552:14:552:14 | tainted : | string.swift:552:14:552:54 | call to prefix(through:) : | -| string.swift:552:14:552:54 | call to prefix(through:) : | string.swift:553:13:553:13 | sub3 | -| string.swift:552:14:552:54 | call to prefix(through:) : | string.swift:554:20:554:20 | sub3 : | -| string.swift:554:20:554:20 | sub3 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:554:20:554:20 | sub3 : | string.swift:554:13:554:24 | call to String.init(_:) | -| string.swift:556:14:556:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(upTo:) : | -| string.swift:556:14:556:14 | tainted : | string.swift:556:14:556:51 | call to prefix(upTo:) : | -| string.swift:556:14:556:51 | call to prefix(upTo:) : | string.swift:557:13:557:13 | sub4 | -| string.swift:556:14:556:51 | call to prefix(upTo:) : | string.swift:558:20:558:20 | sub4 : | -| string.swift:558:20:558:20 | sub4 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:558:20:558:20 | sub4 : | string.swift:558:13:558:24 | call to String.init(_:) | -| string.swift:560:14:560:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(_:) : | -| string.swift:560:14:560:14 | tainted : | string.swift:560:14:560:31 | call to suffix(_:) : | -| string.swift:560:14:560:31 | call to suffix(_:) : | string.swift:561:13:561:13 | sub5 | -| string.swift:560:14:560:31 | call to suffix(_:) : | string.swift:562:20:562:20 | sub5 : | -| string.swift:562:20:562:20 | sub5 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:562:20:562:20 | sub5 : | string.swift:562:13:562:24 | call to String.init(_:) | -| string.swift:564:14:564:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(from:) : | -| string.swift:564:14:564:14 | tainted : | string.swift:564:14:564:53 | call to suffix(from:) : | -| string.swift:564:14:564:53 | call to suffix(from:) : | string.swift:565:13:565:13 | sub6 | -| string.swift:564:14:564:53 | call to suffix(from:) : | string.swift:566:20:566:20 | sub6 : | -| string.swift:566:20:566:20 | sub6 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:566:20:566:20 | sub6 : | string.swift:566:13:566:24 | call to String.init(_:) | -| string.swift:622:20:622:27 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | -| string.swift:622:20:622:27 | call to source() : | string.swift:622:13:622:28 | call to String.init(_:) | -| string.swift:626:32:626:39 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(describing:) : | -| string.swift:626:32:626:39 | call to source() : | string.swift:626:13:626:40 | call to String.init(describing:) | +| string.swift:86:12:87:51 | [summary param] 1 in replaceSubrange(_:with:) : | file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:) : | +| string.swift:101:3:101:63 | [summary param] this in lowercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased(with:) : | +| string.swift:102:3:102:63 | [summary param] this in uppercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased(with:) : | +| string.swift:103:3:103:64 | [summary param] this in capitalized(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in capitalized(with:) : | +| string.swift:104:3:104:64 | [summary param] this in substring(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in substring(from:) : | +| string.swift:105:3:105:71 | [summary param] this in trimmingCharacters(in:) : | file://:0:0:0:0 | [summary] to write: return (return) in trimmingCharacters(in:) : | +| string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | +| string.swift:106:3:106:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | +| string.swift:107:3:107:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | file://:0:0:0:0 | [summary] to write: return (return) in padding(toLength:withPad:startingAt:) : | +| string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | +| string.swift:109:3:109:92 | [summary param] this in folding(options:locale:) : | file://:0:0:0:0 | [summary] to write: return (return) in folding(options:locale:) : | +| string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | +| string.swift:111:3:111:74 | [summary param] this in cString(using:) : | file://:0:0:0:0 | [summary] to write: return (return) in cString(using:) : | +| string.swift:112:8:112:8 | self : | string.swift:112:3:112:79 | self[return] : | +| string.swift:113:3:114:77 | [summary param] 1 in replacingOccurrences(of:with:options:range:) : | file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | +| string.swift:113:3:114:77 | [summary param] this in replacingOccurrences(of:with:options:range:) : | file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | +| string.swift:137:11:137:18 | call to source() : | string.swift:139:13:139:13 | "..." | +| string.swift:137:11:137:18 | call to source() : | string.swift:141:13:141:13 | "..." | +| string.swift:137:11:137:18 | call to source() : | string.swift:143:13:143:13 | "..." | +| string.swift:137:11:137:18 | call to source() : | string.swift:149:13:149:13 | "..." | +| string.swift:137:11:137:18 | call to source() : | string.swift:151:13:151:13 | "..." | +| string.swift:161:17:161:25 | call to source2() : | string.swift:164:13:164:13 | tainted | +| string.swift:161:17:161:25 | call to source2() : | string.swift:167:13:167:21 | ... .+(_:_:) ... | +| string.swift:161:17:161:25 | call to source2() : | string.swift:168:13:168:23 | ... .+(_:_:) ... | +| string.swift:161:17:161:25 | call to source2() : | string.swift:169:13:169:23 | ... .+(_:_:) ... | +| string.swift:161:17:161:25 | call to source2() : | string.swift:172:13:172:29 | ... .+(_:_:) ... | +| string.swift:161:17:161:25 | call to source2() : | string.swift:175:29:175:29 | tainted : | +| string.swift:161:17:161:25 | call to source2() : | string.swift:176:13:176:13 | tainted : | +| string.swift:161:17:161:25 | call to source2() : | string.swift:177:13:177:13 | tainted : | +| string.swift:161:17:161:25 | call to source2() : | string.swift:177:31:177:31 | tainted : | +| string.swift:175:29:175:29 | tainted : | string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | +| string.swift:175:29:175:29 | tainted : | string.swift:175:13:175:36 | call to appending(_:) | +| string.swift:176:13:176:13 | tainted : | string.swift:106:3:106:82 | [summary param] this in appending(_:) : | +| string.swift:176:13:176:13 | tainted : | string.swift:176:13:176:36 | call to appending(_:) | +| string.swift:177:13:177:13 | tainted : | string.swift:106:3:106:82 | [summary param] this in appending(_:) : | +| string.swift:177:13:177:13 | tainted : | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:177:31:177:31 | tainted : | string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | +| string.swift:177:31:177:31 | tainted : | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:190:3:190:3 | [post] &... : | string.swift:191:13:191:13 | str2 | +| string.swift:190:15:190:23 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(_:) : | +| string.swift:190:15:190:23 | call to source2() : | string.swift:190:3:190:3 | [post] &... : | +| string.swift:197:3:197:3 | [post] &... : | string.swift:198:13:198:13 | str3 | +| string.swift:197:27:197:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(contentsOf:) : | +| string.swift:197:27:197:35 | call to source2() : | string.swift:197:3:197:3 | [post] &... : | +| string.swift:204:3:204:3 | [post] &... : | string.swift:205:13:205:13 | str4 | +| string.swift:204:14:204:22 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in write(_:) : | +| string.swift:204:14:204:22 | call to source2() : | string.swift:204:3:204:3 | [post] &... : | +| string.swift:211:3:211:3 | [post] &... : | string.swift:212:13:212:13 | str5 | +| string.swift:211:27:211:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in insert(contentsOf:at:) : | +| string.swift:211:27:211:35 | call to source2() : | string.swift:211:3:211:3 | [post] &... : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:221:20:221:20 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:224:28:224:28 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:225:28:225:28 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:226:28:226:28 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:227:28:227:28 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:228:46:228:46 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:233:31:233:31 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:235:13:235:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:236:13:236:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:237:13:237:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:239:13:239:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:240:13:240:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:241:13:241:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:242:13:242:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:243:13:243:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:244:13:244:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:246:13:246:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:247:13:247:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:250:13:250:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:251:13:251:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:252:13:252:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:253:13:253:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:254:13:254:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:255:13:255:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:256:13:256:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:263:13:263:13 | tainted : | +| string.swift:217:17:217:25 | call to source2() : | string.swift:275:13:275:21 | .description | +| string.swift:217:17:217:25 | call to source2() : | string.swift:277:13:277:21 | .debugDescription | +| string.swift:217:17:217:25 | call to source2() : | string.swift:279:13:279:21 | .utf8 | +| string.swift:217:17:217:25 | call to source2() : | string.swift:281:13:281:21 | .utf16 | +| string.swift:217:17:217:25 | call to source2() : | string.swift:283:13:283:21 | .unicodeScalars | +| string.swift:217:17:217:25 | call to source2() : | string.swift:285:13:285:21 | .utf8CString | +| string.swift:217:17:217:25 | call to source2() : | string.swift:287:13:287:21 | .lazy | +| string.swift:217:17:217:25 | call to source2() : | string.swift:289:13:289:21 | .capitalized | +| string.swift:217:17:217:25 | call to source2() : | string.swift:291:13:291:21 | .localizedCapitalized | +| string.swift:217:17:217:25 | call to source2() : | string.swift:293:13:293:21 | .localizedLowercase | +| string.swift:217:17:217:25 | call to source2() : | string.swift:295:13:295:21 | .localizedUppercase | +| string.swift:217:17:217:25 | call to source2() : | string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | +| string.swift:217:17:217:25 | call to source2() : | string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | +| string.swift:217:17:217:25 | call to source2() : | string.swift:301:13:301:44 | ...! | +| string.swift:217:17:217:25 | call to source2() : | string.swift:304:13:304:13 | tainted : | +| string.swift:218:20:218:27 | call to source() : | string.swift:222:20:222:20 | taintedInt : | +| string.swift:221:20:221:20 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:221:20:221:20 | tainted : | string.swift:221:13:221:27 | call to String.init(_:) | +| string.swift:222:20:222:20 | taintedInt : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:222:20:222:20 | taintedInt : | string.swift:222:13:222:30 | call to String.init(_:) | +| string.swift:224:28:224:28 | tainted : | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | +| string.swift:224:28:224:28 | tainted : | string.swift:224:13:224:44 | call to String.init(format:_:) | +| string.swift:225:28:225:28 | tainted : | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | +| string.swift:225:28:225:28 | tainted : | string.swift:225:13:225:50 | call to String.init(format:arguments:) | +| string.swift:226:28:226:28 | tainted : | string.swift:66:3:66:75 | [summary param] 0 in String.init(format:locale:_:) : | +| string.swift:226:28:226:28 | tainted : | string.swift:226:13:226:57 | call to String.init(format:locale:_:) | +| string.swift:227:28:227:28 | tainted : | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | +| string.swift:227:28:227:28 | tainted : | string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | +| string.swift:228:46:228:46 | tainted : | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | +| string.swift:228:46:228:46 | tainted : | string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | +| string.swift:233:31:233:31 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(repeating:count:) : | +| string.swift:233:31:233:31 | tainted : | string.swift:233:13:233:48 | call to String.init(repeating:count:) | +| string.swift:235:13:235:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropFirst(_:) : | +| string.swift:235:13:235:13 | tainted : | string.swift:235:13:235:33 | call to dropFirst(_:) | +| string.swift:236:13:236:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropLast(_:) : | +| string.swift:236:13:236:13 | tainted : | string.swift:236:13:236:32 | call to dropLast(_:) | +| string.swift:237:13:237:13 | tainted : | string.swift:104:3:104:64 | [summary param] this in substring(from:) : | +| string.swift:237:13:237:13 | tainted : | string.swift:237:13:237:55 | call to substring(from:) | +| string.swift:239:13:239:13 | tainted : | file://:0:0:0:0 | [summary param] this in lowercased() : | +| string.swift:239:13:239:13 | tainted : | string.swift:239:13:239:32 | call to lowercased() | +| string.swift:240:13:240:13 | tainted : | file://:0:0:0:0 | [summary param] this in uppercased() : | +| string.swift:240:13:240:13 | tainted : | string.swift:240:13:240:32 | call to uppercased() | +| string.swift:241:13:241:13 | tainted : | string.swift:101:3:101:63 | [summary param] this in lowercased(with:) : | +| string.swift:241:13:241:13 | tainted : | string.swift:241:13:241:41 | call to lowercased(with:) | +| string.swift:242:13:242:13 | tainted : | string.swift:102:3:102:63 | [summary param] this in uppercased(with:) : | +| string.swift:242:13:242:13 | tainted : | string.swift:242:13:242:41 | call to uppercased(with:) | +| string.swift:243:13:243:13 | tainted : | string.swift:103:3:103:64 | [summary param] this in capitalized(with:) : | +| string.swift:243:13:243:13 | tainted : | string.swift:243:13:243:42 | call to capitalized(with:) | +| string.swift:244:13:244:13 | tainted : | file://:0:0:0:0 | [summary param] this in reversed() : | +| string.swift:244:13:244:13 | tainted : | string.swift:244:13:244:30 | call to reversed() | +| string.swift:246:13:246:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(separator:maxSplits:omittingEmptySubsequences:) : | +| string.swift:246:13:246:13 | tainted : | string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | +| string.swift:247:13:247:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | +| string.swift:247:13:247:13 | tainted : | string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | +| string.swift:250:13:250:13 | tainted : | string.swift:105:3:105:71 | [summary param] this in trimmingCharacters(in:) : | +| string.swift:250:13:250:13 | tainted : | string.swift:250:13:250:68 | call to trimmingCharacters(in:) | +| string.swift:251:13:251:13 | tainted : | string.swift:107:3:107:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | +| string.swift:251:13:251:13 | tainted : | string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | +| string.swift:252:13:252:13 | tainted : | string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | +| string.swift:252:13:252:13 | tainted : | string.swift:252:13:252:69 | call to components(separatedBy:) | +| string.swift:253:13:253:13 | tainted : | string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | +| string.swift:253:13:253:13 | tainted : | string.swift:253:13:253:69 | call to components(separatedBy:) : | +| string.swift:253:13:253:69 | call to components(separatedBy:) : | string.swift:253:13:253:72 | ...[...] | +| string.swift:254:13:254:13 | tainted : | string.swift:109:3:109:92 | [summary param] this in folding(options:locale:) : | +| string.swift:254:13:254:13 | tainted : | string.swift:254:13:254:40 | call to folding(options:locale:) | +| string.swift:255:13:255:13 | tainted : | string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | +| string.swift:255:13:255:13 | tainted : | string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | +| string.swift:256:13:256:13 | tainted : | string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | +| string.swift:256:13:256:13 | tainted : | string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() : | +| string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() : | string.swift:256:13:256:63 | ...! | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:275:13:275:21 | .description | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:277:13:277:21 | .debugDescription | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:279:13:279:21 | .utf8 | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:281:13:281:21 | .utf16 | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:283:13:283:21 | .unicodeScalars | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:285:13:285:21 | .utf8CString | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:287:13:287:21 | .lazy | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:289:13:289:21 | .capitalized | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:291:13:291:21 | .localizedCapitalized | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:293:13:293:21 | .localizedLowercase | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:295:13:295:21 | .localizedUppercase | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:301:13:301:44 | ...! | +| string.swift:263:13:263:13 | [post] tainted : | string.swift:304:13:304:13 | tainted : | +| string.swift:263:13:263:13 | tainted : | string.swift:112:8:112:8 | self : | +| string.swift:263:13:263:13 | tainted : | string.swift:263:13:263:13 | [post] tainted : | +| string.swift:304:13:304:13 | tainted : | string.swift:113:3:114:77 | [summary param] this in replacingOccurrences(of:with:options:range:) : | +| string.swift:304:13:304:13 | tainted : | string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:55:305:63 | call to source2() : | string.swift:113:3:114:77 | [summary param] 1 in replacingOccurrences(of:with:options:range:) : | +| string.swift:305:55:305:63 | call to source2() : | string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:309:14:309:22 | call to source2() : | string.swift:310:13:310:13 | str1 | +| string.swift:309:14:309:22 | call to source2() : | string.swift:311:13:311:13 | &... : | +| string.swift:309:14:309:22 | call to source2() : | string.swift:312:13:312:13 | str1 | +| string.swift:311:13:311:13 | &... : | file://:0:0:0:0 | [summary param] this in remove(at:) : | +| string.swift:311:13:311:13 | &... : | string.swift:311:13:311:44 | call to remove(at:) | +| string.swift:314:14:314:22 | call to source2() : | string.swift:315:13:315:13 | str2 | +| string.swift:314:14:314:22 | call to source2() : | string.swift:317:13:317:13 | str2 | +| string.swift:319:14:319:22 | call to source2() : | string.swift:320:13:320:13 | str3 | +| string.swift:319:14:319:22 | call to source2() : | string.swift:322:13:322:13 | str3 | +| string.swift:324:14:324:22 | call to source2() : | string.swift:325:13:325:13 | str4 | +| string.swift:324:14:324:22 | call to source2() : | string.swift:326:13:326:13 | &... : | +| string.swift:324:14:324:22 | call to source2() : | string.swift:327:13:327:13 | str4 | +| string.swift:324:14:324:22 | call to source2() : | string.swift:329:13:329:13 | str4 | +| string.swift:324:14:324:22 | call to source2() : | string.swift:330:13:330:13 | &... : | +| string.swift:324:14:324:22 | call to source2() : | string.swift:331:13:331:13 | str4 | +| string.swift:324:14:324:22 | call to source2() : | string.swift:333:13:333:13 | str4 | +| string.swift:326:13:326:13 | &... : | file://:0:0:0:0 | [summary param] this in removeFirst() : | +| string.swift:326:13:326:13 | &... : | string.swift:326:13:326:30 | call to removeFirst() | +| string.swift:330:13:330:13 | &... : | file://:0:0:0:0 | [summary param] this in removeLast() : | +| string.swift:330:13:330:13 | &... : | string.swift:330:13:330:29 | call to removeLast() | +| string.swift:335:14:335:22 | call to source2() : | string.swift:336:13:336:13 | str5 | +| string.swift:335:14:335:22 | call to source2() : | string.swift:338:13:338:13 | str5 | +| string.swift:340:14:340:22 | call to source2() : | string.swift:341:13:341:13 | str6 | +| string.swift:340:14:340:22 | call to source2() : | string.swift:343:13:343:13 | str6 | +| string.swift:347:3:347:3 | [post] &... : | string.swift:348:13:348:13 | str7 | +| string.swift:347:62:347:70 | call to source2() : | string.swift:86:12:87:51 | [summary param] 1 in replaceSubrange(_:with:) : | +| string.swift:347:62:347:70 | call to source2() : | string.swift:347:3:347:3 | [post] &... : | +| string.swift:355:23:355:77 | call to String.init(data:encoding:) : | string.swift:358:12:358:25 | ...! | +| string.swift:355:36:355:44 | call to source3() : | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | +| string.swift:355:36:355:44 | call to source3() : | string.swift:355:23:355:77 | call to String.init(data:encoding:) : | +| string.swift:361:30:361:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | +| string.swift:361:30:361:38 | call to source3() : | string.swift:361:13:361:54 | call to String.init(decoding:as:) | +| string.swift:366:17:366:25 | call to source2() : | string.swift:403:22:403:22 | tainted : | +| string.swift:403:22:403:22 | tainted : | string.swift:111:3:111:74 | [summary param] this in cString(using:) : | +| string.swift:403:22:403:22 | tainted : | string.swift:403:22:403:65 | call to cString(using:) : | +| string.swift:403:22:403:65 | call to cString(using:) : | string.swift:404:13:404:13 | arrayString2 | +| string.swift:450:28:450:36 | call to source4() : | string.swift:470:27:470:27 | taintedUInt8Values : | +| string.swift:450:28:450:36 | call to source4() : | string.swift:473:29:473:29 | taintedUInt8Values : | +| string.swift:470:13:470:77 | call to String.init(bytes:encoding:) : | string.swift:470:13:470:78 | ...! | +| string.swift:470:27:470:27 | taintedUInt8Values : | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | +| string.swift:470:27:470:27 | taintedUInt8Values : | string.swift:470:13:470:77 | call to String.init(bytes:encoding:) : | +| string.swift:473:29:473:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | +| string.swift:473:29:473:29 | taintedUInt8Values : | string.swift:473:13:473:47 | call to String.init(cString:) | +| string.swift:506:37:506:45 | call to source5() : | string.swift:526:29:526:29 | taintedCCharValues : | +| string.swift:526:29:526:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | +| string.swift:526:29:526:29 | taintedCCharValues : | string.swift:526:13:526:47 | call to String.init(cString:) | +| string.swift:554:17:554:25 | call to source2() : | string.swift:559:13:559:13 | sub1 | +| string.swift:554:17:554:25 | call to source2() : | string.swift:560:20:560:20 | sub1 : | +| string.swift:554:17:554:25 | call to source2() : | string.swift:562:14:562:14 | tainted : | +| string.swift:554:17:554:25 | call to source2() : | string.swift:566:14:566:14 | tainted : | +| string.swift:554:17:554:25 | call to source2() : | string.swift:570:14:570:14 | tainted : | +| string.swift:554:17:554:25 | call to source2() : | string.swift:574:14:574:14 | tainted : | +| string.swift:554:17:554:25 | call to source2() : | string.swift:578:14:578:14 | tainted : | +| string.swift:560:20:560:20 | sub1 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:560:20:560:20 | sub1 : | string.swift:560:13:560:24 | call to String.init(_:) | +| string.swift:562:14:562:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(_:) : | +| string.swift:562:14:562:14 | tainted : | string.swift:562:14:562:31 | call to prefix(_:) : | +| string.swift:562:14:562:31 | call to prefix(_:) : | string.swift:563:13:563:13 | sub2 | +| string.swift:562:14:562:31 | call to prefix(_:) : | string.swift:564:20:564:20 | sub2 : | +| string.swift:564:20:564:20 | sub2 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:564:20:564:20 | sub2 : | string.swift:564:13:564:24 | call to String.init(_:) | +| string.swift:566:14:566:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(through:) : | +| string.swift:566:14:566:14 | tainted : | string.swift:566:14:566:54 | call to prefix(through:) : | +| string.swift:566:14:566:54 | call to prefix(through:) : | string.swift:567:13:567:13 | sub3 | +| string.swift:566:14:566:54 | call to prefix(through:) : | string.swift:568:20:568:20 | sub3 : | +| string.swift:568:20:568:20 | sub3 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:568:20:568:20 | sub3 : | string.swift:568:13:568:24 | call to String.init(_:) | +| string.swift:570:14:570:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(upTo:) : | +| string.swift:570:14:570:14 | tainted : | string.swift:570:14:570:51 | call to prefix(upTo:) : | +| string.swift:570:14:570:51 | call to prefix(upTo:) : | string.swift:571:13:571:13 | sub4 | +| string.swift:570:14:570:51 | call to prefix(upTo:) : | string.swift:572:20:572:20 | sub4 : | +| string.swift:572:20:572:20 | sub4 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:572:20:572:20 | sub4 : | string.swift:572:13:572:24 | call to String.init(_:) | +| string.swift:574:14:574:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(_:) : | +| string.swift:574:14:574:14 | tainted : | string.swift:574:14:574:31 | call to suffix(_:) : | +| string.swift:574:14:574:31 | call to suffix(_:) : | string.swift:575:13:575:13 | sub5 | +| string.swift:574:14:574:31 | call to suffix(_:) : | string.swift:576:20:576:20 | sub5 : | +| string.swift:576:20:576:20 | sub5 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:576:20:576:20 | sub5 : | string.swift:576:13:576:24 | call to String.init(_:) | +| string.swift:578:14:578:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(from:) : | +| string.swift:578:14:578:14 | tainted : | string.swift:578:14:578:53 | call to suffix(from:) : | +| string.swift:578:14:578:53 | call to suffix(from:) : | string.swift:579:13:579:13 | sub6 | +| string.swift:578:14:578:53 | call to suffix(from:) : | string.swift:580:20:580:20 | sub6 : | +| string.swift:580:20:580:20 | sub6 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:580:20:580:20 | sub6 : | string.swift:580:13:580:24 | call to String.init(_:) | +| string.swift:636:20:636:27 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | +| string.swift:636:20:636:27 | call to source() : | string.swift:636:13:636:28 | call to String.init(_:) | +| string.swift:640:32:640:39 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(describing:) : | +| string.swift:640:32:640:39 | call to source() : | string.swift:640:13:640:40 | call to String.init(describing:) | | subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] | | subscript.swift:14:15:14:23 | call to source2() : | subscript.swift:14:15:14:26 | ...[...] | | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | @@ -1097,6 +1120,7 @@ nodes | file://:0:0:0:0 | [summary] to write: argument this in replaceBytes(in:withBytes:length:) : | semmle.label | [summary] to write: argument this in replaceBytes(in:withBytes:length:) : | | file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:) : | semmle.label | [summary] to write: argument this in replaceSubrange(_:with:) : | | file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:) : | semmle.label | [summary] to write: argument this in replaceSubrange(_:with:) : | +| file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:) : | semmle.label | [summary] to write: argument this in replaceSubrange(_:with:) : | | file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:count:) : | semmle.label | [summary] to write: argument this in replaceSubrange(_:with:count:) : | | file://:0:0:0:0 | [summary] to write: argument this in replacing(_:with:maxReplacements:) : | semmle.label | [summary] to write: argument this in replacing(_:with:maxReplacements:) : | | file://:0:0:0:0 | [summary] to write: argument this in replacing(_:with:subrange:maxReplacements:) : | semmle.label | [summary] to write: argument this in replacing(_:with:subrange:maxReplacements:) : | @@ -1187,6 +1211,8 @@ nodes | file://:0:0:0:0 | [summary] to write: return (return) in remove(at:) : | semmle.label | [summary] to write: return (return) in remove(at:) : | | file://:0:0:0:0 | [summary] to write: return (return) in removeFirst() : | semmle.label | [summary] to write: return (return) in removeFirst() : | | file://:0:0:0:0 | [summary] to write: return (return) in removeLast() : | semmle.label | [summary] to write: return (return) in removeLast() : | +| file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | semmle.label | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | +| file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | semmle.label | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | | file://:0:0:0:0 | [summary] to write: return (return) in reversed() : | semmle.label | [summary] to write: return (return) in reversed() : | | file://:0:0:0:0 | [summary] to write: return (return) in reversed() : | semmle.label | [summary] to write: return (return) in reversed() : | | file://:0:0:0:0 | [summary] to write: return (return) in shuffled() : | semmle.label | [summary] to write: return (return) in shuffled() : | @@ -1355,6 +1381,28 @@ nodes | nsmutabledata.swift:48:33:48:40 | call to source() : | semmle.label | call to source() : | | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 : | semmle.label | nsMutableDataTainted6 : | | nsmutabledata.swift:49:15:49:37 | .mutableBytes | semmle.label | .mutableBytes | +| simple.swift:12:13:12:24 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| simple.swift:12:17:12:24 | call to source() : | semmle.label | call to source() : | +| simple.swift:13:13:13:20 | call to source() : | semmle.label | call to source() : | +| simple.swift:13:13:13:24 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| simple.swift:14:13:14:24 | ... .-(_:_:) ... | semmle.label | ... .-(_:_:) ... | +| simple.swift:14:17:14:24 | call to source() : | semmle.label | call to source() : | +| simple.swift:15:13:15:20 | call to source() : | semmle.label | call to source() : | +| simple.swift:15:13:15:24 | ... .-(_:_:) ... | semmle.label | ... .-(_:_:) ... | +| simple.swift:16:13:16:24 | ... .*(_:_:) ... | semmle.label | ... .*(_:_:) ... | +| simple.swift:16:17:16:24 | call to source() : | semmle.label | call to source() : | +| simple.swift:17:13:17:20 | call to source() : | semmle.label | call to source() : | +| simple.swift:17:13:17:24 | ... .*(_:_:) ... | semmle.label | ... .*(_:_:) ... | +| simple.swift:18:13:18:26 | ... ./(_:_:) ... | semmle.label | ... ./(_:_:) ... | +| simple.swift:18:19:18:26 | call to source() : | semmle.label | call to source() : | +| simple.swift:19:13:19:20 | call to source() : | semmle.label | call to source() : | +| simple.swift:19:13:19:24 | ... ./(_:_:) ... | semmle.label | ... ./(_:_:) ... | +| simple.swift:20:13:20:26 | ... .%(_:_:) ... | semmle.label | ... .%(_:_:) ... | +| simple.swift:20:19:20:26 | call to source() : | semmle.label | call to source() : | +| simple.swift:21:13:21:20 | call to source() : | semmle.label | call to source() : | +| simple.swift:21:13:21:24 | ... .%(_:_:) ... | semmle.label | ... .%(_:_:) ... | +| simple.swift:23:13:23:21 | call to -(_:) | semmle.label | call to -(_:) | +| simple.swift:23:14:23:21 | call to source() : | semmle.label | call to source() : | | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | semmle.label | [summary param] 0 in String.init(data:encoding:) : | | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | semmle.label | [summary param] 0 in String.init(format:_:) : | | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | semmle.label | [summary param] 0 in String.init(format:arguments:) : | @@ -1362,202 +1410,212 @@ nodes | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | semmle.label | [summary param] 0 in String.init(format:locale:arguments:) : | | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | semmle.label | [summary param] 0 in localizedStringWithFormat(_:_:) : | | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | semmle.label | [summary param] 0 in String.init(bytes:encoding:) : | -| string.swift:98:3:98:63 | [summary param] this in lowercased(with:) : | semmle.label | [summary param] this in lowercased(with:) : | -| string.swift:99:3:99:63 | [summary param] this in uppercased(with:) : | semmle.label | [summary param] this in uppercased(with:) : | -| string.swift:100:3:100:64 | [summary param] this in capitalized(with:) : | semmle.label | [summary param] this in capitalized(with:) : | -| string.swift:101:3:101:64 | [summary param] this in substring(from:) : | semmle.label | [summary param] this in substring(from:) : | -| string.swift:102:3:102:71 | [summary param] this in trimmingCharacters(in:) : | semmle.label | [summary param] this in trimmingCharacters(in:) : | -| string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | semmle.label | [summary param] 0 in appending(_:) : | -| string.swift:103:3:103:82 | [summary param] this in appending(_:) : | semmle.label | [summary param] this in appending(_:) : | -| string.swift:104:3:104:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | semmle.label | [summary param] this in padding(toLength:withPad:startingAt:) : | -| string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | semmle.label | [summary param] this in components(separatedBy:) : | -| string.swift:106:3:106:92 | [summary param] this in folding(options:locale:) : | semmle.label | [summary param] this in folding(options:locale:) : | -| string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | semmle.label | [summary param] this in propertyListFromStringsFileFormat() : | -| string.swift:108:3:108:74 | [summary param] this in cString(using:) : | semmle.label | [summary param] this in cString(using:) : | -| string.swift:109:3:109:79 | self[return] : | semmle.label | self[return] : | -| string.swift:109:8:109:8 | self : | semmle.label | self : | -| string.swift:132:11:132:18 | call to source() : | semmle.label | call to source() : | -| string.swift:134:13:134:13 | "..." | semmle.label | "..." | -| string.swift:136:13:136:13 | "..." | semmle.label | "..." | -| string.swift:138:13:138:13 | "..." | semmle.label | "..." | -| string.swift:144:13:144:13 | "..." | semmle.label | "..." | -| string.swift:146:13:146:13 | "..." | semmle.label | "..." | -| string.swift:156:17:156:25 | call to source2() : | semmle.label | call to source2() : | -| string.swift:159:13:159:13 | tainted | semmle.label | tainted | -| string.swift:162:13:162:21 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | -| string.swift:163:13:163:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | -| string.swift:164:13:164:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | -| string.swift:167:13:167:29 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | -| string.swift:170:13:170:36 | call to appending(_:) | semmle.label | call to appending(_:) | -| string.swift:170:29:170:29 | tainted : | semmle.label | tainted : | -| string.swift:171:13:171:13 | tainted : | semmle.label | tainted : | -| string.swift:171:13:171:36 | call to appending(_:) | semmle.label | call to appending(_:) | -| string.swift:172:13:172:13 | tainted : | semmle.label | tainted : | -| string.swift:172:13:172:38 | call to appending(_:) | semmle.label | call to appending(_:) | -| string.swift:172:31:172:31 | tainted : | semmle.label | tainted : | -| string.swift:185:3:185:3 | [post] &... : | semmle.label | [post] &... : | -| string.swift:185:15:185:23 | call to source2() : | semmle.label | call to source2() : | -| string.swift:186:13:186:13 | str2 | semmle.label | str2 | -| string.swift:192:3:192:3 | [post] &... : | semmle.label | [post] &... : | -| string.swift:192:27:192:35 | call to source2() : | semmle.label | call to source2() : | -| string.swift:193:13:193:13 | str3 | semmle.label | str3 | -| string.swift:199:3:199:3 | [post] &... : | semmle.label | [post] &... : | -| string.swift:199:14:199:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:200:13:200:13 | str4 | semmle.label | str4 | -| string.swift:206:3:206:3 | [post] &... : | semmle.label | [post] &... : | -| string.swift:206:27:206:35 | call to source2() : | semmle.label | call to source2() : | -| string.swift:207:13:207:13 | str5 | semmle.label | str5 | -| string.swift:212:17:212:25 | call to source2() : | semmle.label | call to source2() : | -| string.swift:213:20:213:27 | call to source() : | semmle.label | call to source() : | -| string.swift:216:13:216:27 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:216:20:216:20 | tainted : | semmle.label | tainted : | -| string.swift:217:13:217:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:217:20:217:20 | taintedInt : | semmle.label | taintedInt : | -| string.swift:219:13:219:44 | call to String.init(format:_:) | semmle.label | call to String.init(format:_:) | -| string.swift:219:28:219:28 | tainted : | semmle.label | tainted : | -| string.swift:220:13:220:50 | call to String.init(format:arguments:) | semmle.label | call to String.init(format:arguments:) | -| string.swift:220:28:220:28 | tainted : | semmle.label | tainted : | -| string.swift:221:13:221:57 | call to String.init(format:locale:_:) | semmle.label | call to String.init(format:locale:_:) | -| string.swift:221:28:221:28 | tainted : | semmle.label | tainted : | -| string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | semmle.label | call to String.init(format:locale:arguments:) | -| string.swift:222:28:222:28 | tainted : | semmle.label | tainted : | -| string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | semmle.label | call to localizedStringWithFormat(_:_:) | -| string.swift:223:46:223:46 | tainted : | semmle.label | tainted : | -| string.swift:228:13:228:48 | call to String.init(repeating:count:) | semmle.label | call to String.init(repeating:count:) | -| string.swift:228:31:228:31 | tainted : | semmle.label | tainted : | -| string.swift:230:13:230:13 | tainted : | semmle.label | tainted : | -| string.swift:230:13:230:33 | call to dropFirst(_:) | semmle.label | call to dropFirst(_:) | -| string.swift:231:13:231:13 | tainted : | semmle.label | tainted : | -| string.swift:231:13:231:32 | call to dropLast(_:) | semmle.label | call to dropLast(_:) | -| string.swift:232:13:232:13 | tainted : | semmle.label | tainted : | -| string.swift:232:13:232:55 | call to substring(from:) | semmle.label | call to substring(from:) | -| string.swift:234:13:234:13 | tainted : | semmle.label | tainted : | -| string.swift:234:13:234:32 | call to lowercased() | semmle.label | call to lowercased() | +| string.swift:86:12:87:51 | [summary param] 1 in replaceSubrange(_:with:) : | semmle.label | [summary param] 1 in replaceSubrange(_:with:) : | +| string.swift:101:3:101:63 | [summary param] this in lowercased(with:) : | semmle.label | [summary param] this in lowercased(with:) : | +| string.swift:102:3:102:63 | [summary param] this in uppercased(with:) : | semmle.label | [summary param] this in uppercased(with:) : | +| string.swift:103:3:103:64 | [summary param] this in capitalized(with:) : | semmle.label | [summary param] this in capitalized(with:) : | +| string.swift:104:3:104:64 | [summary param] this in substring(from:) : | semmle.label | [summary param] this in substring(from:) : | +| string.swift:105:3:105:71 | [summary param] this in trimmingCharacters(in:) : | semmle.label | [summary param] this in trimmingCharacters(in:) : | +| string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | semmle.label | [summary param] 0 in appending(_:) : | +| string.swift:106:3:106:82 | [summary param] this in appending(_:) : | semmle.label | [summary param] this in appending(_:) : | +| string.swift:107:3:107:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | semmle.label | [summary param] this in padding(toLength:withPad:startingAt:) : | +| string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | semmle.label | [summary param] this in components(separatedBy:) : | +| string.swift:109:3:109:92 | [summary param] this in folding(options:locale:) : | semmle.label | [summary param] this in folding(options:locale:) : | +| string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | semmle.label | [summary param] this in propertyListFromStringsFileFormat() : | +| string.swift:111:3:111:74 | [summary param] this in cString(using:) : | semmle.label | [summary param] this in cString(using:) : | +| string.swift:112:3:112:79 | self[return] : | semmle.label | self[return] : | +| string.swift:112:8:112:8 | self : | semmle.label | self : | +| string.swift:113:3:114:77 | [summary param] 1 in replacingOccurrences(of:with:options:range:) : | semmle.label | [summary param] 1 in replacingOccurrences(of:with:options:range:) : | +| string.swift:113:3:114:77 | [summary param] this in replacingOccurrences(of:with:options:range:) : | semmle.label | [summary param] this in replacingOccurrences(of:with:options:range:) : | +| string.swift:137:11:137:18 | call to source() : | semmle.label | call to source() : | +| string.swift:139:13:139:13 | "..." | semmle.label | "..." | +| string.swift:141:13:141:13 | "..." | semmle.label | "..." | +| string.swift:143:13:143:13 | "..." | semmle.label | "..." | +| string.swift:149:13:149:13 | "..." | semmle.label | "..." | +| string.swift:151:13:151:13 | "..." | semmle.label | "..." | +| string.swift:161:17:161:25 | call to source2() : | semmle.label | call to source2() : | +| string.swift:164:13:164:13 | tainted | semmle.label | tainted | +| string.swift:167:13:167:21 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| string.swift:168:13:168:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| string.swift:169:13:169:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| string.swift:172:13:172:29 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| string.swift:175:13:175:36 | call to appending(_:) | semmle.label | call to appending(_:) | +| string.swift:175:29:175:29 | tainted : | semmle.label | tainted : | +| string.swift:176:13:176:13 | tainted : | semmle.label | tainted : | +| string.swift:176:13:176:36 | call to appending(_:) | semmle.label | call to appending(_:) | +| string.swift:177:13:177:13 | tainted : | semmle.label | tainted : | +| string.swift:177:13:177:38 | call to appending(_:) | semmle.label | call to appending(_:) | +| string.swift:177:31:177:31 | tainted : | semmle.label | tainted : | +| string.swift:190:3:190:3 | [post] &... : | semmle.label | [post] &... : | +| string.swift:190:15:190:23 | call to source2() : | semmle.label | call to source2() : | +| string.swift:191:13:191:13 | str2 | semmle.label | str2 | +| string.swift:197:3:197:3 | [post] &... : | semmle.label | [post] &... : | +| string.swift:197:27:197:35 | call to source2() : | semmle.label | call to source2() : | +| string.swift:198:13:198:13 | str3 | semmle.label | str3 | +| string.swift:204:3:204:3 | [post] &... : | semmle.label | [post] &... : | +| string.swift:204:14:204:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:205:13:205:13 | str4 | semmle.label | str4 | +| string.swift:211:3:211:3 | [post] &... : | semmle.label | [post] &... : | +| string.swift:211:27:211:35 | call to source2() : | semmle.label | call to source2() : | +| string.swift:212:13:212:13 | str5 | semmle.label | str5 | +| string.swift:217:17:217:25 | call to source2() : | semmle.label | call to source2() : | +| string.swift:218:20:218:27 | call to source() : | semmle.label | call to source() : | +| string.swift:221:13:221:27 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:221:20:221:20 | tainted : | semmle.label | tainted : | +| string.swift:222:13:222:30 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:222:20:222:20 | taintedInt : | semmle.label | taintedInt : | +| string.swift:224:13:224:44 | call to String.init(format:_:) | semmle.label | call to String.init(format:_:) | +| string.swift:224:28:224:28 | tainted : | semmle.label | tainted : | +| string.swift:225:13:225:50 | call to String.init(format:arguments:) | semmle.label | call to String.init(format:arguments:) | +| string.swift:225:28:225:28 | tainted : | semmle.label | tainted : | +| string.swift:226:13:226:57 | call to String.init(format:locale:_:) | semmle.label | call to String.init(format:locale:_:) | +| string.swift:226:28:226:28 | tainted : | semmle.label | tainted : | +| string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | semmle.label | call to String.init(format:locale:arguments:) | +| string.swift:227:28:227:28 | tainted : | semmle.label | tainted : | +| string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | semmle.label | call to localizedStringWithFormat(_:_:) | +| string.swift:228:46:228:46 | tainted : | semmle.label | tainted : | +| string.swift:233:13:233:48 | call to String.init(repeating:count:) | semmle.label | call to String.init(repeating:count:) | +| string.swift:233:31:233:31 | tainted : | semmle.label | tainted : | | string.swift:235:13:235:13 | tainted : | semmle.label | tainted : | -| string.swift:235:13:235:32 | call to uppercased() | semmle.label | call to uppercased() | +| string.swift:235:13:235:33 | call to dropFirst(_:) | semmle.label | call to dropFirst(_:) | | string.swift:236:13:236:13 | tainted : | semmle.label | tainted : | -| string.swift:236:13:236:41 | call to lowercased(with:) | semmle.label | call to lowercased(with:) | +| string.swift:236:13:236:32 | call to dropLast(_:) | semmle.label | call to dropLast(_:) | | string.swift:237:13:237:13 | tainted : | semmle.label | tainted : | -| string.swift:237:13:237:41 | call to uppercased(with:) | semmle.label | call to uppercased(with:) | -| string.swift:238:13:238:13 | tainted : | semmle.label | tainted : | -| string.swift:238:13:238:42 | call to capitalized(with:) | semmle.label | call to capitalized(with:) | +| string.swift:237:13:237:55 | call to substring(from:) | semmle.label | call to substring(from:) | | string.swift:239:13:239:13 | tainted : | semmle.label | tainted : | -| string.swift:239:13:239:30 | call to reversed() | semmle.label | call to reversed() | +| string.swift:239:13:239:32 | call to lowercased() | semmle.label | call to lowercased() | +| string.swift:240:13:240:13 | tainted : | semmle.label | tainted : | +| string.swift:240:13:240:32 | call to uppercased() | semmle.label | call to uppercased() | | string.swift:241:13:241:13 | tainted : | semmle.label | tainted : | -| string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | semmle.label | call to split(separator:maxSplits:omittingEmptySubsequences:) | +| string.swift:241:13:241:41 | call to lowercased(with:) | semmle.label | call to lowercased(with:) | | string.swift:242:13:242:13 | tainted : | semmle.label | tainted : | -| string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | semmle.label | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | -| string.swift:245:13:245:13 | tainted : | semmle.label | tainted : | -| string.swift:245:13:245:68 | call to trimmingCharacters(in:) | semmle.label | call to trimmingCharacters(in:) | +| string.swift:242:13:242:41 | call to uppercased(with:) | semmle.label | call to uppercased(with:) | +| string.swift:243:13:243:13 | tainted : | semmle.label | tainted : | +| string.swift:243:13:243:42 | call to capitalized(with:) | semmle.label | call to capitalized(with:) | +| string.swift:244:13:244:13 | tainted : | semmle.label | tainted : | +| string.swift:244:13:244:30 | call to reversed() | semmle.label | call to reversed() | | string.swift:246:13:246:13 | tainted : | semmle.label | tainted : | -| string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | semmle.label | call to padding(toLength:withPad:startingAt:) | +| string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | semmle.label | call to split(separator:maxSplits:omittingEmptySubsequences:) | | string.swift:247:13:247:13 | tainted : | semmle.label | tainted : | -| string.swift:247:13:247:69 | call to components(separatedBy:) | semmle.label | call to components(separatedBy:) | -| string.swift:248:13:248:13 | tainted : | semmle.label | tainted : | -| string.swift:248:13:248:69 | call to components(separatedBy:) : | semmle.label | call to components(separatedBy:) : | -| string.swift:248:13:248:72 | ...[...] | semmle.label | ...[...] | -| string.swift:249:13:249:13 | tainted : | semmle.label | tainted : | -| string.swift:249:13:249:40 | call to folding(options:locale:) | semmle.label | call to folding(options:locale:) | +| string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | semmle.label | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | | string.swift:250:13:250:13 | tainted : | semmle.label | tainted : | -| string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | semmle.label | call to propertyListFromStringsFileFormat() | +| string.swift:250:13:250:68 | call to trimmingCharacters(in:) | semmle.label | call to trimmingCharacters(in:) | | string.swift:251:13:251:13 | tainted : | semmle.label | tainted : | -| string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() : | semmle.label | call to propertyListFromStringsFileFormat() : | -| string.swift:251:13:251:63 | ...! | semmle.label | ...! | -| string.swift:258:13:258:13 | [post] tainted : | semmle.label | [post] tainted : | -| string.swift:258:13:258:13 | tainted : | semmle.label | tainted : | -| string.swift:270:13:270:21 | .description | semmle.label | .description | -| string.swift:272:13:272:21 | .debugDescription | semmle.label | .debugDescription | -| string.swift:274:13:274:21 | .utf8 | semmle.label | .utf8 | -| string.swift:276:13:276:21 | .utf16 | semmle.label | .utf16 | -| string.swift:278:13:278:21 | .unicodeScalars | semmle.label | .unicodeScalars | -| string.swift:280:13:280:21 | .utf8CString | semmle.label | .utf8CString | -| string.swift:282:13:282:21 | .lazy | semmle.label | .lazy | -| string.swift:284:13:284:21 | .capitalized | semmle.label | .capitalized | -| string.swift:286:13:286:21 | .localizedCapitalized | semmle.label | .localizedCapitalized | -| string.swift:288:13:288:21 | .localizedLowercase | semmle.label | .localizedLowercase | -| string.swift:290:13:290:21 | .localizedUppercase | semmle.label | .localizedUppercase | -| string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | semmle.label | .decomposedStringWithCanonicalMapping | -| string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | semmle.label | .precomposedStringWithCompatibilityMapping | -| string.swift:296:13:296:44 | ...! | semmle.label | ...! | -| string.swift:300:14:300:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:301:13:301:13 | str1 | semmle.label | str1 | -| string.swift:302:13:302:13 | &... : | semmle.label | &... : | -| string.swift:302:13:302:44 | call to remove(at:) | semmle.label | call to remove(at:) | -| string.swift:303:13:303:13 | str1 | semmle.label | str1 | -| string.swift:305:14:305:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:306:13:306:13 | str2 | semmle.label | str2 | -| string.swift:308:13:308:13 | str2 | semmle.label | str2 | -| string.swift:310:14:310:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:311:13:311:13 | str3 | semmle.label | str3 | -| string.swift:313:13:313:13 | str3 | semmle.label | str3 | -| string.swift:315:14:315:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:316:13:316:13 | str4 | semmle.label | str4 | -| string.swift:317:13:317:13 | &... : | semmle.label | &... : | -| string.swift:317:13:317:30 | call to removeFirst() | semmle.label | call to removeFirst() | -| string.swift:318:13:318:13 | str4 | semmle.label | str4 | -| string.swift:320:13:320:13 | str4 | semmle.label | str4 | -| string.swift:321:13:321:13 | &... : | semmle.label | &... : | -| string.swift:321:13:321:29 | call to removeLast() | semmle.label | call to removeLast() | -| string.swift:322:13:322:13 | str4 | semmle.label | str4 | -| string.swift:324:13:324:13 | str4 | semmle.label | str4 | -| string.swift:326:14:326:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:327:13:327:13 | str5 | semmle.label | str5 | -| string.swift:329:13:329:13 | str5 | semmle.label | str5 | -| string.swift:331:14:331:22 | call to source2() : | semmle.label | call to source2() : | -| string.swift:332:13:332:13 | str6 | semmle.label | str6 | -| string.swift:334:13:334:13 | str6 | semmle.label | str6 | -| string.swift:341:23:341:77 | call to String.init(data:encoding:) : | semmle.label | call to String.init(data:encoding:) : | -| string.swift:341:36:341:44 | call to source3() : | semmle.label | call to source3() : | -| string.swift:344:12:344:25 | ...! | semmle.label | ...! | -| string.swift:347:13:347:54 | call to String.init(decoding:as:) | semmle.label | call to String.init(decoding:as:) | -| string.swift:347:30:347:38 | call to source3() : | semmle.label | call to source3() : | -| string.swift:352:17:352:25 | call to source2() : | semmle.label | call to source2() : | -| string.swift:389:22:389:22 | tainted : | semmle.label | tainted : | -| string.swift:389:22:389:65 | call to cString(using:) : | semmle.label | call to cString(using:) : | -| string.swift:390:13:390:13 | arrayString2 | semmle.label | arrayString2 | -| string.swift:436:28:436:36 | call to source4() : | semmle.label | call to source4() : | -| string.swift:456:13:456:77 | call to String.init(bytes:encoding:) : | semmle.label | call to String.init(bytes:encoding:) : | -| string.swift:456:13:456:78 | ...! | semmle.label | ...! | -| string.swift:456:27:456:27 | taintedUInt8Values : | semmle.label | taintedUInt8Values : | -| string.swift:459:13:459:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) | -| string.swift:459:29:459:29 | taintedUInt8Values : | semmle.label | taintedUInt8Values : | -| string.swift:492:37:492:45 | call to source5() : | semmle.label | call to source5() : | -| string.swift:512:13:512:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) | -| string.swift:512:29:512:29 | taintedCCharValues : | semmle.label | taintedCCharValues : | -| string.swift:540:17:540:25 | call to source2() : | semmle.label | call to source2() : | -| string.swift:542:13:542:21 | call to source7() | semmle.label | call to source7() | -| string.swift:545:13:545:13 | sub1 | semmle.label | sub1 | -| string.swift:546:13:546:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:546:20:546:20 | sub1 : | semmle.label | sub1 : | -| string.swift:548:14:548:14 | tainted : | semmle.label | tainted : | -| string.swift:548:14:548:31 | call to prefix(_:) : | semmle.label | call to prefix(_:) : | -| string.swift:549:13:549:13 | sub2 | semmle.label | sub2 | -| string.swift:550:13:550:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:550:20:550:20 | sub2 : | semmle.label | sub2 : | -| string.swift:552:14:552:14 | tainted : | semmle.label | tainted : | -| string.swift:552:14:552:54 | call to prefix(through:) : | semmle.label | call to prefix(through:) : | -| string.swift:553:13:553:13 | sub3 | semmle.label | sub3 | -| string.swift:554:13:554:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:554:20:554:20 | sub3 : | semmle.label | sub3 : | -| string.swift:556:14:556:14 | tainted : | semmle.label | tainted : | -| string.swift:556:14:556:51 | call to prefix(upTo:) : | semmle.label | call to prefix(upTo:) : | -| string.swift:557:13:557:13 | sub4 | semmle.label | sub4 | -| string.swift:558:13:558:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:558:20:558:20 | sub4 : | semmle.label | sub4 : | -| string.swift:560:14:560:14 | tainted : | semmle.label | tainted : | -| string.swift:560:14:560:31 | call to suffix(_:) : | semmle.label | call to suffix(_:) : | -| string.swift:561:13:561:13 | sub5 | semmle.label | sub5 | -| string.swift:562:13:562:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:562:20:562:20 | sub5 : | semmle.label | sub5 : | -| string.swift:564:14:564:14 | tainted : | semmle.label | tainted : | -| string.swift:564:14:564:53 | call to suffix(from:) : | semmle.label | call to suffix(from:) : | -| string.swift:565:13:565:13 | sub6 | semmle.label | sub6 | -| string.swift:566:13:566:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:566:20:566:20 | sub6 : | semmle.label | sub6 : | -| string.swift:622:13:622:28 | call to String.init(_:) | semmle.label | call to String.init(_:) | -| string.swift:622:20:622:27 | call to source() : | semmle.label | call to source() : | -| string.swift:626:13:626:40 | call to String.init(describing:) | semmle.label | call to String.init(describing:) | -| string.swift:626:32:626:39 | call to source() : | semmle.label | call to source() : | +| string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | semmle.label | call to padding(toLength:withPad:startingAt:) | +| string.swift:252:13:252:13 | tainted : | semmle.label | tainted : | +| string.swift:252:13:252:69 | call to components(separatedBy:) | semmle.label | call to components(separatedBy:) | +| string.swift:253:13:253:13 | tainted : | semmle.label | tainted : | +| string.swift:253:13:253:69 | call to components(separatedBy:) : | semmle.label | call to components(separatedBy:) : | +| string.swift:253:13:253:72 | ...[...] | semmle.label | ...[...] | +| string.swift:254:13:254:13 | tainted : | semmle.label | tainted : | +| string.swift:254:13:254:40 | call to folding(options:locale:) | semmle.label | call to folding(options:locale:) | +| string.swift:255:13:255:13 | tainted : | semmle.label | tainted : | +| string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | semmle.label | call to propertyListFromStringsFileFormat() | +| string.swift:256:13:256:13 | tainted : | semmle.label | tainted : | +| string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() : | semmle.label | call to propertyListFromStringsFileFormat() : | +| string.swift:256:13:256:63 | ...! | semmle.label | ...! | +| string.swift:263:13:263:13 | [post] tainted : | semmle.label | [post] tainted : | +| string.swift:263:13:263:13 | tainted : | semmle.label | tainted : | +| string.swift:275:13:275:21 | .description | semmle.label | .description | +| string.swift:277:13:277:21 | .debugDescription | semmle.label | .debugDescription | +| string.swift:279:13:279:21 | .utf8 | semmle.label | .utf8 | +| string.swift:281:13:281:21 | .utf16 | semmle.label | .utf16 | +| string.swift:283:13:283:21 | .unicodeScalars | semmle.label | .unicodeScalars | +| string.swift:285:13:285:21 | .utf8CString | semmle.label | .utf8CString | +| string.swift:287:13:287:21 | .lazy | semmle.label | .lazy | +| string.swift:289:13:289:21 | .capitalized | semmle.label | .capitalized | +| string.swift:291:13:291:21 | .localizedCapitalized | semmle.label | .localizedCapitalized | +| string.swift:293:13:293:21 | .localizedLowercase | semmle.label | .localizedLowercase | +| string.swift:295:13:295:21 | .localizedUppercase | semmle.label | .localizedUppercase | +| string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | semmle.label | .decomposedStringWithCanonicalMapping | +| string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | semmle.label | .precomposedStringWithCompatibilityMapping | +| string.swift:301:13:301:44 | ...! | semmle.label | ...! | +| string.swift:304:13:304:13 | tainted : | semmle.label | tainted : | +| string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | semmle.label | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | semmle.label | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:55:305:63 | call to source2() : | semmle.label | call to source2() : | +| string.swift:309:14:309:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:310:13:310:13 | str1 | semmle.label | str1 | +| string.swift:311:13:311:13 | &... : | semmle.label | &... : | +| string.swift:311:13:311:44 | call to remove(at:) | semmle.label | call to remove(at:) | +| string.swift:312:13:312:13 | str1 | semmle.label | str1 | +| string.swift:314:14:314:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:315:13:315:13 | str2 | semmle.label | str2 | +| string.swift:317:13:317:13 | str2 | semmle.label | str2 | +| string.swift:319:14:319:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:320:13:320:13 | str3 | semmle.label | str3 | +| string.swift:322:13:322:13 | str3 | semmle.label | str3 | +| string.swift:324:14:324:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:325:13:325:13 | str4 | semmle.label | str4 | +| string.swift:326:13:326:13 | &... : | semmle.label | &... : | +| string.swift:326:13:326:30 | call to removeFirst() | semmle.label | call to removeFirst() | +| string.swift:327:13:327:13 | str4 | semmle.label | str4 | +| string.swift:329:13:329:13 | str4 | semmle.label | str4 | +| string.swift:330:13:330:13 | &... : | semmle.label | &... : | +| string.swift:330:13:330:29 | call to removeLast() | semmle.label | call to removeLast() | +| string.swift:331:13:331:13 | str4 | semmle.label | str4 | +| string.swift:333:13:333:13 | str4 | semmle.label | str4 | +| string.swift:335:14:335:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:336:13:336:13 | str5 | semmle.label | str5 | +| string.swift:338:13:338:13 | str5 | semmle.label | str5 | +| string.swift:340:14:340:22 | call to source2() : | semmle.label | call to source2() : | +| string.swift:341:13:341:13 | str6 | semmle.label | str6 | +| string.swift:343:13:343:13 | str6 | semmle.label | str6 | +| string.swift:347:3:347:3 | [post] &... : | semmle.label | [post] &... : | +| string.swift:347:62:347:70 | call to source2() : | semmle.label | call to source2() : | +| string.swift:348:13:348:13 | str7 | semmle.label | str7 | +| string.swift:355:23:355:77 | call to String.init(data:encoding:) : | semmle.label | call to String.init(data:encoding:) : | +| string.swift:355:36:355:44 | call to source3() : | semmle.label | call to source3() : | +| string.swift:358:12:358:25 | ...! | semmle.label | ...! | +| string.swift:361:13:361:54 | call to String.init(decoding:as:) | semmle.label | call to String.init(decoding:as:) | +| string.swift:361:30:361:38 | call to source3() : | semmle.label | call to source3() : | +| string.swift:366:17:366:25 | call to source2() : | semmle.label | call to source2() : | +| string.swift:403:22:403:22 | tainted : | semmle.label | tainted : | +| string.swift:403:22:403:65 | call to cString(using:) : | semmle.label | call to cString(using:) : | +| string.swift:404:13:404:13 | arrayString2 | semmle.label | arrayString2 | +| string.swift:450:28:450:36 | call to source4() : | semmle.label | call to source4() : | +| string.swift:470:13:470:77 | call to String.init(bytes:encoding:) : | semmle.label | call to String.init(bytes:encoding:) : | +| string.swift:470:13:470:78 | ...! | semmle.label | ...! | +| string.swift:470:27:470:27 | taintedUInt8Values : | semmle.label | taintedUInt8Values : | +| string.swift:473:13:473:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) | +| string.swift:473:29:473:29 | taintedUInt8Values : | semmle.label | taintedUInt8Values : | +| string.swift:506:37:506:45 | call to source5() : | semmle.label | call to source5() : | +| string.swift:526:13:526:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) | +| string.swift:526:29:526:29 | taintedCCharValues : | semmle.label | taintedCCharValues : | +| string.swift:554:17:554:25 | call to source2() : | semmle.label | call to source2() : | +| string.swift:556:13:556:21 | call to source7() | semmle.label | call to source7() | +| string.swift:559:13:559:13 | sub1 | semmle.label | sub1 | +| string.swift:560:13:560:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:560:20:560:20 | sub1 : | semmle.label | sub1 : | +| string.swift:562:14:562:14 | tainted : | semmle.label | tainted : | +| string.swift:562:14:562:31 | call to prefix(_:) : | semmle.label | call to prefix(_:) : | +| string.swift:563:13:563:13 | sub2 | semmle.label | sub2 | +| string.swift:564:13:564:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:564:20:564:20 | sub2 : | semmle.label | sub2 : | +| string.swift:566:14:566:14 | tainted : | semmle.label | tainted : | +| string.swift:566:14:566:54 | call to prefix(through:) : | semmle.label | call to prefix(through:) : | +| string.swift:567:13:567:13 | sub3 | semmle.label | sub3 | +| string.swift:568:13:568:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:568:20:568:20 | sub3 : | semmle.label | sub3 : | +| string.swift:570:14:570:14 | tainted : | semmle.label | tainted : | +| string.swift:570:14:570:51 | call to prefix(upTo:) : | semmle.label | call to prefix(upTo:) : | +| string.swift:571:13:571:13 | sub4 | semmle.label | sub4 | +| string.swift:572:13:572:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:572:20:572:20 | sub4 : | semmle.label | sub4 : | +| string.swift:574:14:574:14 | tainted : | semmle.label | tainted : | +| string.swift:574:14:574:31 | call to suffix(_:) : | semmle.label | call to suffix(_:) : | +| string.swift:575:13:575:13 | sub5 | semmle.label | sub5 | +| string.swift:576:13:576:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:576:20:576:20 | sub5 : | semmle.label | sub5 : | +| string.swift:578:14:578:14 | tainted : | semmle.label | tainted : | +| string.swift:578:14:578:53 | call to suffix(from:) : | semmle.label | call to suffix(from:) : | +| string.swift:579:13:579:13 | sub6 | semmle.label | sub6 | +| string.swift:580:13:580:24 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:580:20:580:20 | sub6 : | semmle.label | sub6 : | +| string.swift:636:13:636:28 | call to String.init(_:) | semmle.label | call to String.init(_:) | +| string.swift:636:20:636:27 | call to source() : | semmle.label | call to source() : | +| string.swift:640:13:640:40 | call to String.init(describing:) | semmle.label | call to String.init(describing:) | +| string.swift:640:32:640:39 | call to source() : | semmle.label | call to source() : | | subscript.swift:13:15:13:22 | call to source() : | semmle.label | call to source() : | | subscript.swift:13:15:13:25 | ...[...] | semmle.label | ...[...] | | subscript.swift:14:15:14:23 | call to source2() : | semmle.label | call to source2() : | @@ -1864,63 +1922,66 @@ subpaths | nsmutabledata.swift:40:66:40:73 | call to source() : | nsmutabledata.swift:17:5:17:121 | [summary param] 1 in replaceBytes(in:withBytes:length:) : | file://:0:0:0:0 | [summary] to write: argument this in replaceBytes(in:withBytes:length:) : | nsmutabledata.swift:40:5:40:5 | [post] nsMutableDataTainted4 : | | nsmutabledata.swift:44:35:44:42 | call to source() : | nsmutabledata.swift:18:5:18:33 | [summary param] 0 in setData(_:) : | file://:0:0:0:0 | [summary] to write: argument this in setData(_:) : | nsmutabledata.swift:44:5:44:5 | [post] nsMutableDataTainted5 : | | nsmutabledata.swift:49:15:49:15 | nsMutableDataTainted6 : | nsmutabledata.swift:13:9:13:9 | self : | file://:0:0:0:0 | .mutableBytes : | nsmutabledata.swift:49:15:49:37 | .mutableBytes | -| string.swift:170:29:170:29 | tainted : | string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:170:13:170:36 | call to appending(_:) | -| string.swift:171:13:171:13 | tainted : | string.swift:103:3:103:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:171:13:171:36 | call to appending(_:) | -| string.swift:172:13:172:13 | tainted : | string.swift:103:3:103:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:172:31:172:31 | tainted : | string.swift:103:3:103:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:172:13:172:38 | call to appending(_:) | -| string.swift:185:15:185:23 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(_:) : | file://:0:0:0:0 | [summary] to write: argument this in append(_:) : | string.swift:185:3:185:3 | [post] &... : | -| string.swift:192:27:192:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(contentsOf:) : | file://:0:0:0:0 | [summary] to write: argument this in append(contentsOf:) : | string.swift:192:3:192:3 | [post] &... : | -| string.swift:199:14:199:22 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in write(_:) : | file://:0:0:0:0 | [summary] to write: argument this in write(_:) : | string.swift:199:3:199:3 | [post] &... : | -| string.swift:206:27:206:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in insert(contentsOf:at:) : | file://:0:0:0:0 | [summary] to write: argument this in insert(contentsOf:at:) : | string.swift:206:3:206:3 | [post] &... : | -| string.swift:216:20:216:20 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:216:13:216:27 | call to String.init(_:) | -| string.swift:217:20:217:20 | taintedInt : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:217:13:217:30 | call to String.init(_:) | -| string.swift:219:28:219:28 | tainted : | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:_:) : | string.swift:219:13:219:44 | call to String.init(format:_:) | -| string.swift:220:28:220:28 | tainted : | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:arguments:) : | string.swift:220:13:220:50 | call to String.init(format:arguments:) | -| string.swift:221:28:221:28 | tainted : | string.swift:66:3:66:75 | [summary param] 0 in String.init(format:locale:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:locale:_:) : | string.swift:221:13:221:57 | call to String.init(format:locale:_:) | -| string.swift:222:28:222:28 | tainted : | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:locale:arguments:) : | string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | -| string.swift:223:46:223:46 | tainted : | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in localizedStringWithFormat(_:_:) : | string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | -| string.swift:228:31:228:31 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(repeating:count:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(repeating:count:) : | string.swift:228:13:228:48 | call to String.init(repeating:count:) | -| string.swift:230:13:230:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropFirst(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in dropFirst(_:) : | string.swift:230:13:230:33 | call to dropFirst(_:) | -| string.swift:231:13:231:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropLast(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in dropLast(_:) : | string.swift:231:13:231:32 | call to dropLast(_:) | -| string.swift:232:13:232:13 | tainted : | string.swift:101:3:101:64 | [summary param] this in substring(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in substring(from:) : | string.swift:232:13:232:55 | call to substring(from:) | -| string.swift:234:13:234:13 | tainted : | file://:0:0:0:0 | [summary param] this in lowercased() : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased() : | string.swift:234:13:234:32 | call to lowercased() | -| string.swift:235:13:235:13 | tainted : | file://:0:0:0:0 | [summary param] this in uppercased() : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased() : | string.swift:235:13:235:32 | call to uppercased() | -| string.swift:236:13:236:13 | tainted : | string.swift:98:3:98:63 | [summary param] this in lowercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased(with:) : | string.swift:236:13:236:41 | call to lowercased(with:) | -| string.swift:237:13:237:13 | tainted : | string.swift:99:3:99:63 | [summary param] this in uppercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased(with:) : | string.swift:237:13:237:41 | call to uppercased(with:) | -| string.swift:238:13:238:13 | tainted : | string.swift:100:3:100:64 | [summary param] this in capitalized(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in capitalized(with:) : | string.swift:238:13:238:42 | call to capitalized(with:) | -| string.swift:239:13:239:13 | tainted : | file://:0:0:0:0 | [summary param] this in reversed() : | file://:0:0:0:0 | [summary] to write: return (return) in reversed() : | string.swift:239:13:239:30 | call to reversed() | -| string.swift:241:13:241:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(separator:maxSplits:omittingEmptySubsequences:) : | file://:0:0:0:0 | [summary] to write: return (return) in split(separator:maxSplits:omittingEmptySubsequences:) : | string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | -| string.swift:242:13:242:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | file://:0:0:0:0 | [summary] to write: return (return) in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | -| string.swift:245:13:245:13 | tainted : | string.swift:102:3:102:71 | [summary param] this in trimmingCharacters(in:) : | file://:0:0:0:0 | [summary] to write: return (return) in trimmingCharacters(in:) : | string.swift:245:13:245:68 | call to trimmingCharacters(in:) | -| string.swift:246:13:246:13 | tainted : | string.swift:104:3:104:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | file://:0:0:0:0 | [summary] to write: return (return) in padding(toLength:withPad:startingAt:) : | string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | -| string.swift:247:13:247:13 | tainted : | string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | string.swift:247:13:247:69 | call to components(separatedBy:) | -| string.swift:248:13:248:13 | tainted : | string.swift:105:3:105:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | string.swift:248:13:248:69 | call to components(separatedBy:) : | -| string.swift:249:13:249:13 | tainted : | string.swift:106:3:106:92 | [summary param] this in folding(options:locale:) : | file://:0:0:0:0 | [summary] to write: return (return) in folding(options:locale:) : | string.swift:249:13:249:40 | call to folding(options:locale:) | -| string.swift:250:13:250:13 | tainted : | string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | -| string.swift:251:13:251:13 | tainted : | string.swift:107:3:107:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | string.swift:251:13:251:55 | call to propertyListFromStringsFileFormat() : | -| string.swift:258:13:258:13 | tainted : | string.swift:109:8:109:8 | self : | string.swift:109:3:109:79 | self[return] : | string.swift:258:13:258:13 | [post] tainted : | -| string.swift:302:13:302:13 | &... : | file://:0:0:0:0 | [summary param] this in remove(at:) : | file://:0:0:0:0 | [summary] to write: return (return) in remove(at:) : | string.swift:302:13:302:44 | call to remove(at:) | -| string.swift:317:13:317:13 | &... : | file://:0:0:0:0 | [summary param] this in removeFirst() : | file://:0:0:0:0 | [summary] to write: return (return) in removeFirst() : | string.swift:317:13:317:30 | call to removeFirst() | -| string.swift:321:13:321:13 | &... : | file://:0:0:0:0 | [summary param] this in removeLast() : | file://:0:0:0:0 | [summary] to write: return (return) in removeLast() : | string.swift:321:13:321:29 | call to removeLast() | -| string.swift:341:36:341:44 | call to source3() : | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(data:encoding:) : | string.swift:341:23:341:77 | call to String.init(data:encoding:) : | -| string.swift:347:30:347:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) : | string.swift:347:13:347:54 | call to String.init(decoding:as:) | -| string.swift:389:22:389:22 | tainted : | string.swift:108:3:108:74 | [summary param] this in cString(using:) : | file://:0:0:0:0 | [summary] to write: return (return) in cString(using:) : | string.swift:389:22:389:65 | call to cString(using:) : | -| string.swift:456:27:456:27 | taintedUInt8Values : | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(bytes:encoding:) : | string.swift:456:13:456:77 | call to String.init(bytes:encoding:) : | -| string.swift:459:29:459:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:459:13:459:47 | call to String.init(cString:) | -| string.swift:512:29:512:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:512:13:512:47 | call to String.init(cString:) | -| string.swift:546:20:546:20 | sub1 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:546:13:546:24 | call to String.init(_:) | -| string.swift:548:14:548:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(_:) : | string.swift:548:14:548:31 | call to prefix(_:) : | -| string.swift:550:20:550:20 | sub2 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:550:13:550:24 | call to String.init(_:) | -| string.swift:552:14:552:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(through:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(through:) : | string.swift:552:14:552:54 | call to prefix(through:) : | -| string.swift:554:20:554:20 | sub3 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:554:13:554:24 | call to String.init(_:) | -| string.swift:556:14:556:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(upTo:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(upTo:) : | string.swift:556:14:556:51 | call to prefix(upTo:) : | -| string.swift:558:20:558:20 | sub4 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:558:13:558:24 | call to String.init(_:) | -| string.swift:560:14:560:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in suffix(_:) : | string.swift:560:14:560:31 | call to suffix(_:) : | -| string.swift:562:20:562:20 | sub5 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:562:13:562:24 | call to String.init(_:) | -| string.swift:564:14:564:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in suffix(from:) : | string.swift:564:14:564:53 | call to suffix(from:) : | -| string.swift:566:20:566:20 | sub6 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:566:13:566:24 | call to String.init(_:) | -| string.swift:622:20:622:27 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:622:13:622:28 | call to String.init(_:) | -| string.swift:626:32:626:39 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(describing:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(describing:) : | string.swift:626:13:626:40 | call to String.init(describing:) | +| string.swift:175:29:175:29 | tainted : | string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:175:13:175:36 | call to appending(_:) | +| string.swift:176:13:176:13 | tainted : | string.swift:106:3:106:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:176:13:176:36 | call to appending(_:) | +| string.swift:177:13:177:13 | tainted : | string.swift:106:3:106:82 | [summary param] this in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:177:31:177:31 | tainted : | string.swift:106:3:106:82 | [summary param] 0 in appending(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in appending(_:) : | string.swift:177:13:177:38 | call to appending(_:) | +| string.swift:190:15:190:23 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(_:) : | file://:0:0:0:0 | [summary] to write: argument this in append(_:) : | string.swift:190:3:190:3 | [post] &... : | +| string.swift:197:27:197:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in append(contentsOf:) : | file://:0:0:0:0 | [summary] to write: argument this in append(contentsOf:) : | string.swift:197:3:197:3 | [post] &... : | +| string.swift:204:14:204:22 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in write(_:) : | file://:0:0:0:0 | [summary] to write: argument this in write(_:) : | string.swift:204:3:204:3 | [post] &... : | +| string.swift:211:27:211:35 | call to source2() : | file://:0:0:0:0 | [summary param] 0 in insert(contentsOf:at:) : | file://:0:0:0:0 | [summary] to write: argument this in insert(contentsOf:at:) : | string.swift:211:3:211:3 | [post] &... : | +| string.swift:221:20:221:20 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:221:13:221:27 | call to String.init(_:) | +| string.swift:222:20:222:20 | taintedInt : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:222:13:222:30 | call to String.init(_:) | +| string.swift:224:28:224:28 | tainted : | string.swift:64:3:64:63 | [summary param] 0 in String.init(format:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:_:) : | string.swift:224:13:224:44 | call to String.init(format:_:) | +| string.swift:225:28:225:28 | tainted : | string.swift:65:3:65:60 | [summary param] 0 in String.init(format:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:arguments:) : | string.swift:225:13:225:50 | call to String.init(format:arguments:) | +| string.swift:226:28:226:28 | tainted : | string.swift:66:3:66:75 | [summary param] 0 in String.init(format:locale:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:locale:_:) : | string.swift:226:13:226:57 | call to String.init(format:locale:_:) | +| string.swift:227:28:227:28 | tainted : | string.swift:67:3:67:77 | [summary param] 0 in String.init(format:locale:arguments:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(format:locale:arguments:) : | string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | +| string.swift:228:46:228:46 | tainted : | string.swift:69:3:69:106 | [summary param] 0 in localizedStringWithFormat(_:_:) : | file://:0:0:0:0 | [summary] to write: return (return) in localizedStringWithFormat(_:_:) : | string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | +| string.swift:233:31:233:31 | tainted : | file://:0:0:0:0 | [summary param] 0 in String.init(repeating:count:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(repeating:count:) : | string.swift:233:13:233:48 | call to String.init(repeating:count:) | +| string.swift:235:13:235:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropFirst(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in dropFirst(_:) : | string.swift:235:13:235:33 | call to dropFirst(_:) | +| string.swift:236:13:236:13 | tainted : | file://:0:0:0:0 | [summary param] this in dropLast(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in dropLast(_:) : | string.swift:236:13:236:32 | call to dropLast(_:) | +| string.swift:237:13:237:13 | tainted : | string.swift:104:3:104:64 | [summary param] this in substring(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in substring(from:) : | string.swift:237:13:237:55 | call to substring(from:) | +| string.swift:239:13:239:13 | tainted : | file://:0:0:0:0 | [summary param] this in lowercased() : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased() : | string.swift:239:13:239:32 | call to lowercased() | +| string.swift:240:13:240:13 | tainted : | file://:0:0:0:0 | [summary param] this in uppercased() : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased() : | string.swift:240:13:240:32 | call to uppercased() | +| string.swift:241:13:241:13 | tainted : | string.swift:101:3:101:63 | [summary param] this in lowercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in lowercased(with:) : | string.swift:241:13:241:41 | call to lowercased(with:) | +| string.swift:242:13:242:13 | tainted : | string.swift:102:3:102:63 | [summary param] this in uppercased(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in uppercased(with:) : | string.swift:242:13:242:41 | call to uppercased(with:) | +| string.swift:243:13:243:13 | tainted : | string.swift:103:3:103:64 | [summary param] this in capitalized(with:) : | file://:0:0:0:0 | [summary] to write: return (return) in capitalized(with:) : | string.swift:243:13:243:42 | call to capitalized(with:) | +| string.swift:244:13:244:13 | tainted : | file://:0:0:0:0 | [summary param] this in reversed() : | file://:0:0:0:0 | [summary] to write: return (return) in reversed() : | string.swift:244:13:244:30 | call to reversed() | +| string.swift:246:13:246:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(separator:maxSplits:omittingEmptySubsequences:) : | file://:0:0:0:0 | [summary] to write: return (return) in split(separator:maxSplits:omittingEmptySubsequences:) : | string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | +| string.swift:247:13:247:13 | tainted : | file://:0:0:0:0 | [summary param] this in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | file://:0:0:0:0 | [summary] to write: return (return) in split(maxSplits:omittingEmptySubsequences:whereSeparator:) : | string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | +| string.swift:250:13:250:13 | tainted : | string.swift:105:3:105:71 | [summary param] this in trimmingCharacters(in:) : | file://:0:0:0:0 | [summary] to write: return (return) in trimmingCharacters(in:) : | string.swift:250:13:250:68 | call to trimmingCharacters(in:) | +| string.swift:251:13:251:13 | tainted : | string.swift:107:3:107:138 | [summary param] this in padding(toLength:withPad:startingAt:) : | file://:0:0:0:0 | [summary] to write: return (return) in padding(toLength:withPad:startingAt:) : | string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | +| string.swift:252:13:252:13 | tainted : | string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | string.swift:252:13:252:69 | call to components(separatedBy:) | +| string.swift:253:13:253:13 | tainted : | string.swift:108:3:108:80 | [summary param] this in components(separatedBy:) : | file://:0:0:0:0 | [summary] to write: return (return) in components(separatedBy:) : | string.swift:253:13:253:69 | call to components(separatedBy:) : | +| string.swift:254:13:254:13 | tainted : | string.swift:109:3:109:92 | [summary param] this in folding(options:locale:) : | file://:0:0:0:0 | [summary] to write: return (return) in folding(options:locale:) : | string.swift:254:13:254:40 | call to folding(options:locale:) | +| string.swift:255:13:255:13 | tainted : | string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | +| string.swift:256:13:256:13 | tainted : | string.swift:110:3:110:78 | [summary param] this in propertyListFromStringsFileFormat() : | file://:0:0:0:0 | [summary] to write: return (return) in propertyListFromStringsFileFormat() : | string.swift:256:13:256:55 | call to propertyListFromStringsFileFormat() : | +| string.swift:263:13:263:13 | tainted : | string.swift:112:8:112:8 | self : | string.swift:112:3:112:79 | self[return] : | string.swift:263:13:263:13 | [post] tainted : | +| string.swift:304:13:304:13 | tainted : | string.swift:113:3:114:77 | [summary param] this in replacingOccurrences(of:with:options:range:) : | file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:305:55:305:63 | call to source2() : | string.swift:113:3:114:77 | [summary param] 1 in replacingOccurrences(of:with:options:range:) : | file://:0:0:0:0 | [summary] to write: return (return) in replacingOccurrences(of:with:options:range:) : | string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | +| string.swift:311:13:311:13 | &... : | file://:0:0:0:0 | [summary param] this in remove(at:) : | file://:0:0:0:0 | [summary] to write: return (return) in remove(at:) : | string.swift:311:13:311:44 | call to remove(at:) | +| string.swift:326:13:326:13 | &... : | file://:0:0:0:0 | [summary param] this in removeFirst() : | file://:0:0:0:0 | [summary] to write: return (return) in removeFirst() : | string.swift:326:13:326:30 | call to removeFirst() | +| string.swift:330:13:330:13 | &... : | file://:0:0:0:0 | [summary param] this in removeLast() : | file://:0:0:0:0 | [summary] to write: return (return) in removeLast() : | string.swift:330:13:330:29 | call to removeLast() | +| string.swift:347:62:347:70 | call to source2() : | string.swift:86:12:87:51 | [summary param] 1 in replaceSubrange(_:with:) : | file://:0:0:0:0 | [summary] to write: argument this in replaceSubrange(_:with:) : | string.swift:347:3:347:3 | [post] &... : | +| string.swift:355:36:355:44 | call to source3() : | string.swift:60:2:60:54 | [summary param] 0 in String.init(data:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(data:encoding:) : | string.swift:355:23:355:77 | call to String.init(data:encoding:) : | +| string.swift:361:30:361:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) : | string.swift:361:13:361:54 | call to String.init(decoding:as:) | +| string.swift:403:22:403:22 | tainted : | string.swift:111:3:111:74 | [summary param] this in cString(using:) : | file://:0:0:0:0 | [summary] to write: return (return) in cString(using:) : | string.swift:403:22:403:65 | call to cString(using:) : | +| string.swift:470:27:470:27 | taintedUInt8Values : | string.swift:71:3:71:102 | [summary param] 0 in String.init(bytes:encoding:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(bytes:encoding:) : | string.swift:470:13:470:77 | call to String.init(bytes:encoding:) : | +| string.swift:473:29:473:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:473:13:473:47 | call to String.init(cString:) | +| string.swift:526:29:526:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:526:13:526:47 | call to String.init(cString:) | +| string.swift:560:20:560:20 | sub1 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:560:13:560:24 | call to String.init(_:) | +| string.swift:562:14:562:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(_:) : | string.swift:562:14:562:31 | call to prefix(_:) : | +| string.swift:564:20:564:20 | sub2 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:564:13:564:24 | call to String.init(_:) | +| string.swift:566:14:566:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(through:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(through:) : | string.swift:566:14:566:54 | call to prefix(through:) : | +| string.swift:568:20:568:20 | sub3 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:568:13:568:24 | call to String.init(_:) | +| string.swift:570:14:570:14 | tainted : | file://:0:0:0:0 | [summary param] this in prefix(upTo:) : | file://:0:0:0:0 | [summary] to write: return (return) in prefix(upTo:) : | string.swift:570:14:570:51 | call to prefix(upTo:) : | +| string.swift:572:20:572:20 | sub4 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:572:13:572:24 | call to String.init(_:) | +| string.swift:574:14:574:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in suffix(_:) : | string.swift:574:14:574:31 | call to suffix(_:) : | +| string.swift:576:20:576:20 | sub5 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:576:13:576:24 | call to String.init(_:) | +| string.swift:578:14:578:14 | tainted : | file://:0:0:0:0 | [summary param] this in suffix(from:) : | file://:0:0:0:0 | [summary] to write: return (return) in suffix(from:) : | string.swift:578:14:578:53 | call to suffix(from:) : | +| string.swift:580:20:580:20 | sub6 : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:580:13:580:24 | call to String.init(_:) | +| string.swift:636:20:636:27 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(_:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(_:) : | string.swift:636:13:636:28 | call to String.init(_:) | +| string.swift:640:32:640:39 | call to source() : | file://:0:0:0:0 | [summary param] 0 in String.init(describing:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(describing:) : | string.swift:640:13:640:40 | call to String.init(describing:) | | ui.swift:55:10:55:10 | tainted : | ui.swift:16:9:16:9 | self : | file://:0:0:0:0 | .url : | ui.swift:55:10:55:18 | .url | | ui.swift:64:10:64:10 | tainted : | ui.swift:32:13:32:13 | self : | file://:0:0:0:0 | .userActivities : | ui.swift:64:10:64:18 | .userActivities | | ui.swift:68:10:68:10 | tainted : | ui.swift:34:13:34:13 | self : | file://:0:0:0:0 | .urlContexts : | ui.swift:68:10:68:18 | .urlContexts | @@ -2056,102 +2117,116 @@ subpaths | nsmutabledata.swift:41:15:41:15 | nsMutableDataTainted4 | nsmutabledata.swift:40:66:40:73 | call to source() : | nsmutabledata.swift:41:15:41:15 | nsMutableDataTainted4 | result | | nsmutabledata.swift:45:15:45:15 | nsMutableDataTainted5 | nsmutabledata.swift:44:35:44:42 | call to source() : | nsmutabledata.swift:45:15:45:15 | nsMutableDataTainted5 | result | | nsmutabledata.swift:49:15:49:37 | .mutableBytes | nsmutabledata.swift:48:33:48:40 | call to source() : | nsmutabledata.swift:49:15:49:37 | .mutableBytes | result | -| string.swift:134:13:134:13 | "..." | string.swift:132:11:132:18 | call to source() : | string.swift:134:13:134:13 | "..." | result | -| string.swift:136:13:136:13 | "..." | string.swift:132:11:132:18 | call to source() : | string.swift:136:13:136:13 | "..." | result | -| string.swift:138:13:138:13 | "..." | string.swift:132:11:132:18 | call to source() : | string.swift:138:13:138:13 | "..." | result | -| string.swift:144:13:144:13 | "..." | string.swift:132:11:132:18 | call to source() : | string.swift:144:13:144:13 | "..." | result | -| string.swift:146:13:146:13 | "..." | string.swift:132:11:132:18 | call to source() : | string.swift:146:13:146:13 | "..." | result | -| string.swift:159:13:159:13 | tainted | string.swift:156:17:156:25 | call to source2() : | string.swift:159:13:159:13 | tainted | result | -| string.swift:162:13:162:21 | ... .+(_:_:) ... | string.swift:156:17:156:25 | call to source2() : | string.swift:162:13:162:21 | ... .+(_:_:) ... | result | -| string.swift:163:13:163:23 | ... .+(_:_:) ... | string.swift:156:17:156:25 | call to source2() : | string.swift:163:13:163:23 | ... .+(_:_:) ... | result | -| string.swift:164:13:164:23 | ... .+(_:_:) ... | string.swift:156:17:156:25 | call to source2() : | string.swift:164:13:164:23 | ... .+(_:_:) ... | result | -| string.swift:167:13:167:29 | ... .+(_:_:) ... | string.swift:156:17:156:25 | call to source2() : | string.swift:167:13:167:29 | ... .+(_:_:) ... | result | -| string.swift:170:13:170:36 | call to appending(_:) | string.swift:156:17:156:25 | call to source2() : | string.swift:170:13:170:36 | call to appending(_:) | result | -| string.swift:171:13:171:36 | call to appending(_:) | string.swift:156:17:156:25 | call to source2() : | string.swift:171:13:171:36 | call to appending(_:) | result | -| string.swift:172:13:172:38 | call to appending(_:) | string.swift:156:17:156:25 | call to source2() : | string.swift:172:13:172:38 | call to appending(_:) | result | -| string.swift:186:13:186:13 | str2 | string.swift:185:15:185:23 | call to source2() : | string.swift:186:13:186:13 | str2 | result | -| string.swift:193:13:193:13 | str3 | string.swift:192:27:192:35 | call to source2() : | string.swift:193:13:193:13 | str3 | result | -| string.swift:200:13:200:13 | str4 | string.swift:199:14:199:22 | call to source2() : | string.swift:200:13:200:13 | str4 | result | -| string.swift:207:13:207:13 | str5 | string.swift:206:27:206:35 | call to source2() : | string.swift:207:13:207:13 | str5 | result | -| string.swift:216:13:216:27 | call to String.init(_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:216:13:216:27 | call to String.init(_:) | result | -| string.swift:217:13:217:30 | call to String.init(_:) | string.swift:213:20:213:27 | call to source() : | string.swift:217:13:217:30 | call to String.init(_:) | result | -| string.swift:219:13:219:44 | call to String.init(format:_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:219:13:219:44 | call to String.init(format:_:) | result | -| string.swift:220:13:220:50 | call to String.init(format:arguments:) | string.swift:212:17:212:25 | call to source2() : | string.swift:220:13:220:50 | call to String.init(format:arguments:) | result | -| string.swift:221:13:221:57 | call to String.init(format:locale:_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:221:13:221:57 | call to String.init(format:locale:_:) | result | -| string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | string.swift:212:17:212:25 | call to source2() : | string.swift:222:13:222:63 | call to String.init(format:locale:arguments:) | result | -| string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:223:13:223:62 | call to localizedStringWithFormat(_:_:) | result | -| string.swift:228:13:228:48 | call to String.init(repeating:count:) | string.swift:212:17:212:25 | call to source2() : | string.swift:228:13:228:48 | call to String.init(repeating:count:) | result | -| string.swift:230:13:230:33 | call to dropFirst(_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:230:13:230:33 | call to dropFirst(_:) | result | -| string.swift:231:13:231:32 | call to dropLast(_:) | string.swift:212:17:212:25 | call to source2() : | string.swift:231:13:231:32 | call to dropLast(_:) | result | -| string.swift:232:13:232:55 | call to substring(from:) | string.swift:212:17:212:25 | call to source2() : | string.swift:232:13:232:55 | call to substring(from:) | result | -| string.swift:234:13:234:32 | call to lowercased() | string.swift:212:17:212:25 | call to source2() : | string.swift:234:13:234:32 | call to lowercased() | result | -| string.swift:235:13:235:32 | call to uppercased() | string.swift:212:17:212:25 | call to source2() : | string.swift:235:13:235:32 | call to uppercased() | result | -| string.swift:236:13:236:41 | call to lowercased(with:) | string.swift:212:17:212:25 | call to source2() : | string.swift:236:13:236:41 | call to lowercased(with:) | result | -| string.swift:237:13:237:41 | call to uppercased(with:) | string.swift:212:17:212:25 | call to source2() : | string.swift:237:13:237:41 | call to uppercased(with:) | result | -| string.swift:238:13:238:42 | call to capitalized(with:) | string.swift:212:17:212:25 | call to source2() : | string.swift:238:13:238:42 | call to capitalized(with:) | result | -| string.swift:239:13:239:30 | call to reversed() | string.swift:212:17:212:25 | call to source2() : | string.swift:239:13:239:30 | call to reversed() | result | -| string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | string.swift:212:17:212:25 | call to source2() : | string.swift:241:13:241:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | result | -| string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | string.swift:212:17:212:25 | call to source2() : | string.swift:242:13:244:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | result | -| string.swift:245:13:245:68 | call to trimmingCharacters(in:) | string.swift:212:17:212:25 | call to source2() : | string.swift:245:13:245:68 | call to trimmingCharacters(in:) | result | -| string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | string.swift:212:17:212:25 | call to source2() : | string.swift:246:13:246:70 | call to padding(toLength:withPad:startingAt:) | result | -| string.swift:247:13:247:69 | call to components(separatedBy:) | string.swift:212:17:212:25 | call to source2() : | string.swift:247:13:247:69 | call to components(separatedBy:) | result | -| string.swift:248:13:248:72 | ...[...] | string.swift:212:17:212:25 | call to source2() : | string.swift:248:13:248:72 | ...[...] | result | -| string.swift:249:13:249:40 | call to folding(options:locale:) | string.swift:212:17:212:25 | call to source2() : | string.swift:249:13:249:40 | call to folding(options:locale:) | result | -| string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | string.swift:212:17:212:25 | call to source2() : | string.swift:250:13:250:55 | call to propertyListFromStringsFileFormat() | result | -| string.swift:251:13:251:63 | ...! | string.swift:212:17:212:25 | call to source2() : | string.swift:251:13:251:63 | ...! | result | -| string.swift:270:13:270:21 | .description | string.swift:212:17:212:25 | call to source2() : | string.swift:270:13:270:21 | .description | result | -| string.swift:272:13:272:21 | .debugDescription | string.swift:212:17:212:25 | call to source2() : | string.swift:272:13:272:21 | .debugDescription | result | -| string.swift:274:13:274:21 | .utf8 | string.swift:212:17:212:25 | call to source2() : | string.swift:274:13:274:21 | .utf8 | result | -| string.swift:276:13:276:21 | .utf16 | string.swift:212:17:212:25 | call to source2() : | string.swift:276:13:276:21 | .utf16 | result | -| string.swift:278:13:278:21 | .unicodeScalars | string.swift:212:17:212:25 | call to source2() : | string.swift:278:13:278:21 | .unicodeScalars | result | -| string.swift:280:13:280:21 | .utf8CString | string.swift:212:17:212:25 | call to source2() : | string.swift:280:13:280:21 | .utf8CString | result | -| string.swift:282:13:282:21 | .lazy | string.swift:212:17:212:25 | call to source2() : | string.swift:282:13:282:21 | .lazy | result | -| string.swift:284:13:284:21 | .capitalized | string.swift:212:17:212:25 | call to source2() : | string.swift:284:13:284:21 | .capitalized | result | -| string.swift:286:13:286:21 | .localizedCapitalized | string.swift:212:17:212:25 | call to source2() : | string.swift:286:13:286:21 | .localizedCapitalized | result | -| string.swift:288:13:288:21 | .localizedLowercase | string.swift:212:17:212:25 | call to source2() : | string.swift:288:13:288:21 | .localizedLowercase | result | -| string.swift:290:13:290:21 | .localizedUppercase | string.swift:212:17:212:25 | call to source2() : | string.swift:290:13:290:21 | .localizedUppercase | result | -| string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | string.swift:212:17:212:25 | call to source2() : | string.swift:292:13:292:21 | .decomposedStringWithCanonicalMapping | result | -| string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | string.swift:212:17:212:25 | call to source2() : | string.swift:294:13:294:21 | .precomposedStringWithCompatibilityMapping | result | -| string.swift:296:13:296:44 | ...! | string.swift:212:17:212:25 | call to source2() : | string.swift:296:13:296:44 | ...! | result | -| string.swift:301:13:301:13 | str1 | string.swift:300:14:300:22 | call to source2() : | string.swift:301:13:301:13 | str1 | result | -| string.swift:302:13:302:44 | call to remove(at:) | string.swift:300:14:300:22 | call to source2() : | string.swift:302:13:302:44 | call to remove(at:) | result | -| string.swift:303:13:303:13 | str1 | string.swift:300:14:300:22 | call to source2() : | string.swift:303:13:303:13 | str1 | result | -| string.swift:306:13:306:13 | str2 | string.swift:305:14:305:22 | call to source2() : | string.swift:306:13:306:13 | str2 | result | -| string.swift:308:13:308:13 | str2 | string.swift:305:14:305:22 | call to source2() : | string.swift:308:13:308:13 | str2 | result | -| string.swift:311:13:311:13 | str3 | string.swift:310:14:310:22 | call to source2() : | string.swift:311:13:311:13 | str3 | result | -| string.swift:313:13:313:13 | str3 | string.swift:310:14:310:22 | call to source2() : | string.swift:313:13:313:13 | str3 | result | -| string.swift:316:13:316:13 | str4 | string.swift:315:14:315:22 | call to source2() : | string.swift:316:13:316:13 | str4 | result | -| string.swift:317:13:317:30 | call to removeFirst() | string.swift:315:14:315:22 | call to source2() : | string.swift:317:13:317:30 | call to removeFirst() | result | -| string.swift:318:13:318:13 | str4 | string.swift:315:14:315:22 | call to source2() : | string.swift:318:13:318:13 | str4 | result | -| string.swift:320:13:320:13 | str4 | string.swift:315:14:315:22 | call to source2() : | string.swift:320:13:320:13 | str4 | result | -| string.swift:321:13:321:29 | call to removeLast() | string.swift:315:14:315:22 | call to source2() : | string.swift:321:13:321:29 | call to removeLast() | result | -| string.swift:322:13:322:13 | str4 | string.swift:315:14:315:22 | call to source2() : | string.swift:322:13:322:13 | str4 | result | -| string.swift:324:13:324:13 | str4 | string.swift:315:14:315:22 | call to source2() : | string.swift:324:13:324:13 | str4 | result | -| string.swift:327:13:327:13 | str5 | string.swift:326:14:326:22 | call to source2() : | string.swift:327:13:327:13 | str5 | result | -| string.swift:329:13:329:13 | str5 | string.swift:326:14:326:22 | call to source2() : | string.swift:329:13:329:13 | str5 | result | -| string.swift:332:13:332:13 | str6 | string.swift:331:14:331:22 | call to source2() : | string.swift:332:13:332:13 | str6 | result | -| string.swift:334:13:334:13 | str6 | string.swift:331:14:331:22 | call to source2() : | string.swift:334:13:334:13 | str6 | result | -| string.swift:344:12:344:25 | ...! | string.swift:341:36:341:44 | call to source3() : | string.swift:344:12:344:25 | ...! | result | -| string.swift:347:13:347:54 | call to String.init(decoding:as:) | string.swift:347:30:347:38 | call to source3() : | string.swift:347:13:347:54 | call to String.init(decoding:as:) | result | -| string.swift:390:13:390:13 | arrayString2 | string.swift:352:17:352:25 | call to source2() : | string.swift:390:13:390:13 | arrayString2 | result | -| string.swift:456:13:456:78 | ...! | string.swift:436:28:436:36 | call to source4() : | string.swift:456:13:456:78 | ...! | result | -| string.swift:459:13:459:47 | call to String.init(cString:) | string.swift:436:28:436:36 | call to source4() : | string.swift:459:13:459:47 | call to String.init(cString:) | result | -| string.swift:512:13:512:47 | call to String.init(cString:) | string.swift:492:37:492:45 | call to source5() : | string.swift:512:13:512:47 | call to String.init(cString:) | result | -| string.swift:542:13:542:21 | call to source7() | string.swift:542:13:542:21 | call to source7() | string.swift:542:13:542:21 | call to source7() | result | -| string.swift:545:13:545:13 | sub1 | string.swift:540:17:540:25 | call to source2() : | string.swift:545:13:545:13 | sub1 | result | -| string.swift:546:13:546:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:546:13:546:24 | call to String.init(_:) | result | -| string.swift:549:13:549:13 | sub2 | string.swift:540:17:540:25 | call to source2() : | string.swift:549:13:549:13 | sub2 | result | -| string.swift:550:13:550:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:550:13:550:24 | call to String.init(_:) | result | -| string.swift:553:13:553:13 | sub3 | string.swift:540:17:540:25 | call to source2() : | string.swift:553:13:553:13 | sub3 | result | -| string.swift:554:13:554:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:554:13:554:24 | call to String.init(_:) | result | -| string.swift:557:13:557:13 | sub4 | string.swift:540:17:540:25 | call to source2() : | string.swift:557:13:557:13 | sub4 | result | -| string.swift:558:13:558:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:558:13:558:24 | call to String.init(_:) | result | -| string.swift:561:13:561:13 | sub5 | string.swift:540:17:540:25 | call to source2() : | string.swift:561:13:561:13 | sub5 | result | -| string.swift:562:13:562:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:562:13:562:24 | call to String.init(_:) | result | -| string.swift:565:13:565:13 | sub6 | string.swift:540:17:540:25 | call to source2() : | string.swift:565:13:565:13 | sub6 | result | -| string.swift:566:13:566:24 | call to String.init(_:) | string.swift:540:17:540:25 | call to source2() : | string.swift:566:13:566:24 | call to String.init(_:) | result | -| string.swift:622:13:622:28 | call to String.init(_:) | string.swift:622:20:622:27 | call to source() : | string.swift:622:13:622:28 | call to String.init(_:) | result | -| string.swift:626:13:626:40 | call to String.init(describing:) | string.swift:626:32:626:39 | call to source() : | string.swift:626:13:626:40 | call to String.init(describing:) | result | +| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() : | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result | +| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() : | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result | +| simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() : | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result | +| simple.swift:15:13:15:24 | ... .-(_:_:) ... | simple.swift:15:13:15:20 | call to source() : | simple.swift:15:13:15:24 | ... .-(_:_:) ... | result | +| simple.swift:16:13:16:24 | ... .*(_:_:) ... | simple.swift:16:17:16:24 | call to source() : | simple.swift:16:13:16:24 | ... .*(_:_:) ... | result | +| simple.swift:17:13:17:24 | ... .*(_:_:) ... | simple.swift:17:13:17:20 | call to source() : | simple.swift:17:13:17:24 | ... .*(_:_:) ... | result | +| simple.swift:18:13:18:26 | ... ./(_:_:) ... | simple.swift:18:19:18:26 | call to source() : | simple.swift:18:13:18:26 | ... ./(_:_:) ... | result | +| simple.swift:19:13:19:24 | ... ./(_:_:) ... | simple.swift:19:13:19:20 | call to source() : | simple.swift:19:13:19:24 | ... ./(_:_:) ... | result | +| simple.swift:20:13:20:26 | ... .%(_:_:) ... | simple.swift:20:19:20:26 | call to source() : | simple.swift:20:13:20:26 | ... .%(_:_:) ... | result | +| simple.swift:21:13:21:24 | ... .%(_:_:) ... | simple.swift:21:13:21:20 | call to source() : | simple.swift:21:13:21:24 | ... .%(_:_:) ... | result | +| simple.swift:23:13:23:21 | call to -(_:) | simple.swift:23:14:23:21 | call to source() : | simple.swift:23:13:23:21 | call to -(_:) | result | +| string.swift:139:13:139:13 | "..." | string.swift:137:11:137:18 | call to source() : | string.swift:139:13:139:13 | "..." | result | +| string.swift:141:13:141:13 | "..." | string.swift:137:11:137:18 | call to source() : | string.swift:141:13:141:13 | "..." | result | +| string.swift:143:13:143:13 | "..." | string.swift:137:11:137:18 | call to source() : | string.swift:143:13:143:13 | "..." | result | +| string.swift:149:13:149:13 | "..." | string.swift:137:11:137:18 | call to source() : | string.swift:149:13:149:13 | "..." | result | +| string.swift:151:13:151:13 | "..." | string.swift:137:11:137:18 | call to source() : | string.swift:151:13:151:13 | "..." | result | +| string.swift:164:13:164:13 | tainted | string.swift:161:17:161:25 | call to source2() : | string.swift:164:13:164:13 | tainted | result | +| string.swift:167:13:167:21 | ... .+(_:_:) ... | string.swift:161:17:161:25 | call to source2() : | string.swift:167:13:167:21 | ... .+(_:_:) ... | result | +| string.swift:168:13:168:23 | ... .+(_:_:) ... | string.swift:161:17:161:25 | call to source2() : | string.swift:168:13:168:23 | ... .+(_:_:) ... | result | +| string.swift:169:13:169:23 | ... .+(_:_:) ... | string.swift:161:17:161:25 | call to source2() : | string.swift:169:13:169:23 | ... .+(_:_:) ... | result | +| string.swift:172:13:172:29 | ... .+(_:_:) ... | string.swift:161:17:161:25 | call to source2() : | string.swift:172:13:172:29 | ... .+(_:_:) ... | result | +| string.swift:175:13:175:36 | call to appending(_:) | string.swift:161:17:161:25 | call to source2() : | string.swift:175:13:175:36 | call to appending(_:) | result | +| string.swift:176:13:176:36 | call to appending(_:) | string.swift:161:17:161:25 | call to source2() : | string.swift:176:13:176:36 | call to appending(_:) | result | +| string.swift:177:13:177:38 | call to appending(_:) | string.swift:161:17:161:25 | call to source2() : | string.swift:177:13:177:38 | call to appending(_:) | result | +| string.swift:191:13:191:13 | str2 | string.swift:190:15:190:23 | call to source2() : | string.swift:191:13:191:13 | str2 | result | +| string.swift:198:13:198:13 | str3 | string.swift:197:27:197:35 | call to source2() : | string.swift:198:13:198:13 | str3 | result | +| string.swift:205:13:205:13 | str4 | string.swift:204:14:204:22 | call to source2() : | string.swift:205:13:205:13 | str4 | result | +| string.swift:212:13:212:13 | str5 | string.swift:211:27:211:35 | call to source2() : | string.swift:212:13:212:13 | str5 | result | +| string.swift:221:13:221:27 | call to String.init(_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:221:13:221:27 | call to String.init(_:) | result | +| string.swift:222:13:222:30 | call to String.init(_:) | string.swift:218:20:218:27 | call to source() : | string.swift:222:13:222:30 | call to String.init(_:) | result | +| string.swift:224:13:224:44 | call to String.init(format:_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:224:13:224:44 | call to String.init(format:_:) | result | +| string.swift:225:13:225:50 | call to String.init(format:arguments:) | string.swift:217:17:217:25 | call to source2() : | string.swift:225:13:225:50 | call to String.init(format:arguments:) | result | +| string.swift:226:13:226:57 | call to String.init(format:locale:_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:226:13:226:57 | call to String.init(format:locale:_:) | result | +| string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | string.swift:217:17:217:25 | call to source2() : | string.swift:227:13:227:63 | call to String.init(format:locale:arguments:) | result | +| string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:228:13:228:62 | call to localizedStringWithFormat(_:_:) | result | +| string.swift:233:13:233:48 | call to String.init(repeating:count:) | string.swift:217:17:217:25 | call to source2() : | string.swift:233:13:233:48 | call to String.init(repeating:count:) | result | +| string.swift:235:13:235:33 | call to dropFirst(_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:235:13:235:33 | call to dropFirst(_:) | result | +| string.swift:236:13:236:32 | call to dropLast(_:) | string.swift:217:17:217:25 | call to source2() : | string.swift:236:13:236:32 | call to dropLast(_:) | result | +| string.swift:237:13:237:55 | call to substring(from:) | string.swift:217:17:217:25 | call to source2() : | string.swift:237:13:237:55 | call to substring(from:) | result | +| string.swift:239:13:239:32 | call to lowercased() | string.swift:217:17:217:25 | call to source2() : | string.swift:239:13:239:32 | call to lowercased() | result | +| string.swift:240:13:240:32 | call to uppercased() | string.swift:217:17:217:25 | call to source2() : | string.swift:240:13:240:32 | call to uppercased() | result | +| string.swift:241:13:241:41 | call to lowercased(with:) | string.swift:217:17:217:25 | call to source2() : | string.swift:241:13:241:41 | call to lowercased(with:) | result | +| string.swift:242:13:242:41 | call to uppercased(with:) | string.swift:217:17:217:25 | call to source2() : | string.swift:242:13:242:41 | call to uppercased(with:) | result | +| string.swift:243:13:243:42 | call to capitalized(with:) | string.swift:217:17:217:25 | call to source2() : | string.swift:243:13:243:42 | call to capitalized(with:) | result | +| string.swift:244:13:244:30 | call to reversed() | string.swift:217:17:217:25 | call to source2() : | string.swift:244:13:244:30 | call to reversed() | result | +| string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | string.swift:217:17:217:25 | call to source2() : | string.swift:246:13:246:41 | call to split(separator:maxSplits:omittingEmptySubsequences:) | result | +| string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | string.swift:217:17:217:25 | call to source2() : | string.swift:247:13:249:4 | call to split(maxSplits:omittingEmptySubsequences:whereSeparator:) | result | +| string.swift:250:13:250:68 | call to trimmingCharacters(in:) | string.swift:217:17:217:25 | call to source2() : | string.swift:250:13:250:68 | call to trimmingCharacters(in:) | result | +| string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | string.swift:217:17:217:25 | call to source2() : | string.swift:251:13:251:70 | call to padding(toLength:withPad:startingAt:) | result | +| string.swift:252:13:252:69 | call to components(separatedBy:) | string.swift:217:17:217:25 | call to source2() : | string.swift:252:13:252:69 | call to components(separatedBy:) | result | +| string.swift:253:13:253:72 | ...[...] | string.swift:217:17:217:25 | call to source2() : | string.swift:253:13:253:72 | ...[...] | result | +| string.swift:254:13:254:40 | call to folding(options:locale:) | string.swift:217:17:217:25 | call to source2() : | string.swift:254:13:254:40 | call to folding(options:locale:) | result | +| string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | string.swift:217:17:217:25 | call to source2() : | string.swift:255:13:255:55 | call to propertyListFromStringsFileFormat() | result | +| string.swift:256:13:256:63 | ...! | string.swift:217:17:217:25 | call to source2() : | string.swift:256:13:256:63 | ...! | result | +| string.swift:275:13:275:21 | .description | string.swift:217:17:217:25 | call to source2() : | string.swift:275:13:275:21 | .description | result | +| string.swift:277:13:277:21 | .debugDescription | string.swift:217:17:217:25 | call to source2() : | string.swift:277:13:277:21 | .debugDescription | result | +| string.swift:279:13:279:21 | .utf8 | string.swift:217:17:217:25 | call to source2() : | string.swift:279:13:279:21 | .utf8 | result | +| string.swift:281:13:281:21 | .utf16 | string.swift:217:17:217:25 | call to source2() : | string.swift:281:13:281:21 | .utf16 | result | +| string.swift:283:13:283:21 | .unicodeScalars | string.swift:217:17:217:25 | call to source2() : | string.swift:283:13:283:21 | .unicodeScalars | result | +| string.swift:285:13:285:21 | .utf8CString | string.swift:217:17:217:25 | call to source2() : | string.swift:285:13:285:21 | .utf8CString | result | +| string.swift:287:13:287:21 | .lazy | string.swift:217:17:217:25 | call to source2() : | string.swift:287:13:287:21 | .lazy | result | +| string.swift:289:13:289:21 | .capitalized | string.swift:217:17:217:25 | call to source2() : | string.swift:289:13:289:21 | .capitalized | result | +| string.swift:291:13:291:21 | .localizedCapitalized | string.swift:217:17:217:25 | call to source2() : | string.swift:291:13:291:21 | .localizedCapitalized | result | +| string.swift:293:13:293:21 | .localizedLowercase | string.swift:217:17:217:25 | call to source2() : | string.swift:293:13:293:21 | .localizedLowercase | result | +| string.swift:295:13:295:21 | .localizedUppercase | string.swift:217:17:217:25 | call to source2() : | string.swift:295:13:295:21 | .localizedUppercase | result | +| string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | string.swift:217:17:217:25 | call to source2() : | string.swift:297:13:297:21 | .decomposedStringWithCanonicalMapping | result | +| string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | string.swift:217:17:217:25 | call to source2() : | string.swift:299:13:299:21 | .precomposedStringWithCompatibilityMapping | result | +| string.swift:301:13:301:44 | ...! | string.swift:217:17:217:25 | call to source2() : | string.swift:301:13:301:44 | ...! | result | +| string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | string.swift:217:17:217:25 | call to source2() : | string.swift:304:13:304:60 | call to replacingOccurrences(of:with:options:range:) | result | +| string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | string.swift:305:55:305:63 | call to source2() : | string.swift:305:13:305:64 | call to replacingOccurrences(of:with:options:range:) | result | +| string.swift:310:13:310:13 | str1 | string.swift:309:14:309:22 | call to source2() : | string.swift:310:13:310:13 | str1 | result | +| string.swift:311:13:311:44 | call to remove(at:) | string.swift:309:14:309:22 | call to source2() : | string.swift:311:13:311:44 | call to remove(at:) | result | +| string.swift:312:13:312:13 | str1 | string.swift:309:14:309:22 | call to source2() : | string.swift:312:13:312:13 | str1 | result | +| string.swift:315:13:315:13 | str2 | string.swift:314:14:314:22 | call to source2() : | string.swift:315:13:315:13 | str2 | result | +| string.swift:317:13:317:13 | str2 | string.swift:314:14:314:22 | call to source2() : | string.swift:317:13:317:13 | str2 | result | +| string.swift:320:13:320:13 | str3 | string.swift:319:14:319:22 | call to source2() : | string.swift:320:13:320:13 | str3 | result | +| string.swift:322:13:322:13 | str3 | string.swift:319:14:319:22 | call to source2() : | string.swift:322:13:322:13 | str3 | result | +| string.swift:325:13:325:13 | str4 | string.swift:324:14:324:22 | call to source2() : | string.swift:325:13:325:13 | str4 | result | +| string.swift:326:13:326:30 | call to removeFirst() | string.swift:324:14:324:22 | call to source2() : | string.swift:326:13:326:30 | call to removeFirst() | result | +| string.swift:327:13:327:13 | str4 | string.swift:324:14:324:22 | call to source2() : | string.swift:327:13:327:13 | str4 | result | +| string.swift:329:13:329:13 | str4 | string.swift:324:14:324:22 | call to source2() : | string.swift:329:13:329:13 | str4 | result | +| string.swift:330:13:330:29 | call to removeLast() | string.swift:324:14:324:22 | call to source2() : | string.swift:330:13:330:29 | call to removeLast() | result | +| string.swift:331:13:331:13 | str4 | string.swift:324:14:324:22 | call to source2() : | string.swift:331:13:331:13 | str4 | result | +| string.swift:333:13:333:13 | str4 | string.swift:324:14:324:22 | call to source2() : | string.swift:333:13:333:13 | str4 | result | +| string.swift:336:13:336:13 | str5 | string.swift:335:14:335:22 | call to source2() : | string.swift:336:13:336:13 | str5 | result | +| string.swift:338:13:338:13 | str5 | string.swift:335:14:335:22 | call to source2() : | string.swift:338:13:338:13 | str5 | result | +| string.swift:341:13:341:13 | str6 | string.swift:340:14:340:22 | call to source2() : | string.swift:341:13:341:13 | str6 | result | +| string.swift:343:13:343:13 | str6 | string.swift:340:14:340:22 | call to source2() : | string.swift:343:13:343:13 | str6 | result | +| string.swift:348:13:348:13 | str7 | string.swift:347:62:347:70 | call to source2() : | string.swift:348:13:348:13 | str7 | result | +| string.swift:358:12:358:25 | ...! | string.swift:355:36:355:44 | call to source3() : | string.swift:358:12:358:25 | ...! | result | +| string.swift:361:13:361:54 | call to String.init(decoding:as:) | string.swift:361:30:361:38 | call to source3() : | string.swift:361:13:361:54 | call to String.init(decoding:as:) | result | +| string.swift:404:13:404:13 | arrayString2 | string.swift:366:17:366:25 | call to source2() : | string.swift:404:13:404:13 | arrayString2 | result | +| string.swift:470:13:470:78 | ...! | string.swift:450:28:450:36 | call to source4() : | string.swift:470:13:470:78 | ...! | result | +| string.swift:473:13:473:47 | call to String.init(cString:) | string.swift:450:28:450:36 | call to source4() : | string.swift:473:13:473:47 | call to String.init(cString:) | result | +| string.swift:526:13:526:47 | call to String.init(cString:) | string.swift:506:37:506:45 | call to source5() : | string.swift:526:13:526:47 | call to String.init(cString:) | result | +| string.swift:556:13:556:21 | call to source7() | string.swift:556:13:556:21 | call to source7() | string.swift:556:13:556:21 | call to source7() | result | +| string.swift:559:13:559:13 | sub1 | string.swift:554:17:554:25 | call to source2() : | string.swift:559:13:559:13 | sub1 | result | +| string.swift:560:13:560:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:560:13:560:24 | call to String.init(_:) | result | +| string.swift:563:13:563:13 | sub2 | string.swift:554:17:554:25 | call to source2() : | string.swift:563:13:563:13 | sub2 | result | +| string.swift:564:13:564:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:564:13:564:24 | call to String.init(_:) | result | +| string.swift:567:13:567:13 | sub3 | string.swift:554:17:554:25 | call to source2() : | string.swift:567:13:567:13 | sub3 | result | +| string.swift:568:13:568:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:568:13:568:24 | call to String.init(_:) | result | +| string.swift:571:13:571:13 | sub4 | string.swift:554:17:554:25 | call to source2() : | string.swift:571:13:571:13 | sub4 | result | +| string.swift:572:13:572:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:572:13:572:24 | call to String.init(_:) | result | +| string.swift:575:13:575:13 | sub5 | string.swift:554:17:554:25 | call to source2() : | string.swift:575:13:575:13 | sub5 | result | +| string.swift:576:13:576:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:576:13:576:24 | call to String.init(_:) | result | +| string.swift:579:13:579:13 | sub6 | string.swift:554:17:554:25 | call to source2() : | string.swift:579:13:579:13 | sub6 | result | +| string.swift:580:13:580:24 | call to String.init(_:) | string.swift:554:17:554:25 | call to source2() : | string.swift:580:13:580:24 | call to String.init(_:) | result | +| string.swift:636:13:636:28 | call to String.init(_:) | string.swift:636:20:636:27 | call to source() : | string.swift:636:13:636:28 | call to String.init(_:) | result | +| string.swift:640:13:640:40 | call to String.init(describing:) | string.swift:640:32:640:39 | call to source() : | string.swift:640:13:640:40 | call to String.init(describing:) | result | | subscript.swift:13:15:13:25 | ...[...] | subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] | result | | subscript.swift:14:15:14:26 | ...[...] | subscript.swift:14:15:14:23 | call to source2() : | subscript.swift:14:15:14:26 | ...[...] | result | | try.swift:9:13:9:24 | try ... | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/simple.swift b/swift/ql/test/library-tests/dataflow/taint/simple.swift new file mode 100644 index 00000000000..8ede1e6eb0c --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/taint/simple.swift @@ -0,0 +1,70 @@ + +// --- stubs --- + +// --- tests --- + +func source() -> Int { return 0; } +func sink(arg: Any) {} + +func taintThroughArithmetic() { + // arithmetic + + sink(arg: 1 + source()) // $ tainted=12 + sink(arg: source() + 1) // $ tainted=13 + sink(arg: 1 - source()) // $ tainted=14 + sink(arg: source() - 1) // $ tainted=15 + sink(arg: 2 * source()) // $ tainted=16 + sink(arg: source() * 2) // $ tainted=17 + sink(arg: 100 / source()) // $ tainted=18 + sink(arg: source() / 100) // $ tainted=19 + sink(arg: 100 % source()) // $ tainted=20 + sink(arg: source() % 100) // $ tainted=21 + + sink(arg: -source()) // $ tainted=23 + + // overflow operators + + sink(arg: 1 &+ source()) // $ MISSING: tainted= + sink(arg: source() &+ 1) // $ MISSING: tainted= + sink(arg: 1 &- source()) // $ MISSING: tainted= + sink(arg: source() &- 1) // $ MISSING: tainted= + sink(arg: 2 &* source()) // $ MISSING: tainted= + sink(arg: source() &* 2) // $ MISSING: tainted= +} + +func taintThroughAssignmentArithmetic() { + var a = 0 + sink(arg: a) + a += 1 + sink(arg: a) + a += source() + sink(arg: a) // $ MISSING: tainted= + a += 1 + sink(arg: a) // $ MISSING: tainted= + a = 0 + sink(arg: a) + + var b = 128 + b -= source() + sink(arg: b) // $ MISSING: tainted= + b -= 1 + sink(arg: b) // $ MISSING: tainted= + + var c = 10 + c *= source() + sink(arg: c) // $ MISSING: tainted= + c *= 2 + sink(arg: c) // $ MISSING: tainted= + + var d = 100 + d /= source() + sink(arg: d) // $ MISSING: tainted= + d /= 2 + sink(arg: d) // $ MISSING: tainted= + + var e = 1000 + e %= source() + sink(arg: e) // $ MISSING: tainted= + e %= 100 + sink(arg: e) // $ MISSING: tainted= +} diff --git a/swift/ql/test/library-tests/dataflow/taint/string.swift b/swift/ql/test/library-tests/dataflow/taint/string.swift index 45d4bb078a6..d1843d95ef2 100644 --- a/swift/ql/test/library-tests/dataflow/taint/string.swift +++ b/swift/ql/test/library-tests/dataflow/taint/string.swift @@ -82,6 +82,9 @@ extension String : CVarArg { func withPlatformString(_ body: (UnsafePointer) throws -> Result) rethrows -> Result { return 0 as! Result } init?(validating path: FilePath) { self.init() } + + mutating func replaceSubrange(_ subrange: Range, with newElements: C) + where C : Collection, C.Element == Character {} } extension StringProtocol { @@ -107,6 +110,8 @@ extension StringProtocol { func propertyListFromStringsFileFormat() -> [String : String] { return [:] } func cString(using encoding: String.Encoding) -> [CChar]? { return nil } func enumerateLines(invoking body: @escaping (String, inout Bool) -> Void) {} + func replacingOccurrences(of target: Target, with replacement: Replacement, options: String.CompareOptions = [], range searchRange: Range? = nil) -> String + where Target : StringProtocol, Replacement : StringProtocol { return "" } } class Data @@ -131,19 +136,19 @@ func sink(arg: Any) {} func taintThroughInterpolatedStrings() { var x = source() - sink(arg: "\(x)") // $ tainted=132 + sink(arg: "\(x)") // $ tainted=137 - sink(arg: "\(x) \(x)") // $ tainted=132 + sink(arg: "\(x) \(x)") // $ tainted=137 - sink(arg: "\(x) \(0) \(x)") // $ tainted=132 + sink(arg: "\(x) \(0) \(x)") // $ tainted=137 let y = 42 sink(arg: "\(y)") // clean - sink(arg: "\(x) hello \(y)") // $ tainted=132 + sink(arg: "\(x) hello \(y)") // $ tainted=137 - sink(arg: "\(y) world \(x)") // $ tainted=132 + sink(arg: "\(y) world \(x)") // $ tainted=137 x = 0 sink(arg: "\(x)") // clean @@ -156,55 +161,55 @@ func taintThroughStringConcatenation() { let tainted = source2() sink(arg: clean) - sink(arg: tainted) // $ tainted=156 + sink(arg: tainted) // $ tainted=161 sink(arg: clean + clean) - sink(arg: clean + tainted) // $ tainted=156 - sink(arg: tainted + clean) // $ tainted=156 - sink(arg: tainted + tainted) // $ tainted=156 + sink(arg: clean + tainted) // $ tainted=161 + sink(arg: tainted + clean) // $ tainted=161 + sink(arg: tainted + tainted) // $ tainted=161 sink(arg: ">" + clean + "<") - sink(arg: ">" + tainted + "<") // $ tainted=156 + sink(arg: ">" + tainted + "<") // $ tainted=161 sink(arg: clean.appending(clean)) - sink(arg: clean.appending(tainted)) // $ tainted=156 - sink(arg: tainted.appending(clean)) // $ tainted=156 - sink(arg: tainted.appending(tainted)) // $ tainted=156 + sink(arg: clean.appending(tainted)) // $ tainted=161 + sink(arg: tainted.appending(clean)) // $ tainted=161 + sink(arg: tainted.appending(tainted)) // $ tainted=161 var str = "abc" sink(arg: str) str += "def" sink(arg: str) str += source2() - sink(arg: str) // $ MISSING: tainted=178 + sink(arg: str) // $ MISSING: tainted=183 var str2 = "abc" sink(arg: str2) str2.append("def") sink(arg: str2) str2.append(source2()) - sink(arg: str2) // $ tainted=185 + sink(arg: str2) // $ tainted=190 var str3 = "abc" sink(arg: str3) str3.append(contentsOf: "def") sink(arg: str3) str3.append(contentsOf: source2()) - sink(arg: str3) // $ tainted=192 + sink(arg: str3) // $ tainted=197 var str4 = "abc" sink(arg: str4) str4.write("def") sink(arg: str4) str4.write(source2()) - sink(arg: str4) // $ tainted=199 + sink(arg: str4) // $ tainted=204 var str5 = "abc" sink(arg: str5) str5.insert(contentsOf: "abc", at: str5.startIndex) sink(arg: str5) str5.insert(contentsOf: source2(), at: str5.startIndex) - sink(arg: str5) // $ tainted=206 + sink(arg: str5) // $ tainted=211 } func taintThroughSimpleStringOperations() { @@ -213,42 +218,42 @@ func taintThroughSimpleStringOperations() { let taintedInt = source() sink(arg: String(clean)) - sink(arg: String(tainted)) // $ tainted=212 - sink(arg: String(taintedInt)) // $ tainted=213 + sink(arg: String(tainted)) // $ tainted=217 + sink(arg: String(taintedInt)) // $ tainted=218 - sink(arg: String(format: tainted, 1, 2, 3)) // $ tainted=212 - sink(arg: String(format: tainted, arguments: [])) // $ tainted=212 - sink(arg: String(format: tainted, locale: nil, 1, 2, 3)) // $ tainted=212 - sink(arg: String(format: tainted, locale: nil, arguments: [])) // $ tainted=212 - sink(arg: String.localizedStringWithFormat(tainted, 1, 2, 3)) // $ tainted=212 - sink(arg: String(format: "%s", tainted)) // $ MISSING: tainted=212 - sink(arg: String(format: "%i %i %i", 1, 2, taintedInt)) // $ MISSING: tainted=213 + sink(arg: String(format: tainted, 1, 2, 3)) // $ tainted=217 + sink(arg: String(format: tainted, arguments: [])) // $ tainted=217 + sink(arg: String(format: tainted, locale: nil, 1, 2, 3)) // $ tainted=217 + sink(arg: String(format: tainted, locale: nil, arguments: [])) // $ tainted=217 + sink(arg: String.localizedStringWithFormat(tainted, 1, 2, 3)) // $ tainted=217 + sink(arg: String(format: "%s", tainted)) // $ MISSING: tainted=217 + sink(arg: String(format: "%i %i %i", 1, 2, taintedInt)) // $ MISSING: tainted=218 sink(arg: String(repeating: clean, count: 2)) - sink(arg: String(repeating: tainted, count: 2)) // $ tainted=212 + sink(arg: String(repeating: tainted, count: 2)) // $ tainted=217 - sink(arg: tainted.dropFirst(10)) // $ tainted=212 - sink(arg: tainted.dropLast(10)) // $ tainted=212 - sink(arg: tainted.substring(from: tainted.startIndex)) // $ tainted=212 + sink(arg: tainted.dropFirst(10)) // $ tainted=217 + sink(arg: tainted.dropLast(10)) // $ tainted=217 + sink(arg: tainted.substring(from: tainted.startIndex)) // $ tainted=217 - sink(arg: tainted.lowercased()) // $ tainted=212 - sink(arg: tainted.uppercased()) // $ tainted=212 - sink(arg: tainted.lowercased(with: nil)) // $ tainted=212 - sink(arg: tainted.uppercased(with: nil)) // $ tainted=212 - sink(arg: tainted.capitalized(with: nil)) // $ tainted=212 - sink(arg: tainted.reversed()) // $ tainted=212 + sink(arg: tainted.lowercased()) // $ tainted=217 + sink(arg: tainted.uppercased()) // $ tainted=217 + sink(arg: tainted.lowercased(with: nil)) // $ tainted=217 + sink(arg: tainted.uppercased(with: nil)) // $ tainted=217 + sink(arg: tainted.capitalized(with: nil)) // $ tainted=217 + sink(arg: tainted.reversed()) // $ tainted=217 - sink(arg: tainted.split(separator: ",")) // $ tainted=212 - sink(arg: tainted.split(whereSeparator: { // $ tainted=212 + sink(arg: tainted.split(separator: ",")) // $ tainted=217 + sink(arg: tainted.split(whereSeparator: { c in return (c == ",") - })) - sink(arg: tainted.trimmingCharacters(in: CharacterSet.whitespaces)) // $ tainted=212 - sink(arg: tainted.padding(toLength: 20, withPad: " ", startingAt: 0)) // $ tainted=212 - sink(arg: tainted.components(separatedBy: CharacterSet.whitespaces)) // $ tainted=212 - sink(arg: tainted.components(separatedBy: CharacterSet.whitespaces)[0]) // $ tainted=212 - sink(arg: tainted.folding(locale: nil)) // $ tainted=212 - sink(arg: tainted.propertyListFromStringsFileFormat()) // $ tainted=212 - sink(arg: tainted.propertyListFromStringsFileFormat()["key"]!) // $ tainted=212 + })) // $ tainted=217 + sink(arg: tainted.trimmingCharacters(in: CharacterSet.whitespaces)) // $ tainted=217 + sink(arg: tainted.padding(toLength: 20, withPad: " ", startingAt: 0)) // $ tainted=217 + sink(arg: tainted.components(separatedBy: CharacterSet.whitespaces)) // $ tainted=217 + sink(arg: tainted.components(separatedBy: CharacterSet.whitespaces)[0]) // $ tainted=217 + sink(arg: tainted.folding(locale: nil)) // $ tainted=217 + sink(arg: tainted.propertyListFromStringsFileFormat()) // $ tainted=217 + sink(arg: tainted.propertyListFromStringsFileFormat()["key"]!) // $ tainted=217 sink(arg: clean.enumerateLines(invoking: { line, stop in @@ -257,81 +262,90 @@ func taintThroughSimpleStringOperations() { })) sink(arg: tainted.enumerateLines(invoking: { line, stop in - sink(arg: line) // $ MISSING: tainted=212 + sink(arg: line) // $ MISSING: tainted=217 sink(arg: stop) })) sink(arg: [clean, clean].joined()) - sink(arg: [tainted, clean].joined()) // $ MISSING: tainted=212 - sink(arg: [clean, tainted].joined()) // $ MISSING: tainted=212 - sink(arg: [tainted, tainted].joined()) // $ MISSING: tainted=212 + sink(arg: [tainted, clean].joined()) // $ MISSING: tainted=217 + sink(arg: [clean, tainted].joined()) // $ MISSING: tainted=217 + sink(arg: [tainted, tainted].joined()) // $ MISSING: tainted=217 sink(arg: clean.description) - sink(arg: tainted.description) // $ tainted=212 + sink(arg: tainted.description) // $ tainted=217 sink(arg: clean.debugDescription) - sink(arg: tainted.debugDescription) // $ tainted=212 + sink(arg: tainted.debugDescription) // $ tainted=217 sink(arg: clean.utf8) - sink(arg: tainted.utf8) // $ tainted=212 + sink(arg: tainted.utf8) // $ tainted=217 sink(arg: clean.utf16) - sink(arg: tainted.utf16) // $ tainted=212 + sink(arg: tainted.utf16) // $ tainted=217 sink(arg: clean.unicodeScalars) - sink(arg: tainted.unicodeScalars) // $ tainted=212 + sink(arg: tainted.unicodeScalars) // $ tainted=217 sink(arg: clean.utf8CString) - sink(arg: tainted.utf8CString) // $ tainted=212 + sink(arg: tainted.utf8CString) // $ tainted=217 sink(arg: clean.lazy) - sink(arg: tainted.lazy) // $ tainted=212 + sink(arg: tainted.lazy) // $ tainted=217 sink(arg: clean.capitalized) - sink(arg: tainted.capitalized) // $ tainted=212 + sink(arg: tainted.capitalized) // $ tainted=217 sink(arg: clean.localizedCapitalized) - sink(arg: tainted.localizedCapitalized) // $ tainted=212 + sink(arg: tainted.localizedCapitalized) // $ tainted=217 sink(arg: clean.localizedLowercase) - sink(arg: tainted.localizedLowercase) // $ tainted=212 + sink(arg: tainted.localizedLowercase) // $ tainted=217 sink(arg: clean.localizedUppercase) - sink(arg: tainted.localizedUppercase) // $ tainted=212 + sink(arg: tainted.localizedUppercase) // $ tainted=217 sink(arg: clean.decomposedStringWithCanonicalMapping) - sink(arg: tainted.decomposedStringWithCanonicalMapping) // $ tainted=212 + sink(arg: tainted.decomposedStringWithCanonicalMapping) // $ tainted=217 sink(arg: clean.precomposedStringWithCompatibilityMapping) - sink(arg: tainted.precomposedStringWithCompatibilityMapping) // $ tainted=212 + sink(arg: tainted.precomposedStringWithCompatibilityMapping) // $ tainted=217 sink(arg: clean.removingPercentEncoding!) - sink(arg: tainted.removingPercentEncoding!) // $ tainted=212 + sink(arg: tainted.removingPercentEncoding!) // $ tainted=217 + + sink(arg: clean.replacingOccurrences(of: "a", with: "b")) + sink(arg: tainted.replacingOccurrences(of: "a", with: "b")) // $ tainted=217 + sink(arg: clean.replacingOccurrences(of: "a", with: source2())) // $ tainted=305 } func taintThroughMutatingStringOperations() { var str1 = source2() - sink(arg: str1) // $ tainted=300 - sink(arg: str1.remove(at: str1.startIndex)) // $ tainted=300 - sink(arg: str1) // $ tainted=300 + sink(arg: str1) // $ tainted=309 + sink(arg: str1.remove(at: str1.startIndex)) // $ tainted=309 + sink(arg: str1) // $ tainted=309 var str2 = source2() - sink(arg: str2) // $ tainted=305 + sink(arg: str2) // $ tainted=314 str2.removeAll() - sink(arg: str2) // $ SPURIOUS: tainted=305 + sink(arg: str2) // $ SPURIOUS: tainted=314 var str3 = source2() - sink(arg: str3) // $ tainted=310 + sink(arg: str3) // $ tainted=319 str3.removeAll(where: { _ in true } ) - sink(arg: str3) // $ SPURIOUS: tainted=310 + sink(arg: str3) // $ SPURIOUS: tainted=319 var str4 = source2() - sink(arg: str4) // $ tainted=315 - sink(arg: str4.removeFirst()) // $ tainted=315 - sink(arg: str4) // $ tainted=315 + sink(arg: str4) // $ tainted=324 + sink(arg: str4.removeFirst()) // $ tainted=324 + sink(arg: str4) // $ tainted=324 str4.removeFirst(5) - sink(arg: str4) // $ tainted=315 - sink(arg: str4.removeLast()) // $ tainted=315 - sink(arg: str4) // $ tainted=315 + sink(arg: str4) // $ tainted=324 + sink(arg: str4.removeLast()) // $ tainted=324 + sink(arg: str4) // $ tainted=324 str4.removeLast(5) - sink(arg: str4) // $ tainted=315 + sink(arg: str4) // $ tainted=324 var str5 = source2() - sink(arg: str5) // $ tainted=326 + sink(arg: str5) // $ tainted=335 str5.removeSubrange(str5.startIndex ... str5.index(str5.startIndex, offsetBy: 5)) - sink(arg: str5) // $ tainted=326 + sink(arg: str5) // $ tainted=335 var str6 = source2() - sink(arg: str6) // $ tainted=331 + sink(arg: str6) // $ tainted=340 str6.makeContiguousUTF8() - sink(arg: str6) // $ tainted=331 + sink(arg: str6) // $ tainted=340 + + var str7 = "" + sink(arg: str7) + str7.replaceSubrange((nil as Range?)!, with: source2()) + sink(arg: str7) // $ tainted=347 } func source3() -> Data { return Data("") } @@ -341,10 +355,10 @@ func taintThroughData() { let stringTainted = String(data: source3(), encoding: String.Encoding.utf8) sink(arg: stringClean!) - sink(arg: stringTainted!) // $ tainted=341 + sink(arg: stringTainted!) // $ tainted=355 sink(arg: String(decoding: Data(""), as: UTF8.self)) - sink(arg: String(decoding: source3(), as: UTF8.self)) // $ tainted=347 + sink(arg: String(decoding: source3(), as: UTF8.self)) // $ tainted=361 } func taintThroughEncodings() { @@ -358,8 +372,8 @@ func taintThroughEncodings() { }) tainted.withUTF8({ buffer in - sink(arg: buffer) // $ MISSING: tainted=352 - sink(arg: buffer.baseAddress!) // $ MISSING: tainted=352 + sink(arg: buffer) // $ MISSING: tainted=366 + sink(arg: buffer.baseAddress!) // $ MISSING: tainted=366 }) clean.withCString({ @@ -368,7 +382,7 @@ func taintThroughEncodings() { }) tainted.withCString({ ptr in - sink(arg: ptr) // $ MISSING: tainted=352 + sink(arg: ptr) // $ MISSING: tainted=366 }) clean.withCString(encodedAs: UTF8.self, { ptr in @@ -376,7 +390,7 @@ func taintThroughEncodings() { }) tainted.withCString(encodedAs: UTF8.self, { ptr in - sink(arg: ptr) // $ MISSING: tainted=352 + sink(arg: ptr) // $ MISSING: tainted=366 }) let arrayString1 = clean.cString(using: String.Encoding.utf8)! @@ -387,11 +401,11 @@ func taintThroughEncodings() { sink(arg: String(cString: buffer.baseAddress!)) }) let arrayString2 = tainted.cString(using: String.Encoding.utf8)! - sink(arg: arrayString2) // $ tainted=352 + sink(arg: arrayString2) // $ tainted=366 arrayString1.withUnsafeBufferPointer({ buffer in - sink(arg: buffer) // $ MISSING: tainted=352 - sink(arg: String(cString: buffer.baseAddress!)) // $ MISSING: tainted=352 + sink(arg: buffer) // $ MISSING: tainted=366 + sink(arg: String(cString: buffer.baseAddress!)) // $ MISSING: tainted=366 }) clean.withPlatformString({ @@ -407,14 +421,14 @@ func taintThroughEncodings() { }) tainted.withPlatformString({ ptr in - sink(arg: ptr) // $ MISSING: tainted=352 - sink(arg: String(platformString: ptr)) // $ MISSING: tainted=352 + sink(arg: ptr) // $ MISSING: tainted=366 + sink(arg: String(platformString: ptr)) // $ MISSING: tainted=366 let buffer = UnsafeBufferPointer(start: ptr, count: 10) let arrayString = Array(buffer) - sink(arg: buffer) // $ MISSING: tainted=352 - sink(arg: arrayString) // $ MISSING: tainted=352 - sink(arg: String(platformString: arrayString)) // $ MISSING: tainted=352 + sink(arg: buffer) // $ MISSING: tainted=366 + sink(arg: arrayString) // $ MISSING: tainted=366 + sink(arg: String(platformString: arrayString)) // $ MISSING: tainted=366 }) clean.withContiguousStorageIfAvailable({ @@ -425,7 +439,7 @@ func taintThroughEncodings() { tainted.withContiguousStorageIfAvailable({ ptr in sink(arg: ptr) - sink(arg: ptr.baseAddress!) // $ MISSING: tainted=352 + sink(arg: ptr.baseAddress!) // $ MISSING: tainted=366 }) } @@ -443,20 +457,20 @@ func taintFromUInt8Array() { return 3 } )) - sink(arg: String(unsafeUninitializedCapacity: 256, initializingUTF8With: { // $ MISSING: tainted=436 + sink(arg: String(unsafeUninitializedCapacity: 256, initializingUTF8With: { // $ MISSING: tainted=450 (buffer: UnsafeMutableBufferPointer) -> Int in sink(arg: buffer) let _ = buffer.initialize(from: taintedUInt8Values) - sink(arg: buffer) // $ MISSING: tainted=436 + sink(arg: buffer) // $ MISSING: tainted=450 return 256 } )) sink(arg: String(bytes: cleanUInt8Values, encoding: String.Encoding.utf8)!) - sink(arg: String(bytes: taintedUInt8Values, encoding: String.Encoding.utf8)!) // $ tainted=436 + sink(arg: String(bytes: taintedUInt8Values, encoding: String.Encoding.utf8)!) // $ tainted=450 sink(arg: String(cString: cleanUInt8Values)) - sink(arg: String(cString: taintedUInt8Values)) // $ tainted=436 + sink(arg: String(cString: taintedUInt8Values)) // $ tainted=450 try! cleanUInt8Values.withUnsafeBufferPointer({ (buffer: UnsafeBufferPointer) throws in @@ -466,9 +480,9 @@ func taintFromUInt8Array() { }) try! taintedUInt8Values.withUnsafeBufferPointer({ (buffer: UnsafeBufferPointer) throws in - sink(arg: buffer) // $ MISSING: tainted=436 - sink(arg: buffer.baseAddress!) // $ MISSING: tainted=436 - sink(arg: String(cString: buffer.baseAddress!)) // $ MISSING: tainted=436 + sink(arg: buffer) // $ MISSING: tainted=450 + sink(arg: buffer.baseAddress!) // $ MISSING: tainted=450 + sink(arg: String(cString: buffer.baseAddress!)) // $ MISSING: tainted=450 }) try! cleanUInt8Values.withUnsafeMutableBytes({ @@ -479,9 +493,9 @@ func taintFromUInt8Array() { }) try! taintedUInt8Values.withUnsafeMutableBytes({ (buffer: UnsafeMutableRawBufferPointer) throws in - sink(arg: buffer) // $ MISSING: tainted=436 - sink(arg: buffer.baseAddress!) // $ MISSING: tainted=436 - sink(arg: String(bytesNoCopy: buffer.baseAddress!, length: buffer.count, encoding: String.Encoding.utf8, freeWhenDone: false)!) // $ MISSING: tainted=436 + sink(arg: buffer) // $ MISSING: tainted=450 + sink(arg: buffer.baseAddress!) // $ MISSING: tainted=450 + sink(arg: String(bytesNoCopy: buffer.baseAddress!, length: buffer.count, encoding: String.Encoding.utf8, freeWhenDone: false)!) // $ MISSING: tainted=450 }) } @@ -501,15 +515,15 @@ func taintThroughCCharArray() { }) taintedCCharValues.withUnsafeBufferPointer({ ptr in - sink(arg: ptr) // $ MISSING: tainted=492 - sink(arg: ptr.baseAddress!) // $ MISSING: tainted=492 - sink(arg: String(utf8String: ptr.baseAddress!)!) // $ MISSING: tainted=492 - sink(arg: String(validatingUTF8: ptr.baseAddress!)!) // $ MISSING: tainted=492 - sink(arg: String(cString: ptr.baseAddress!)) // $ MISSING: tainted=492 + sink(arg: ptr) // $ MISSING: tainted=506 + sink(arg: ptr.baseAddress!) // $ MISSING: tainted=506 + sink(arg: String(utf8String: ptr.baseAddress!)!) // $ MISSING: tainted=506 + sink(arg: String(validatingUTF8: ptr.baseAddress!)!) // $ MISSING: tainted=506 + sink(arg: String(cString: ptr.baseAddress!)) // $ MISSING: tainted=506 }) sink(arg: String(cString: cleanCCharValues)) - sink(arg: String(cString: taintedCCharValues)) // $ tainted=492 + sink(arg: String(cString: taintedCCharValues)) // $ tainted=506 } func source6() -> [unichar] { return [] } @@ -527,10 +541,10 @@ func taintThroughUnicharArray() { }) taintedUnicharValues.withUnsafeBufferPointer({ ptr in - sink(arg: ptr) // $ MISSING: tainted=519 - sink(arg: ptr.baseAddress!) // $ MISSING: tainted=519 - sink(arg: String(utf16CodeUnits: ptr.baseAddress!, count: ptr.count)) // $ MISSING: tainted=519 - sink(arg: String(utf16CodeUnitsNoCopy: ptr.baseAddress!, count: ptr.count, freeWhenDone: false)) // $ MISSING: tainted=519 + sink(arg: ptr) // $ MISSING: tainted=533 + sink(arg: ptr.baseAddress!) // $ MISSING: tainted=533 + sink(arg: String(utf16CodeUnits: ptr.baseAddress!, count: ptr.count)) // $ MISSING: tainted=533 + sink(arg: String(utf16CodeUnitsNoCopy: ptr.baseAddress!, count: ptr.count, freeWhenDone: false)) // $ MISSING: tainted=533 }) } @@ -539,31 +553,31 @@ func source7() -> Substring { return Substring() } func taintThroughSubstring() { let tainted = source2() - sink(arg: source7()) // $ tainted=542 + sink(arg: source7()) // $ tainted=556 let sub1 = tainted[tainted.startIndex ..< tainted.endIndex] - sink(arg: sub1) // $ tainted=540 - sink(arg: String(sub1)) // $ tainted=540 + sink(arg: sub1) // $ tainted=554 + sink(arg: String(sub1)) // $ tainted=554 let sub2 = tainted.prefix(10) - sink(arg: sub2) // $ tainted=540 - sink(arg: String(sub2)) // $ tainted=540 + sink(arg: sub2) // $ tainted=554 + sink(arg: String(sub2)) // $ tainted=554 let sub3 = tainted.prefix(through: tainted.endIndex) - sink(arg: sub3) // $ tainted=540 - sink(arg: String(sub3)) // $ tainted=540 + sink(arg: sub3) // $ tainted=554 + sink(arg: String(sub3)) // $ tainted=554 let sub4 = tainted.prefix(upTo: tainted.endIndex) - sink(arg: sub4) // $ tainted=540 - sink(arg: String(sub4)) // $ tainted=540 + sink(arg: sub4) // $ tainted=554 + sink(arg: String(sub4)) // $ tainted=554 let sub5 = tainted.suffix(10) - sink(arg: sub5) // $ tainted=540 - sink(arg: String(sub5)) // $ tainted=540 + sink(arg: sub5) // $ tainted=554 + sink(arg: String(sub5)) // $ tainted=554 let sub6 = tainted.suffix(from: tainted.startIndex) - sink(arg: sub6) // $ tainted=540 - sink(arg: String(sub6)) // $ tainted=540 + sink(arg: sub6) // $ tainted=554 + sink(arg: String(sub6)) // $ tainted=554 } func taintedThroughFilePath() { @@ -571,16 +585,16 @@ func taintedThroughFilePath() { let tainted = FilePath(source2()) sink(arg: clean) - sink(arg: tainted) // $ MISSING: tainted=571 + sink(arg: tainted) // $ MISSING: tainted=585 - sink(arg: tainted.extension!) // $ MISSING: tainted=571 - sink(arg: tainted.stem!) // $ MISSING: tainted=571 - sink(arg: tainted.string) // $ MISSING: tainted=571 - sink(arg: tainted.description) // $ MISSING: tainted=571 - sink(arg: tainted.debugDescription) // $ MISSING: tainted=571 + sink(arg: tainted.extension!) // $ MISSING: tainted=585 + sink(arg: tainted.stem!) // $ MISSING: tainted=585 + sink(arg: tainted.string) // $ MISSING: tainted=585 + sink(arg: tainted.description) // $ MISSING: tainted=585 + sink(arg: tainted.debugDescription) // $ MISSING: tainted=585 - sink(arg: String(decoding: tainted)) // $ MISSING: tainted=571 - sink(arg: String(validating: tainted)!) // $ MISSING: tainted=571 + sink(arg: String(decoding: tainted)) // $ MISSING: tainted=585 + sink(arg: String(validating: tainted)!) // $ MISSING: tainted=585 let _ = clean.withCString({ ptr in @@ -588,7 +602,7 @@ func taintedThroughFilePath() { }) let _ = tainted.withCString({ ptr in - sink(arg: ptr) // $ MISSING: tainted=571 + sink(arg: ptr) // $ MISSING: tainted=585 }) let _ = clean.withPlatformString({ @@ -599,34 +613,34 @@ func taintedThroughFilePath() { }) let _ = tainted.withPlatformString({ ptr in - sink(arg: ptr) // $ MISSING: tainted=571 - sink(arg: String(platformString: ptr)) // $ MISSING: tainted=571 - sink(arg: String(validatingPlatformString: ptr)!) // $ MISSING: tainted=571 + sink(arg: ptr) // $ MISSING: tainted=585 + sink(arg: String(platformString: ptr)) // $ MISSING: tainted=585 + sink(arg: String(validatingPlatformString: ptr)!) // $ MISSING: tainted=585 }) var fp1 = FilePath("") sink(arg: fp1) fp1.append(source2()) - sink(arg: fp1) // $ MISSING: tainted=609 + sink(arg: fp1) // $ MISSING: tainted=623 fp1.append("") - sink(arg: fp1) // $ MISSING: tainted=609 + sink(arg: fp1) // $ MISSING: tainted=623 sink(arg: clean.appending("")) - sink(arg: clean.appending(source2())) // $ MISSING: tainted=615 - sink(arg: tainted.appending("")) // $ MISSING: tainted=571 - sink(arg: tainted.appending(source2())) // $ MISSING: tainted=571,617 + sink(arg: clean.appending(source2())) // $ MISSING: tainted=629 + sink(arg: tainted.appending("")) // $ MISSING: tainted=585 + sink(arg: tainted.appending(source2())) // $ MISSING: tainted=585,631 } func taintedThroughConversion() { sink(arg: String(0)) - sink(arg: String(source())) // $ tainted=622 + sink(arg: String(source())) // $ tainted=636 sink(arg: Int(0).description) - sink(arg: source().description) // $ MISSING: tainted=624 + sink(arg: source().description) // $ MISSING: tainted=638 sink(arg: String(describing: 0)) - sink(arg: String(describing: source())) // $ tainted=626 + sink(arg: String(describing: source())) // $ tainted=640 sink(arg: Int("123")!) - sink(arg: Int(source2())!) // $ MISSING: tainted=629 + sink(arg: Int(source2())!) // $ MISSING: tainted=643 } func untaintedFields() { diff --git a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.expected b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.expected index 248df8d5d40..b9e72064b4f 100644 --- a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.expected +++ b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.expected @@ -4,3 +4,4 @@ | arithmeticoperation.swift:9:6:9:10 | ... ./(_:_:) ... | BinaryArithmeticOperation, DivExpr | | arithmeticoperation.swift:10:6:10:10 | ... .%(_:_:) ... | BinaryArithmeticOperation, RemExpr | | arithmeticoperation.swift:11:6:11:7 | call to -(_:) | UnaryArithmeticOperation, UnaryMinusExpr | +| arithmeticoperation.swift:12:6:12:7 | call to +(_:) | UnaryArithmeticOperation, UnaryPlusExpr | diff --git a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.ql b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.ql index 9d98daa68af..ce0de008255 100644 --- a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.ql +++ b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.ql @@ -16,6 +16,8 @@ string describe(ArithmeticOperation e) { e instanceof UnaryArithmeticOperation and result = "UnaryArithmeticOperation" or e instanceof UnaryMinusExpr and result = "UnaryMinusExpr" + or + e instanceof UnaryPlusExpr and result = "UnaryPlusExpr" } from ArithmeticOperation e diff --git a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.swift b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.swift index 096b6709600..74b15b2d846 100644 --- a/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.swift +++ b/swift/ql/test/library-tests/elements/expr/arithmeticoperation/arithmeticoperation.swift @@ -9,4 +9,5 @@ func test(c: Bool, x: Int, y: Int, z: Int) { v = 3 / 4; v = x % y; v = -x; + v = +x; } diff --git a/swift/ql/test/query-tests/Security/CWE-022/testPathInjection.swift b/swift/ql/test/query-tests/Security/CWE-022/testPathInjection.swift index fbca64d0652..bceeaf1a1ed 100644 --- a/swift/ql/test/query-tests/Security/CWE-022/testPathInjection.swift +++ b/swift/ql/test/query-tests/Security/CWE-022/testPathInjection.swift @@ -9,13 +9,32 @@ class NSURL { } extension String { - init(contentsOf: URL) { + struct Encoding { + static let utf8 = Encoding() + } + + init(contentsOf: URL) { let data = "" self.init(data) } + + init(contentsOfFile path: String) throws { + self.init("") + } + + init(contentsOfFile path: String, encoding enc: String.Encoding) throws { + self.init("") + } + + init(contentsOfFile path: String, usedEncoding: inout String.Encoding) throws { + self.init("") + } } class NSString { + convenience init(contentsOfFile path: String, encoding enc: UInt) throws { self.init() } + convenience init(contentsOfFile path: String, usedEncoding enc: UnsafeMutablePointer?) throws { self.init() } + func write(toFile: String, atomically: Bool, encoding: UInt) {} func write(to: URL, atomically: Bool, encoding: UInt) {} } @@ -166,91 +185,99 @@ func test() { let safeUrl = URL(string: "")! let safeNsUrl = NSURL(string: "")! - Data("").write(to: remoteUrl, options: []) // $ hasPathInjection=163 + Data("").write(to: remoteUrl, options: []) // $ hasPathInjection=182 let nsData = NSData() - let _ = nsData.write(to: remoteUrl, atomically: false) // $ hasPathInjection=163 - nsData.write(to: remoteUrl, options: []) // $ hasPathInjection=163 - let _ = nsData.write(toFile: remoteString, atomically: false) // $ hasPathInjection=163 - nsData.write(toFile: remoteString, options: []) // $ hasPathInjection=163 + let _ = nsData.write(to: remoteUrl, atomically: false) // $ hasPathInjection=182 + nsData.write(to: remoteUrl, options: []) // $ hasPathInjection=182 + let _ = nsData.write(toFile: remoteString, atomically: false) // $ hasPathInjection=182 + nsData.write(toFile: remoteString, options: []) // $ hasPathInjection=182 let fm = FileManager() - let _ = fm.contentsOfDirectory(at: remoteUrl, includingPropertiesForKeys: [], options: []) // $ hasPathInjection=163 - let _ = fm.contentsOfDirectory(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.enumerator(at: remoteUrl, includingPropertiesForKeys: [], options: [], errorHandler: nil) // $ hasPathInjection=163 - let _ = fm.enumerator(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.subpathsOfDirectory(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.subpaths(atPath: remoteString) // $ hasPathInjection=163 - fm.createDirectory(at: remoteUrl, withIntermediateDirectories: false, attributes: [:]) // $ hasPathInjection=163 - let _ = fm.createDirectory(atPath: remoteString, attributes: [:]) // $ hasPathInjection=163 - let _ = fm.createFile(atPath: remoteString, contents: nil, attributes: [:]) // $ hasPathInjection=163 - fm.removeItem(at: remoteUrl) // $ hasPathInjection=163 - fm.removeItem(atPath: remoteString) // $ hasPathInjection=163 - fm.trashItem(at: remoteUrl, resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=163 - let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ hasPathInjection=163 - let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ hasPathInjection=163 - fm.replaceItem(at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=163 - fm.replaceItem(at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=163 - fm.copyItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=163 - fm.copyItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=163 - fm.copyItem(atPath: remoteString, toPath: "") // $ hasPathInjection=163 - fm.copyItem(atPath: "", toPath: remoteString) // $ hasPathInjection=163 - fm.moveItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=163 - fm.moveItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=163 - fm.moveItem(atPath: remoteString, toPath: "") // $ hasPathInjection=163 - fm.moveItem(atPath: "", toPath: remoteString) // $ hasPathInjection=163 - fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ hasPathInjection=163 - fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ hasPathInjection=163 - fm.createSymbolicLink(atPath: remoteString, withDestinationPath: "") // $ hasPathInjection=163 - fm.createSymbolicLink(atPath: "", withDestinationPath: remoteString) // $ hasPathInjection=163 - fm.linkItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=163 - fm.linkItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=163 - fm.linkItem(atPath: remoteString, toPath: "") // $ hasPathInjection=163 - fm.linkItem(atPath: "", toPath: remoteString) // $ hasPathInjection=163 - let _ = fm.destinationOfSymbolicLink(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.fileExists(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.fileExists(atPath: remoteString, isDirectory: UnsafeMutablePointer.init(bitPattern: 0)) // $ hasPathInjection=163 - fm.setAttributes([:], ofItemAtPath: remoteString) // $ hasPathInjection=163 - let _ = fm.contents(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.contentsEqual(atPath: remoteString, andPath: "") // $ hasPathInjection=163 - let _ = fm.contentsEqual(atPath: "", andPath: remoteString) // $ hasPathInjection=163 - let _ = fm.changeCurrentDirectoryPath(remoteString) // $ hasPathInjection=163 - let _ = fm.unmountVolume(at: remoteUrl, options: [], completionHandler: { _ in }) // $ hasPathInjection=163 + let _ = fm.contentsOfDirectory(at: remoteUrl, includingPropertiesForKeys: [], options: []) // $ hasPathInjection=182 + let _ = fm.contentsOfDirectory(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.enumerator(at: remoteUrl, includingPropertiesForKeys: [], options: [], errorHandler: nil) // $ hasPathInjection=182 + let _ = fm.enumerator(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.subpathsOfDirectory(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.subpaths(atPath: remoteString) // $ hasPathInjection=182 + fm.createDirectory(at: remoteUrl, withIntermediateDirectories: false, attributes: [:]) // $ hasPathInjection=182 + let _ = fm.createDirectory(atPath: remoteString, attributes: [:]) // $ hasPathInjection=182 + let _ = fm.createFile(atPath: remoteString, contents: nil, attributes: [:]) // $ hasPathInjection=182 + fm.removeItem(at: remoteUrl) // $ hasPathInjection=182 + fm.removeItem(atPath: remoteString) // $ hasPathInjection=182 + fm.trashItem(at: remoteUrl, resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=182 + let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ hasPathInjection=182 + let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ hasPathInjection=182 + fm.replaceItem(at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=182 + fm.replaceItem(at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ hasPathInjection=182 + fm.copyItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=182 + fm.copyItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=182 + fm.copyItem(atPath: remoteString, toPath: "") // $ hasPathInjection=182 + fm.copyItem(atPath: "", toPath: remoteString) // $ hasPathInjection=182 + fm.moveItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=182 + fm.moveItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=182 + fm.moveItem(atPath: remoteString, toPath: "") // $ hasPathInjection=182 + fm.moveItem(atPath: "", toPath: remoteString) // $ hasPathInjection=182 + fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ hasPathInjection=182 + fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ hasPathInjection=182 + fm.createSymbolicLink(atPath: remoteString, withDestinationPath: "") // $ hasPathInjection=182 + fm.createSymbolicLink(atPath: "", withDestinationPath: remoteString) // $ hasPathInjection=182 + fm.linkItem(at: remoteUrl, to: safeUrl) // $ hasPathInjection=182 + fm.linkItem(at: safeUrl, to: remoteUrl) // $ hasPathInjection=182 + fm.linkItem(atPath: remoteString, toPath: "") // $ hasPathInjection=182 + fm.linkItem(atPath: "", toPath: remoteString) // $ hasPathInjection=182 + let _ = fm.destinationOfSymbolicLink(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.fileExists(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.fileExists(atPath: remoteString, isDirectory: UnsafeMutablePointer.init(bitPattern: 0)) // $ hasPathInjection=182 + fm.setAttributes([:], ofItemAtPath: remoteString) // $ hasPathInjection=182 + let _ = fm.contents(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.contentsEqual(atPath: remoteString, andPath: "") // $ hasPathInjection=182 + let _ = fm.contentsEqual(atPath: "", andPath: remoteString) // $ hasPathInjection=182 + let _ = fm.changeCurrentDirectoryPath(remoteString) // $ hasPathInjection=182 + let _ = fm.unmountVolume(at: remoteUrl, options: [], completionHandler: { _ in }) // $ hasPathInjection=182 // Deprecated methods - let _ = fm.changeFileAttributes([:], atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.directoryContents(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.createDirectory(atPath: remoteString, attributes: [:]) // $ hasPathInjection=163 - let _ = fm.createSymbolicLink(atPath: remoteString, pathContent: "") // $ hasPathInjection=163 - let _ = fm.createSymbolicLink(atPath: "", pathContent: remoteString) // $ hasPathInjection=163 - let _ = fm.pathContentOfSymbolicLink(atPath: remoteString) // $ hasPathInjection=163 - let _ = fm.replaceItemAtURL(originalItemURL: remoteNsUrl, withItemAtURL: safeNsUrl, backupItemName: nil, options: []) // $ hasPathInjection=163 - let _ = fm.replaceItemAtURL(originalItemURL: safeNsUrl, withItemAtURL: remoteNsUrl, backupItemName: nil, options: []) // $ hasPathInjection=163 + let _ = fm.changeFileAttributes([:], atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.directoryContents(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.createDirectory(atPath: remoteString, attributes: [:]) // $ hasPathInjection=182 + let _ = fm.createSymbolicLink(atPath: remoteString, pathContent: "") // $ hasPathInjection=182 + let _ = fm.createSymbolicLink(atPath: "", pathContent: remoteString) // $ hasPathInjection=182 + let _ = fm.pathContentOfSymbolicLink(atPath: remoteString) // $ hasPathInjection=182 + let _ = fm.replaceItemAtURL(originalItemURL: remoteNsUrl, withItemAtURL: safeNsUrl, backupItemName: nil, options: []) // $ hasPathInjection=182 + let _ = fm.replaceItemAtURL(originalItemURL: safeNsUrl, withItemAtURL: remoteNsUrl, backupItemName: nil, options: []) // $ hasPathInjection=182 - NSString().write(to: remoteUrl, atomically: true, encoding: 0) // $ hasPathInjection=163 - NSString().write(toFile: remoteString, atomically: true, encoding: 0) // $ hasPathInjection=163 - let _ = NSKeyedUnarchiver().unarchiveObject(withFile: remoteString) // $ hasPathInjection=163 - let _ = ArchiveByteStream.fileStream(fd: remoteString as! FileDescriptor, automaticClose: true) // $ hasPathInjection=163 - ArchiveByteStream.withFileStream(fd: remoteString as! FileDescriptor, automaticClose: true) { _ in } // $ hasPathInjection=163 - let _ = ArchiveByteStream.fileStream(path: FilePath(stringLiteral: remoteString), mode: .readOnly, options: .append, permissions: .ownerRead) // $ hasPathInjection=163 - ArchiveByteStream.withFileStream(path: FilePath(stringLiteral: remoteString), mode: .readOnly, options: .append, permissions: .ownerRead) { _ in } // $ hasPathInjection=163 - let _ = Bundle(url: remoteUrl) // $ hasPathInjection=163 - let _ = Bundle(path: remoteString) // $ hasPathInjection=163 + var encoding = String.Encoding.utf8 + let _ = try! String(contentsOfFile: remoteString) // $ hasPathInjection=182 + let _ = try! String(contentsOfFile: remoteString, encoding: String.Encoding.utf8) // $ hasPathInjection=182 + let _ = try! String(contentsOfFile: remoteString, usedEncoding: &encoding) // $ hasPathInjection=182 - let _ = Database(path: remoteString, description: "", configuration: Configuration()) // $ hasPathInjection=163 + let _ = try! NSString(contentsOfFile: remoteString, encoding: 0) // $ hasPathInjection=182 + let _ = try! NSString(contentsOfFile: remoteString, usedEncoding: nil) // $ hasPathInjection=182 + NSString().write(to: remoteUrl, atomically: true, encoding: 0) // $ hasPathInjection=182 + NSString().write(toFile: remoteString, atomically: true, encoding: 0) // $ hasPathInjection=182 + + let _ = NSKeyedUnarchiver().unarchiveObject(withFile: remoteString) // $ hasPathInjection=182 + let _ = ArchiveByteStream.fileStream(fd: remoteString as! FileDescriptor, automaticClose: true) // $ hasPathInjection=182 + ArchiveByteStream.withFileStream(fd: remoteString as! FileDescriptor, automaticClose: true) { _ in } // $ hasPathInjection=182 + let _ = ArchiveByteStream.fileStream(path: FilePath(stringLiteral: remoteString), mode: .readOnly, options: .append, permissions: .ownerRead) // $ hasPathInjection=182 + ArchiveByteStream.withFileStream(path: FilePath(stringLiteral: remoteString), mode: .readOnly, options: .append, permissions: .ownerRead) { _ in } // $ hasPathInjection=182 + let _ = Bundle(url: remoteUrl) // $ hasPathInjection=182 + let _ = Bundle(path: remoteString) // $ hasPathInjection=182 + + let _ = Database(path: remoteString, description: "", configuration: Configuration()) // $ hasPathInjection=182 let _ = Database(path: "", description: "", configuration: Configuration()) // Safe - let _ = DatabasePool(path: remoteString, configuration: Configuration()) // $ hasPathInjection=163 + let _ = DatabasePool(path: remoteString, configuration: Configuration()) // $ hasPathInjection=182 let _ = DatabasePool(path: "", configuration: Configuration()) // Safe - let _ = DatabaseQueue(path: remoteString, configuration: Configuration()) // $ hasPathInjection=163 + let _ = DatabaseQueue(path: remoteString, configuration: Configuration()) // $ hasPathInjection=182 let _ = DatabaseQueue(path: "", configuration: Configuration()) // Safe - let _ = DatabaseSnapshotPool(path: remoteString, configuration: Configuration()) // $ hasPathInjection=163 + let _ = DatabaseSnapshotPool(path: remoteString, configuration: Configuration()) // $ hasPathInjection=182 let _ = DatabaseSnapshotPool(path: "", configuration: Configuration()) // Safe - let _ = SerializedDatabase(path: remoteString, defaultLabel: "") // $ hasPathInjection=163 + let _ = SerializedDatabase(path: remoteString, defaultLabel: "") // $ hasPathInjection=182 let _ = SerializedDatabase(path: "", defaultLabel: "") // Safe - let _ = SerializedDatabase(path: remoteString, defaultLabel: "", purpose: nil) // $ hasPathInjection=163 + let _ = SerializedDatabase(path: remoteString, defaultLabel: "", purpose: nil) // $ hasPathInjection=182 let _ = SerializedDatabase(path: "", defaultLabel: "", purpose: nil) // Safe - let _ = SerializedDatabase(path: remoteString, configuration: Configuration(), defaultLabel: "") // $ hasPathInjection=163 + let _ = SerializedDatabase(path: remoteString, configuration: Configuration(), defaultLabel: "") // $ hasPathInjection=182 let _ = SerializedDatabase(path: "", configuration: Configuration(), defaultLabel: "") // Safe - let _ = SerializedDatabase(path: remoteString, configuration: Configuration(), defaultLabel: "", purpose: nil) // $ hasPathInjection=163 + let _ = SerializedDatabase(path: remoteString, configuration: Configuration(), defaultLabel: "", purpose: nil) // $ hasPathInjection=182 let _ = SerializedDatabase(path: "", configuration: Configuration(), defaultLabel: "", purpose: nil) // Safe } @@ -263,5 +290,5 @@ func testSanitizers() { if (filePath.lexicallyNormalized().starts(with: "/safe")) { let _ = fm.contents(atPath: remoteString) // Safe } - let _ = fm.contents(atPath: remoteString) // $ hasPathInjection=258 + let _ = fm.contents(atPath: remoteString) // $ hasPathInjection=285 } diff --git a/swift/schema.py b/swift/schema.py index 251db0f242f..9c94a642369 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -9,7 +9,7 @@ This file should be kept simple: For how documentation of generated QL code works, please read schema_documentation.md. """ -from swift.codegen.lib.schema.defs import * +from misc.codegen.lib.schemadefs import * include("prefix.dbscheme") diff --git a/swift/third_party/load.bzl b/swift/third_party/load.bzl index bf6e4ae600e..8bbb0089957 100644 --- a/swift/third_party/load.bzl +++ b/swift/third_party/load.bzl @@ -1,9 +1,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -_swift_prebuilt_version = "swift-5.7.1-RELEASE.44582.104" +_swift_prebuilt_version = "swift-5.7.3-RELEASE.124" _swift_sha_map = { - "Linux-X64": "8d94f2d75f2aa9ee8e5421318d2f07b27e095127c9be0156794a88d8e9a0f19a", - "macOS-X64": "5f0550d2924e7071d006a0c9802acbd9a11f0017073e4a1eb27b7ddc4764f3f2", + "Linux-X64": "9d89a101e09a4581b014b04f266f21192530b56124c91653658606ae2af4f75a", + "macOS-ARM64": "95136fadf91d317526ad61d393e9ac31cb564534105777d04650b048d923c58d", + "macOS-X64": "b91725a401b9d33f235f3ad3435a2fe9a36585a83d368a924d6e274e05499773", } _swift_arch_map = {