mirror of
https://github.com/github/codeql.git
synced 2026-05-26 17:11:24 +02:00
Compare commits
1 Commits
esbena/ena
...
esbena/act
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a68709955 |
@@ -1 +0,0 @@
|
||||
5.0.0
|
||||
14
.github/actions/fetch-codeql/action.yml
vendored
14
.github/actions/fetch-codeql/action.yml
vendored
@@ -3,22 +3,12 @@ description: Fetches the latest version of CodeQL
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Select platform - Linux
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: echo "GA_CODEQL_CLI_PLATFORM=linux64" >> $GITHUB_ENV
|
||||
|
||||
- name: Select platform - MacOS
|
||||
if: runner.os == 'MacOS'
|
||||
shell: bash
|
||||
run: echo "GA_CODEQL_CLI_PLATFORM=osx64" >> $GITHUB_ENV
|
||||
|
||||
- name: Fetch CodeQL
|
||||
shell: bash
|
||||
run: |
|
||||
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
|
||||
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-$GA_CODEQL_CLI_PLATFORM.zip "$LATEST"
|
||||
unzip -q -d "${RUNNER_TEMP}" codeql-$GA_CODEQL_CLI_PLATFORM.zip
|
||||
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
|
||||
unzip -q -d "${RUNNER_TEMP}" codeql-linux64.zip
|
||||
echo "${RUNNER_TEMP}/codeql" >> "${GITHUB_PATH}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
53
.github/workflows/post-pr-comment.yml
vendored
53
.github/workflows/post-pr-comment.yml
vendored
@@ -1,17 +1,12 @@
|
||||
# This workflow is the second part of the process described in
|
||||
# .github/workflows/qhelp-pr-preview.yml
|
||||
# See that file for more info.
|
||||
|
||||
name: Post PR comment
|
||||
name: Post pull-request comment
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Render QHelp changes]
|
||||
workflows: ["Query help preview"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
post_comment:
|
||||
@@ -22,53 +17,15 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
|
||||
- name: Check that PR SHA matches workflow SHA
|
||||
run: |
|
||||
PR="$(grep -o '^[0-9]\+$' pr_number.txt)"
|
||||
- run: |
|
||||
PR="$(grep -o '^[0-9]\+$' pr.txt)"
|
||||
PR_HEAD_SHA="$(gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR}" --jq .head.sha)"
|
||||
# Check that the pull-request head SHA matches the head SHA of the workflow run
|
||||
if [ "${WORKFLOW_RUN_HEAD_SHA}" != "${PR_HEAD_SHA}" ]; then
|
||||
echo "PR head SHA ${PR_HEAD_SHA} does not match workflow_run event SHA ${WORKFLOW_RUN_HEAD_SHA}. Stopping." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
gh pr comment "${PR}" --repo "${GITHUB_REPOSITORY}" -F comment.txt
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
WORKFLOW_RUN_HEAD_SHA: ${{ github.event.workflow_run.head_commit.id }}
|
||||
|
||||
- name: Create or update comment
|
||||
run: |
|
||||
COMMENT_PREFIX="QHelp previews"
|
||||
COMMENT_AUTHOR="github-actions[bot]"
|
||||
PR_NUMBER="$(grep -o '^[0-9]\+$' pr_number.txt)"
|
||||
|
||||
# If there is no existing comment, comment_id.txt will contain just a
|
||||
# newline (due to jq & gh behaviour). This will cause grep to fail, so
|
||||
# we catch that.
|
||||
RAW_COMMENT_ID=$(grep -o '^[0-9]\+$' comment_id.txt || true)
|
||||
|
||||
if [ $RAW_COMMENT_ID ]
|
||||
then
|
||||
# Fetch existing comment, and validate:
|
||||
# - comment belongs to the PR with number $PR_NUMBER
|
||||
# - comment starts with the expected prefix ("QHelp previews")
|
||||
# - comment author is github-actions[bot]
|
||||
FILTER='select(.issue_url | endswith($repo+"/issues/"+$pr))
|
||||
| select(.body | startswith($prefix))
|
||||
| select(.user.login == $author)
|
||||
| .id'
|
||||
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/comments/${RAW_COMMENT_ID}" | jq --arg repo "${GITHUB_REPOSITORY}" --arg pr "${PR_NUMBER}" --arg prefix "${COMMENT_PREFIX}" --arg author "${COMMENT_AUTHOR}" "${FILTER}")
|
||||
if [ $COMMENT_ID ]
|
||||
then
|
||||
# Update existing comment
|
||||
jq --rawfile body comment_body.txt '{"body":$body}' -n | gh api "repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}" -X PATCH --input -
|
||||
else
|
||||
echo "Comment ${RAW_COMMENT_ID} did not pass validations: not editing." >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Create new comment
|
||||
jq --rawfile body comment_body.txt '{"body":$body}' -n | gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" -X POST --input -
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
51
.github/workflows/qhelp-pr-preview.yml
vendored
51
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -1,25 +1,7 @@
|
||||
# This workflow checks for any changes in .qhelp files in pull requests.
|
||||
# For any changed files, it renders them to markdown in a file called `comment_body.txt`.
|
||||
# It then checks if there's an existing comment on the pull request generated by
|
||||
# this workflow, and writes the comment ID to `comment_id.txt`.
|
||||
# It also writes the PR number to `pr_number.txt`.
|
||||
# These three files are uploaded as an artifact.
|
||||
|
||||
# When this workflow completes, the workflow "Post PR comment" runs.
|
||||
# It downloads the artifact and adds a comment to the PR with the rendered
|
||||
# QHelp.
|
||||
|
||||
# The task is split like this because creating PR comments requires extra
|
||||
# permissions that we don't want to expose to PRs from external forks.
|
||||
|
||||
# For more info see:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run
|
||||
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
|
||||
name: Render QHelp changes
|
||||
name: Query help preview
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -33,16 +15,12 @@ jobs:
|
||||
qhelp:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "${PR_NUMBER}" > pr_number.txt
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
- run: echo "${{ github.event.number }}" > pr.txt
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: comment
|
||||
path: pr_number.txt
|
||||
if-no-files-found: error
|
||||
path: pr.txt
|
||||
retention-days: 1
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
@@ -58,7 +36,7 @@ jobs:
|
||||
- name: QHelp preview
|
||||
run: |
|
||||
EXIT_CODE=0
|
||||
echo "QHelp previews:" > comment_body.txt
|
||||
echo "QHelp previews:" > comment.txt
|
||||
while read -r -d $'\0' path; do
|
||||
if [ ! -f "${path}" ]; then
|
||||
exit 1
|
||||
@@ -74,29 +52,12 @@ jobs:
|
||||
echo '```'
|
||||
fi
|
||||
echo "</details>"
|
||||
done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt
|
||||
done < "${RUNNER_TEMP}/paths.txt" >> comment.txt
|
||||
exit "${EXIT_CODE}"
|
||||
|
||||
- if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: comment
|
||||
path: comment_body.txt
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Save ID of existing QHelp comment (if it exists)
|
||||
run: |
|
||||
# Find the latest comment starting with "QHelp previews"
|
||||
COMMENT_PREFIX="QHelp previews"
|
||||
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate | jq --arg prefix "${COMMENT_PREFIX}" '[.[] | select(.body|startswith($prefix)) | .id] | max' > comment_id.txt
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: comment
|
||||
path: comment_id.txt
|
||||
if-no-files-found: error
|
||||
path: comment.txt
|
||||
retention-days: 1
|
||||
|
||||
51
.github/workflows/swift-qltest.yml
vendored
51
.github/workflows/swift-qltest.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: "Swift: Run QL Tests"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "swift/**"
|
||||
- .github/workflows/swift-qltest.yml
|
||||
branches:
|
||||
- main
|
||||
defaults:
|
||||
run:
|
||||
working-directory: swift
|
||||
|
||||
jobs:
|
||||
qlformat:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check QL formatting
|
||||
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
|
||||
qltest:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os : [ubuntu-20.04, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Install bazelisk - Linux
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y wget
|
||||
wget https://github.com/bazelbuild/bazelisk/releases/download/v1.11.0/bazelisk-linux-amd64
|
||||
mv bazelisk-linux-amd64 /usr/local/bin/bazel
|
||||
chmod +x /usr/local/bin/bazel
|
||||
- name: Install bazelisk - macOS
|
||||
if: runner.os == 'MacOS'
|
||||
run: |
|
||||
brew install bazelisk
|
||||
- name: Build Swift extractor
|
||||
run: |
|
||||
bazel run //swift:create-extractor-pack
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --threads=0 --ram 5000 --search-path "${{ github.workspace }}/swift/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition ql/test
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -31,8 +31,5 @@ csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# links created by bazel
|
||||
# links create by bazel
|
||||
/bazel-*
|
||||
|
||||
# CLion project files
|
||||
/.clwb
|
||||
|
||||
@@ -2,41 +2,28 @@
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v13.0.1
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: clang-format
|
||||
files: ^swift/.*\.(h|c|cpp)$
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: codeql-format
|
||||
- id: codeql-format
|
||||
name: Fix QL file formatting
|
||||
files: \.qll?$
|
||||
language: system
|
||||
entry: codeql query format --in-place
|
||||
|
||||
- id: sync-files
|
||||
- id: sync-files
|
||||
name: Fix files required to be identical
|
||||
language: system
|
||||
entry: python3 config/sync-files.py --latest
|
||||
pass_filenames: false
|
||||
|
||||
- id: qhelp
|
||||
- id: qhelp
|
||||
name: Check query help generation
|
||||
files: \.qhelp$
|
||||
language: system
|
||||
entry: python3 misc/scripts/check-qhelp.py
|
||||
|
||||
- id: swift-codegen
|
||||
name: Run Swift checked in code generation
|
||||
files: ^swift/(codegen/|.*/generated/|ql/lib/swift\.dbscheme$)
|
||||
language: system
|
||||
entry: bazel run //swift/codegen
|
||||
pass_filenames: false
|
||||
|
||||
@@ -27,7 +27,3 @@
|
||||
# Bazel
|
||||
**/*.bazel @github/codeql-ci-reviewers
|
||||
**/*.bzl @github/codeql-ci-reviewers
|
||||
|
||||
# Documentation etc
|
||||
/*.md @github/code-scanning-product
|
||||
/LICENSE @github/code-scanning-product
|
||||
|
||||
@@ -13,9 +13,7 @@ We welcome contributions to our standard library and standard checks. Do you hav
|
||||
|
||||
## License
|
||||
|
||||
The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com).
|
||||
|
||||
The CodeQL CLI (including the CodeQL engine) is hosted in a [different repository](https://github.com/github/codeql-cli-binaries) and is [licensed separately](https://github.com/github/codeql-cli-binaries/blob/main/LICENSE.md). If you'd like to use the CodeQL CLI to analyze closed-source code, you will need a separate commercial license; please [contact us](https://github.com/enterprise/contact) for further help.
|
||||
The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com). The use of CodeQL on open source code is licensed under specific [Terms & Conditions](https://securitylab.github.com/tools/codeql/license/) UNLESS you have a commercial license in place. If you'd like to use CodeQL with a commercial codebase, please [contact us](https://github.com/enterprise/contact) for further help.
|
||||
|
||||
## Visual Studio Code integration
|
||||
|
||||
|
||||
@@ -1,12 +1,2 @@
|
||||
# Please notice that any bazel targets and definitions in this repository are currently experimental
|
||||
# and for internal use only.
|
||||
|
||||
workspace(name = "codeql")
|
||||
|
||||
load("//misc/bazel:workspace.bzl", "codeql_workspace")
|
||||
|
||||
codeql_workspace()
|
||||
|
||||
load("//misc/bazel:workspace_deps.bzl", "codeql_workspace_deps")
|
||||
|
||||
codeql_workspace_deps()
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
@@ -384,8 +383,7 @@
|
||||
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
],
|
||||
"C++ ExternalAPIs": [
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||
@@ -551,4 +549,4 @@
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,3 @@
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
|
||||
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
|
||||
4
cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md
Normal file
4
cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.
|
||||
@@ -1,20 +0,0 @@
|
||||
## 0.0.12
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
|
||||
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.0.13
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.1.0-dev
|
||||
version: 0.0.12-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -84,7 +84,6 @@ private int fileHeaderLimit(File f) {
|
||||
fc = fileFirstComment(f) and
|
||||
result =
|
||||
min(int line |
|
||||
// code ending the initial comments
|
||||
exists(DeclarationEntry de, Location l |
|
||||
l = de.getLocation() and
|
||||
l.getFile() = f and
|
||||
@@ -106,13 +105,7 @@ private int fileHeaderLimit(File f) {
|
||||
line > fc
|
||||
)
|
||||
or
|
||||
// end of the file
|
||||
line = f.getMetrics().getNumberOfLines()
|
||||
or
|
||||
// rarely, we've seen extremely long sequences of initial comments
|
||||
// (and/or limitations in the above constraints) cause an overflow of
|
||||
// the maximum string length. So don't look past 1000 lines regardless.
|
||||
line = 1000
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,10 @@ class Element extends ElementBase {
|
||||
then
|
||||
exists(MacroInvocation mi |
|
||||
this = mi.getAGeneratedElement() and
|
||||
not hasCloserMacroInvocation(this, mi) and
|
||||
not exists(MacroInvocation closer |
|
||||
this = closer.getAGeneratedElement() and
|
||||
mi = closer.getParentInvocation+()
|
||||
) and
|
||||
result = mi.getMacro()
|
||||
)
|
||||
else result = this
|
||||
@@ -233,14 +236,6 @@ class Element extends ElementBase {
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasCloserMacroInvocation(Element elem, MacroInvocation mi) {
|
||||
exists(MacroInvocation closer |
|
||||
elem = closer.getAGeneratedElement() and
|
||||
mi = closer.getParentInvocation()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isFromTemplateInstantiationRec(Element e, Element instantiation) {
|
||||
instantiation.(Function).isConstructedFrom(_) and
|
||||
e = instantiation
|
||||
|
||||
@@ -27,11 +27,11 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
|
||||
why = bufferVar and
|
||||
not memberMayBeVarSize(_, bufferVar) and
|
||||
// zero sized arrays are likely to have special usage, for example
|
||||
// behaving a bit like a 'union' overlapping other fields.
|
||||
not result = 0
|
||||
not result = 0 // zero sized arrays are likely to have special usage, for example
|
||||
or
|
||||
// buffer is an initialized array, e.g., int buffer[] = {1, 2, 3};
|
||||
// behaving a bit like a 'union' overlapping other fields.
|
||||
// buffer is an initialized array
|
||||
// e.g. int buffer[] = {1, 2, 3};
|
||||
why = bufferVar.getInitializer().getExpr() and
|
||||
(
|
||||
why instanceof AggregateLiteral or
|
||||
|
||||
@@ -80,11 +80,7 @@ abstract class StackVariableReachability extends string {
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k, ControlFlowNode node |
|
||||
node = bb.getNode(k) and this.isBarrier(pragma[only_bind_into](node), v)
|
||||
|
|
||||
k in [i + 1 .. j - 1]
|
||||
)
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ predicate guardedAbs(Operation e, Expr use) {
|
||||
* Holds if the value of `use` is guarded to be less than something, and `e`
|
||||
* is in code controlled by that guard (where the guard condition held).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedLesser(Operation e, Expr use) {
|
||||
exists(GuardCondition c | c.ensuresLt(use, _, _, e.getBasicBlock(), true))
|
||||
or
|
||||
@@ -36,7 +35,6 @@ predicate guardedLesser(Operation e, Expr use) {
|
||||
* Holds if the value of `use` is guarded to be greater than something, and `e`
|
||||
* is in code controlled by that guard (where the guard condition held).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedGreater(Operation e, Expr use) {
|
||||
exists(GuardCondition c | c.ensuresLt(use, _, _, e.getBasicBlock(), false))
|
||||
or
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `cpp/overflow-destination`, `cpp/unclear-array-index-validation`, and `cpp/uncontrolled-allocation-size` queries have been modernized and converted to `path-problem` queries and provide more true positive results.
|
||||
* The `cpp/system-data-exposure` query has been increased from `medium` to `high` precision, following a number of improvements to the query logic.
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -116,8 +116,8 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
|
||||
state instanceof ConcatState
|
||||
}
|
||||
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
override predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
isSink(node, state) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/system-data-exposure` query has been increased from `medium` to `high` precision, following a number of improvements to the query logic.
|
||||
@@ -1,6 +1,4 @@
|
||||
## 0.0.12
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/overflow-destination`, `cpp/unclear-array-index-validation`, and `cpp/uncontrolled-allocation-size` queries have been modernized and converted to `path-problem` queries and provide more true positive results.
|
||||
* The `cpp/system-data-exposure` query has been increased from `medium` to `high` precision, following a number of improvements to the query logic.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.0.13
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -21,7 +21,7 @@ class WriteAccessCheckMacro extends Macro {
|
||||
VariableAccess va;
|
||||
|
||||
WriteAccessCheckMacro() {
|
||||
this.getName() = ["user_write_access_begin", "user_access_begin", "access_ok"] and
|
||||
this.getName() = ["user_write_access_begin", "user_access_begin"] and
|
||||
va.getEnclosingElement() = this.getAnInvocation().getAnExpandedElement()
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ class UnSafePutUserMacro extends Macro {
|
||||
}
|
||||
|
||||
Expr getUserModePtr() {
|
||||
result = writeUserPtr.getOperand().(AddressOfExpr).getOperand().(FieldAccess).getQualifier() or
|
||||
result = writeUserPtr.getOperand()
|
||||
result = writeUserPtr.getOperand().(AddressOfExpr).getOperand().(FieldAccess).getQualifier()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +46,11 @@ class ExploitableUserModePtrParam extends Parameter {
|
||||
not exists(WriteAccessCheckMacro writeAccessCheck |
|
||||
DataFlow::localFlow(DataFlow::parameterNode(this),
|
||||
DataFlow::exprNode(writeAccessCheck.getArgument()))
|
||||
) and
|
||||
exists(UnSafePutUserMacro unsafePutUser |
|
||||
DataFlow::localFlow(DataFlow::parameterNode(this),
|
||||
DataFlow::exprNode(unsafePutUser.getUserModePtr()))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from ExploitableUserModePtrParam p
|
||||
from ExploitableUserModePtrParam p, UnSafePutUserMacro unsafePutUser
|
||||
where
|
||||
DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(unsafePutUser.getUserModePtr()))
|
||||
select p, "unsafe_put_user write user-mode pointer $@ without check.", p, p.toString()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.1.0-dev
|
||||
version: 0.0.12-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| templates.cpp:9:14:9:14 | using c | UsingDeclarationEntry, enclosingElement:std |
|
||||
| usings.cpp:8:10:8:11 | using nf | UsingDeclarationEntry, enclosingElement:(global namespace) |
|
||||
| templates.cpp:9:5:9:14 | using c | UsingDeclarationEntry, enclosingElement:std |
|
||||
| usings.cpp:8:1:8:11 | using nf | UsingDeclarationEntry, enclosingElement:(global namespace) |
|
||||
| usings.cpp:9:1:9:17 | using namespace N | UsingDirectiveEntry, enclosingElement:(global namespace) |
|
||||
| usings.cpp:18:12:18:13 | using bf | UsingDeclarationEntry, enclosingElement:D |
|
||||
| usings.cpp:21:13:21:14 | using gf | UsingDeclarationEntry, enclosingElement:{ ... } |
|
||||
| usings.cpp:34:18:34:20 | using tbf | UsingDeclarationEntry, enclosingElement:TD |
|
||||
| usings.cpp:42:20:42:22 | using foo | UsingDeclarationEntry, enclosingElement:nsbar |
|
||||
| usings.cpp:18:3:18:13 | using bf | UsingDeclarationEntry, enclosingElement:D |
|
||||
| usings.cpp:21:5:21:14 | using gf | UsingDeclarationEntry, enclosingElement:{ ... } |
|
||||
| usings.cpp:34:3:34:20 | using tbf | UsingDeclarationEntry, enclosingElement:TD |
|
||||
| usings.cpp:42:5:42:22 | using foo | UsingDeclarationEntry, enclosingElement:nsbar |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
name: codeql/csharp-downgrades
|
||||
groups: csharp
|
||||
version: 0.0.6-dev
|
||||
downgrades: .
|
||||
library: true
|
||||
library: true
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.0.7
|
||||
|
||||
## 1.0.6
|
||||
|
||||
## 1.0.5
|
||||
|
||||
## 1.0.4
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## 1.0.6
|
||||
@@ -1 +0,0 @@
|
||||
## 1.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.7
|
||||
lastReleaseVersion: 1.0.5
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.1.0-dev
|
||||
version: 1.0.6-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/csharp-all: "*"
|
||||
codeql/csharp-all: ~0.0.3
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.0.7
|
||||
|
||||
## 1.0.6
|
||||
|
||||
## 1.0.5
|
||||
|
||||
## 1.0.4
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## 1.0.6
|
||||
@@ -1 +0,0 @@
|
||||
## 1.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.7
|
||||
lastReleaseVersion: 1.0.5
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.1.0-dev
|
||||
version: 1.0.6-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
defaultSuiteFile: codeql-suites/solorigate.qls
|
||||
dependencies:
|
||||
codeql/csharp-all: "*"
|
||||
codeql/csharp-solorigate-all: "*"
|
||||
codeql/csharp-all: ~0.0.3
|
||||
codeql/csharp-solorigate-all: ^1.0
|
||||
|
||||
@@ -1,24 +1,3 @@
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.
|
||||
@@ -1,18 +0,0 @@
|
||||
## 0.0.12
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.0.13
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.1.0-dev
|
||||
version: 0.0.12-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -42,7 +42,9 @@ module AccessPath {
|
||||
* Parses a lower-bounded interval `n..` and gets the lower bound.
|
||||
*/
|
||||
bindingset[arg]
|
||||
int parseLowerBound(string arg) { result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt() }
|
||||
private int parseLowerBound(string arg) {
|
||||
result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an integer constant or interval (bounded or unbounded) that explicitly
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -87,9 +87,21 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow into `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierIn(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited when the flow state is
|
||||
* `state`
|
||||
*/
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
@@ -309,7 +321,7 @@ private class RetNodeEx extends NodeEx {
|
||||
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
|
||||
}
|
||||
|
||||
private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
private predicate fullInBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n)
|
||||
@@ -318,7 +330,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierIn(n, state)
|
||||
|
|
||||
config.isSource(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fullOutBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n)
|
||||
@@ -327,6 +348,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
|
||||
exists(Node n |
|
||||
node.asNode() = n and
|
||||
config.isBarrierOut(n, state)
|
||||
|
|
||||
config.isSink(n, state)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -352,6 +382,12 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
config.isBarrierIn(n, state) and
|
||||
not config.isSource(n, state)
|
||||
or
|
||||
config.isBarrierOut(n, state) and
|
||||
not config.isSink(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
@@ -384,8 +420,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullOutBarrier(node1, config) and
|
||||
not fullInBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
@@ -438,6 +474,8 @@ private predicate additionalLocalStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config)
|
||||
)
|
||||
@@ -479,6 +517,8 @@ private predicate additionalJumpStateStep(
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateOutBarrier(node1, s1, config) and
|
||||
not stateInBarrier(node2, s2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
not stateBarrier(node2, s2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -878,8 +918,8 @@ private module Stage1 {
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
revFlow(node, true, config) and
|
||||
fwdFlow(node, true, config) and
|
||||
not inBarrier(node, config) and
|
||||
not outBarrier(node, config)
|
||||
not fullInBarrier(node, config) and
|
||||
not fullOutBarrier(node, config)
|
||||
}
|
||||
|
||||
/** Holds if flow may return from `callable`. */
|
||||
@@ -974,8 +1014,8 @@ private predicate flowOutOfCallNodeCand1(
|
||||
) {
|
||||
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
|
||||
Stage1::revFlow(ret, config) and
|
||||
not outBarrier(ret, config) and
|
||||
not inBarrier(out, config)
|
||||
not fullOutBarrier(ret, config) and
|
||||
not fullInBarrier(out, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -996,8 +1036,8 @@ private predicate flowIntoCallNodeCand1(
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
not outBarrier(arg, config) and
|
||||
not inBarrier(p, config)
|
||||
not fullOutBarrier(arg, config) and
|
||||
not fullInBarrier(p, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,8 +1158,8 @@ private module Stage2 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
bindingset[node1, state1, config]
|
||||
bindingset[node2, state2, config]
|
||||
@@ -1206,7 +1246,7 @@ private module Stage2 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -1911,8 +1951,8 @@ private module Stage3 {
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
|
||||
private predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
@@ -1995,7 +2035,7 @@ private module Stage3 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -2725,11 +2765,12 @@ private module Stage4 {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc) {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
|
||||
result =
|
||||
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
|
||||
node.getEnclosingCallable())
|
||||
node.getEnclosingCallable()) and
|
||||
exists(config)
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2822,7 +2863,7 @@ private module Stage4 {
|
||||
or
|
||||
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
|
||||
fwdFlow(mid, state0, cc, argAp, ap0, config) and
|
||||
localCc = getLocalCc(mid, cc)
|
||||
localCc = getLocalCc(mid, cc, config)
|
||||
|
|
||||
localStep(mid, state0, node, state, true, _, config, localCc) and
|
||||
ap = ap0
|
||||
@@ -5007,7 +5048,6 @@ private module FlowExploration {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathStep(
|
||||
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
|
||||
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation into `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerIn(node, state)
|
||||
}
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
@@ -116,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* Holds if taint propagation out of `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizerOut(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## 0.0.12
|
||||
@@ -1 +0,0 @@
|
||||
## 0.0.13
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.1.0-dev
|
||||
version: 0.0.12-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* @name Capture sink models.
|
||||
* @description Finds public methods that act as sinks as they flow into a a known sink.
|
||||
* @kind diagnostic
|
||||
* @id cs/utils/model-generator/sink-models
|
||||
* @tags model-generator
|
||||
*/
|
||||
|
||||
private import internal.CaptureModels
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* @name Capture source models.
|
||||
* @description Finds APIs that act as sources as they expose already known sources.
|
||||
* @kind diagnostic
|
||||
* @id cs/utils/model-generator/source-models
|
||||
* @tags model-generator
|
||||
*/
|
||||
|
||||
private import internal.CaptureModels
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* @name Capture summary models.
|
||||
* @description Finds applicable summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cs/utils/model-generator/summary-models
|
||||
* @tags model-generator
|
||||
*/
|
||||
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
@@ -7,7 +7,6 @@ private import semmle.code.csharp.commons.Util as Util
|
||||
private import semmle.code.csharp.commons.Collections as Collections
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
private import semmle.code.csharp.frameworks.System as System
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
@@ -19,11 +18,21 @@ module TaintTracking = CS::TaintTracking;
|
||||
class Type = CS::Type;
|
||||
|
||||
/**
|
||||
* Holds if any of the parameters of `api` are `System.Func<>`.
|
||||
* Holds if `api` is an override or an interface implementation that
|
||||
* is irrelevant to the data flow analysis.
|
||||
*/
|
||||
private predicate isHigherOrder(CS::Callable api) {
|
||||
exists(Type t | t = api.getAParameter().getType().getUnboundDeclaration() |
|
||||
t instanceof SystemLinqExpressions::DelegateExtType
|
||||
private predicate isIrrelevantOverrideOrImplementation(CS::Callable api) {
|
||||
exists(CS::Callable exclude, CS::Method m |
|
||||
(
|
||||
api = m.getAnOverrider*().getUnboundDeclaration()
|
||||
or
|
||||
api = m.getAnUltimateImplementor().getUnboundDeclaration()
|
||||
) and
|
||||
exclude = m.getUnboundDeclaration()
|
||||
|
|
||||
exists(System::SystemObjectClass c | exclude = [c.getGetHashCodeMethod(), c.getEqualsMethod()])
|
||||
or
|
||||
exists(System::SystemIEquatableTInterface i | exclude = i.getEqualsMethod())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,7 +44,7 @@ private predicate isRelevantForModels(CS::Callable api) {
|
||||
api.getDeclaringType().getNamespace().getQualifiedName() != "" and
|
||||
not api instanceof CS::ConversionOperator and
|
||||
not api instanceof Util::MainMethod and
|
||||
not isHigherOrder(api)
|
||||
not isIrrelevantOverrideOrImplementation(api)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,13 +65,8 @@ predicate asPartialModel = DataFlowPrivate::Csv::asPartialModel/1;
|
||||
/**
|
||||
* Holds for type `t` for fields that are relevant as an intermediate
|
||||
* read or write step in the data flow analysis.
|
||||
* That is, flow through any data-flow node that does not have a relevant type
|
||||
* will be excluded.
|
||||
*/
|
||||
predicate isRelevantType(CS::Type t) {
|
||||
not t instanceof CS::SimpleType and
|
||||
not t instanceof CS::Enum
|
||||
}
|
||||
predicate isRelevantType(CS::Type t) { not t instanceof CS::Enum }
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the qualifier.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| NoSummaries;PublicClassFlow;false;PublicReturn;(System.Object);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;generated:taint |
|
||||
| NoSummaries;PublicClassFlow;false;PublicReturn;(System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;BaseClassFlow;true;ReturnParam;(System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;BasicFlow;false;ReturnField;();;Argument[Qualifier];ReturnValue;generated:taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam0;(System.String,System.Object);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam1;(System.String,System.Object);;Argument[1];ReturnValue;generated:taint |
|
||||
@@ -11,14 +11,14 @@
|
||||
| Summaries;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);;Argument[Qualifier];Argument[0].Element;generated:taint |
|
||||
| Summaries;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);;Argument[1];Argument[0].Element;generated:taint |
|
||||
| Summaries;CollectionFlow;false;AssignFieldToArray;(System.Object[]);;Argument[Qualifier];Argument[0].Element;generated:taint |
|
||||
| Summaries;CollectionFlow;false;AssignToArray;(System.Object,System.Object[]);;Argument[0];Argument[1].Element;generated:taint |
|
||||
| Summaries;CollectionFlow;false;ReturnArrayElement;(System.Object[]);;Argument[0].Element;ReturnValue;generated:taint |
|
||||
| Summaries;CollectionFlow;false;AssignToArray;(System.Int32,System.Int32[]);;Argument[0];Argument[1].Element;generated:taint |
|
||||
| Summaries;CollectionFlow;false;ReturnArrayElement;(System.Int32[]);;Argument[0].Element;ReturnValue;generated:taint |
|
||||
| Summaries;CollectionFlow;false;ReturnFieldInAList;();;Argument[Qualifier];ReturnValue;generated:taint |
|
||||
| Summaries;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);;Argument[0].Element;ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.String,System.String);;Argument[1];ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.String,System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Object);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;EqualsGetHashCodeNoFlow;false;Equals;(System.String);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.Int32,System.Int32);;Argument[1];ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.Int32,System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;EqualsGetHashCodeNoFlow;false;Equals;(System.Int32);;Argument[0];ReturnValue;generated:taint |
|
||||
| Summaries;GenericFlow<>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);;Argument[Qualifier];Argument[0].Element;generated:taint |
|
||||
| Summaries;GenericFlow<>;false;AddToGenericList<>;(System.Collections.Generic.List<S>,S);;Argument[1];Argument[0].Element;generated:taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnFieldInGenericList;();;Argument[Qualifier];ReturnValue;generated:taint |
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace NoSummaries;
|
||||
// Just to prove that, if a method like this is correctly exposed, a flow summary will be captured.
|
||||
public class PublicClassFlow
|
||||
{
|
||||
public object PublicReturn(object input)
|
||||
public int PublicReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
@@ -14,19 +14,19 @@ public class PublicClassFlow
|
||||
|
||||
public sealed class PublicClassNoFlow
|
||||
{
|
||||
private object PrivateReturn(object input)
|
||||
private int PrivateReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
internal object InternalReturn(object input)
|
||||
internal int InternalReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
private class PrivateClassNoFlow
|
||||
{
|
||||
public object ReturnParam(object input)
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public sealed class PublicClassNoFlow
|
||||
{
|
||||
public class NestedPublicClassFlow
|
||||
{
|
||||
public object ReturnParam(object input)
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
@@ -44,10 +44,10 @@ public sealed class PublicClassNoFlow
|
||||
}
|
||||
}
|
||||
|
||||
public class EquatableBound : IEquatable<object>
|
||||
public class EquatableBound : IEquatable<int>
|
||||
{
|
||||
public readonly bool tainted;
|
||||
public bool Equals(object other)
|
||||
public bool Equals(int other)
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
@@ -60,42 +60,4 @@ public class EquatableUnBound<T> : IEquatable<T>
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
}
|
||||
|
||||
// No methods in this class will have generated flow summaries as
|
||||
// simple types are used.
|
||||
public class SimpleTypes
|
||||
{
|
||||
public bool M1(bool b)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
public Boolean M2(Boolean b)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
public int M3(int i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
public Int32 M4(Int32 i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
public class HigherOrderParameters
|
||||
{
|
||||
public string M1(string s, Func<string, string> map)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
public object M2(Func<object, object> map, object o)
|
||||
{
|
||||
return map(o);
|
||||
}
|
||||
}
|
||||
@@ -48,12 +48,12 @@ public class CollectionFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
public object ReturnArrayElement(object[] input)
|
||||
public int ReturnArrayElement(int[] input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
public void AssignToArray(object data, object[] target)
|
||||
public void AssignToArray(int data, int[] target)
|
||||
{
|
||||
target[0] = data;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ public class GenericFlow<T>
|
||||
|
||||
public abstract class BaseClassFlow
|
||||
{
|
||||
public virtual object ReturnParam(object input)
|
||||
public virtual int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ public abstract class BaseClassFlow
|
||||
|
||||
public class DerivedClass1Flow : BaseClassFlow
|
||||
{
|
||||
public string ReturnParam1(string input0, string input1)
|
||||
public int ReturnParam1(int input0, int input1)
|
||||
{
|
||||
return input1;
|
||||
}
|
||||
@@ -162,12 +162,12 @@ public class DerivedClass1Flow : BaseClassFlow
|
||||
|
||||
public class DerivedClass2Flow : BaseClassFlow
|
||||
{
|
||||
public override object ReturnParam(object input)
|
||||
public override int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public string ReturnParam0(string input0, int input1)
|
||||
public int ReturnParam0(int input0, int input1)
|
||||
{
|
||||
return input0;
|
||||
}
|
||||
@@ -195,13 +195,13 @@ public class OperatorFlow
|
||||
}
|
||||
|
||||
// No flow summary as this is an implicit conversion operator.
|
||||
public static implicit operator OperatorFlow(string s)
|
||||
public static implicit operator OperatorFlow(int i)
|
||||
{
|
||||
return new OperatorFlow(s);
|
||||
return new OperatorFlow(i);
|
||||
}
|
||||
|
||||
// No flow summary as this is an explicit conversion operator.
|
||||
public static explicit operator OperatorFlow(string[] b)
|
||||
public static explicit operator OperatorFlow(byte b)
|
||||
{
|
||||
return new OperatorFlow(b);
|
||||
}
|
||||
@@ -220,9 +220,9 @@ public class EqualsGetHashCodeNoFlow
|
||||
}
|
||||
|
||||
// Flow summary as this is not an override of the object Equals method.
|
||||
public string Equals(string s)
|
||||
public int Equals(int i)
|
||||
{
|
||||
return s;
|
||||
return i;
|
||||
}
|
||||
|
||||
// No flow summary as this is an override of the GetHashCode method.
|
||||
|
||||
5
defs.bzl
5
defs.bzl
@@ -1,5 +0,0 @@
|
||||
codeql_platform = select({
|
||||
"@platforms//os:linux": "linux64",
|
||||
"@platforms//os:macos": "osx64",
|
||||
"@platforms//os:windows": "win64",
|
||||
})
|
||||
@@ -100,12 +100,12 @@ As a consequence, ``A != B`` has a very different meaning to the :ref:`negation
|
||||
- ``1 = [1 .. 2]`` holds, because ``1 = 1``.
|
||||
- ``not 1 = [1 .. 2]`` doesn't hold, because there is a common value (``1``).
|
||||
|
||||
#. Compare ``1`` and ``int empty() { none() }`` (a predicate defining the empty set of integers):
|
||||
- ``1 != empty()`` doesn't hold, because there are no values in ``empty()``, so no values
|
||||
#. Compare ``1`` and ``none()`` (the "empty set"):
|
||||
- ``1 != none()`` doesn't hold, because there are no values in ``none()``, so no values
|
||||
that are not equal to ``1``.
|
||||
- ``1 = empty()`` also doesn't hold, because there are no values in ``empty()``, so no values
|
||||
- ``1 = none()`` also doesn't hold, because there are no values in ``none()``, so no values
|
||||
that are equal to ``1``.
|
||||
- ``not 1 = empty()`` holds, because there are no common values.
|
||||
- ``not 1 = none()`` holds, because there are no common values.
|
||||
|
||||
.. index:: instanceof
|
||||
.. _type-checks:
|
||||
@@ -295,48 +295,9 @@ necessary, since they highlight the default precedence. You usually only add par
|
||||
override the default precedence, but you can also add them to make your code easier to read
|
||||
(even if they aren't required).
|
||||
|
||||
QL also has two nullary connectives indicating the always true formula,
|
||||
``any()``, and the always false formula, ``none()``.
|
||||
|
||||
The logical connectives in QL work similarly to Boolean connectives in other programming
|
||||
languages. Here is a brief overview:
|
||||
|
||||
.. index:: any, true
|
||||
.. _true:
|
||||
|
||||
``any()``
|
||||
=========
|
||||
|
||||
The built-in predicate ``any()`` is a formula that always holds.
|
||||
|
||||
**Example**
|
||||
|
||||
The following predicate defines the set of all expressions.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
Expr allExpressions() {
|
||||
any()
|
||||
}
|
||||
|
||||
.. index:: none, false
|
||||
.. _false:
|
||||
|
||||
``none()``
|
||||
==========
|
||||
|
||||
The built-in predicate ``none()`` is a formula that never holds.
|
||||
|
||||
**Example**
|
||||
|
||||
The following predicate defines the empty set of integers.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
int emptySet() {
|
||||
none()
|
||||
}
|
||||
|
||||
.. index:: not, negation
|
||||
.. _negation:
|
||||
|
||||
|
||||
@@ -387,26 +387,26 @@ from ``OneTwoThree`` and ``int``.
|
||||
Non-extending subtypes
|
||||
======================
|
||||
|
||||
Besides extending base types, classes can also declare ``instanceof`` relationships with other types.
|
||||
Declaring a class as ``instanceof Foo`` is roughly equivalent to saying ``this instanceof Foo`` in the characteristic predicate.
|
||||
The main differences are that you can call methods on ``Bar`` via ``super`` and you can get better optimisation.
|
||||
Besides extending base types, classes can also declare `instanceof` relationships with other types.
|
||||
Declaring a class as `instanceof Foo` is roughly equivalent to saying `this instanceof Foo` in the characteristic predicate.
|
||||
The main differences are that you can call methods on Bar via `super` and you can get better optimisation.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
class Foo extends int {
|
||||
Foo() { this in [1 .. 10] }
|
||||
|
||||
string fooMethod() { result = "foo" }
|
||||
string foo_method() { result = "foo" }
|
||||
}
|
||||
|
||||
class Bar instanceof Foo {
|
||||
string toString() { result = super.fooMethod() }
|
||||
string toString() { result = super.foo_method() }
|
||||
}
|
||||
|
||||
In this example, the characteristic predicate from ``Foo`` also applies to ``Bar``.
|
||||
However, ``fooMethod`` is not exposed in ``Bar``, so the query ``select any(Bar b).fooMethod()``
|
||||
In this example, the characteristic predicate from `Foo` also applies to `Bar`.
|
||||
However, `foo_method` is not exposed in `Bar`, so the query `select any(Bar b).foo_method()`
|
||||
results in a compile time error. Note from the example that it is still possible to access
|
||||
methods from instanceof supertypes from within the specialising class with the ``super`` keyword.
|
||||
methods from instanceof supertypes from within the specialising class with the `super` keyword.
|
||||
|
||||
Crucially, the instanceof **supertypes** are not **base types**.
|
||||
This means that these supertypes do not participate in overriding, and any fields of such
|
||||
@@ -430,10 +430,10 @@ The following example demonstrates this.
|
||||
override string foo() { result = "bar" }
|
||||
}
|
||||
|
||||
Here, the method ``Bar::foo`` does not override ``Foo::foo``.
|
||||
Instead, it overrides only ``Interface::foo``.
|
||||
This means that ``select any(Foo f).foo()`` yields ``foo``.
|
||||
Had ``Bar`` been defined as ``extends Foo``, then ``select any(Foo f).foo()`` would yield ``bar``.
|
||||
Here, the method `Bar::foo` does not override `Foo::foo`.
|
||||
Instead, it overrides only `Interface::foo`.
|
||||
This means that `select any(Foo f).foo()` yields only `foo`.
|
||||
Had `Bar` been defined as `extends Foo`, then `select any(Foo b)` would yield `bar`.
|
||||
|
||||
.. _character-types:
|
||||
.. _domain-types:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user