mirror of
https://github.com/github/codeql.git
synced 2025-12-24 20:56:33 +01:00
merge in main
This commit is contained in:
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"provide": [
|
|
||||||
"*/ql/src/qlpack.yml",
|
|
||||||
"*/ql/lib/qlpack.yml",
|
|
||||||
"*/ql/test/qlpack.yml",
|
|
||||||
"*/ql/examples/qlpack.yml",
|
|
||||||
"*/ql/consistency-queries/qlpack.yml",
|
|
||||||
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
|
|
||||||
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
|
|
||||||
"javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml",
|
|
||||||
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
|
|
||||||
"csharp/ql/campaigns/Solorigate/lib/qlpack.yml",
|
|
||||||
"csharp/ql/campaigns/Solorigate/src/qlpack.yml",
|
|
||||||
"csharp/ql/campaigns/Solorigate/test/qlpack.yml",
|
|
||||||
"misc/legacy-support/*/qlpack.yml",
|
|
||||||
"misc/suite-helpers/qlpack.yml",
|
|
||||||
"ruby/extractor-pack/codeql-extractor.yml",
|
|
||||||
"ql/extractor-pack/codeql-extractor.yml"
|
|
||||||
],
|
|
||||||
"versionPolicies": {
|
|
||||||
"default": {
|
|
||||||
"requireChangeNotes": true,
|
|
||||||
"committedPrereleaseSuffix": "dev",
|
|
||||||
"committedVersion": "nextPatchRelease"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
.devcontainer/swift/Dockerfile
Normal file
9
.devcontainer/swift/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/cpp/.devcontainer/base.Dockerfile
|
||||||
|
|
||||||
|
# [Choice] Debian / Ubuntu version (use Debian 11, Ubuntu 18.04/22.04 on local arm64/Apple Silicon): debian-11, debian-10, ubuntu-22.04, ubuntu-20.04, ubuntu-18.04
|
||||||
|
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-ubuntu-22.04
|
||||||
|
|
||||||
|
USER root
|
||||||
|
ADD root.sh /tmp/root.sh
|
||||||
|
ADD update-codeql.sh /usr/local/bin/update-codeql
|
||||||
|
RUN bash /tmp/root.sh && rm /tmp/root.sh
|
||||||
25
.devcontainer/swift/devcontainer.json
Normal file
25
.devcontainer/swift/devcontainer.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extensions": [
|
||||||
|
"github.vscode-codeql",
|
||||||
|
"hbenl.vscode-test-explorer",
|
||||||
|
"ms-vscode.test-adapter-converter",
|
||||||
|
"slevesque.vscode-zipexplorer",
|
||||||
|
"ms-vscode.cpptools"
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/target/**": true
|
||||||
|
},
|
||||||
|
"codeQL.runningQueries.memory": 2048
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile",
|
||||||
|
},
|
||||||
|
"runArgs": [
|
||||||
|
"--cap-add=SYS_PTRACE",
|
||||||
|
"--security-opt",
|
||||||
|
"seccomp=unconfined"
|
||||||
|
],
|
||||||
|
"remoteUser": "vscode",
|
||||||
|
"onCreateCommand": ".devcontainer/swift/user.sh"
|
||||||
|
}
|
||||||
22
.devcontainer/swift/root.sh
Normal file
22
.devcontainer/swift/root.sh
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
set -xe
|
||||||
|
|
||||||
|
BAZELISK_VERSION=v1.12.0
|
||||||
|
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get -y install --no-install-recommends \
|
||||||
|
zlib1g-dev \
|
||||||
|
uuid-dev \
|
||||||
|
python3-distutils \
|
||||||
|
python3-pip \
|
||||||
|
bash-completion
|
||||||
|
|
||||||
|
# Install Bazel
|
||||||
|
curl -fSsL -o /usr/local/bin/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-linux-amd64
|
||||||
|
echo "${BAZELISK_DOWNLOAD_SHA} */usr/local/bin/bazelisk" | sha256sum --check -
|
||||||
|
chmod 0755 /usr/local/bin/bazelisk
|
||||||
|
ln -s bazelisk /usr/local/bin/bazel
|
||||||
|
|
||||||
|
# install latest codeql
|
||||||
|
update-codeql
|
||||||
20
.devcontainer/swift/update-codeql.sh
Executable file
20
.devcontainer/swift/update-codeql.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
URL=https://github.com/github/codeql-cli-binaries/releases
|
||||||
|
LATEST_VERSION=$(curl -L -s -H 'Accept: application/json' $URL/latest | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')
|
||||||
|
CURRENT_VERSION=v$(codeql version 2>/dev/null | sed -ne 's/.*release \([0-9.]*\)\./\1/p')
|
||||||
|
if [[ $CURRENT_VERSION != $LATEST_VERSION ]]; then
|
||||||
|
if [[ $UID != 0 ]]; then
|
||||||
|
echo "update required, please run this script with sudo:"
|
||||||
|
echo " sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ZIP=$(mktemp codeql.XXXX.zip)
|
||||||
|
curl -fSqL -o $ZIP $URL/download/$LATEST_VERSION/codeql-linux64.zip
|
||||||
|
unzip -q $ZIP -d /opt
|
||||||
|
rm $ZIP
|
||||||
|
ln -sf /opt/codeql/codeql /usr/local/bin/codeql
|
||||||
|
echo installed version $LATEST_VERSION
|
||||||
|
else
|
||||||
|
echo current version $CURRENT_VERSION is up-to-date
|
||||||
|
fi
|
||||||
13
.devcontainer/swift/user.sh
Executable file
13
.devcontainer/swift/user.sh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
set -xe
|
||||||
|
|
||||||
|
# add the workspace to the codeql search path
|
||||||
|
mkdir -p /home/vscode/.config/codeql
|
||||||
|
echo "--search-path /workspaces/codeql" > /home/vscode/.config/codeql/config
|
||||||
|
|
||||||
|
# create a swift extractor pack with the current state
|
||||||
|
cd /workspaces/codeql
|
||||||
|
bazel run swift/create-extractor-pack
|
||||||
|
|
||||||
|
#install and set up pre-commit
|
||||||
|
python3 -m pip install pre-commit --no-warn-script-location
|
||||||
|
$HOME/.local/bin/pre-commit install
|
||||||
9
.gitattributes
vendored
9
.gitattributes
vendored
@@ -39,6 +39,7 @@
|
|||||||
*.py text
|
*.py text
|
||||||
*.lua text
|
*.lua text
|
||||||
*.expected text
|
*.expected text
|
||||||
|
*.go text
|
||||||
|
|
||||||
# Explicitly set a bunch of known extensions to binary, because Git < 2.10 will treat
|
# Explicitly set a bunch of known extensions to binary, because Git < 2.10 will treat
|
||||||
# `* text=auto eol=lf` as `* text eol=lf`
|
# `* text=auto eol=lf` as `* text eol=lf`
|
||||||
@@ -52,6 +53,14 @@
|
|||||||
java/ql/test/stubs/**/*.java linguist-generated=true
|
java/ql/test/stubs/**/*.java linguist-generated=true
|
||||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||||
|
|
||||||
|
# Force git not to modify line endings for go or html files under the go/ql directory
|
||||||
|
go/ql/**/*.go -text
|
||||||
|
go/ql/**/*.html -text
|
||||||
|
# Force git not to modify line endings for go dbschemes
|
||||||
|
go/*.dbscheme -text
|
||||||
|
# Preserve unusual line ending from codeql-go merge
|
||||||
|
go/extractor/opencsv/CSVReader.java -text
|
||||||
|
|
||||||
# For some languages, upgrade script testing references really old dbscheme
|
# For some languages, upgrade script testing references really old dbscheme
|
||||||
# files from legacy upgrades that have CRLF line endings. Since upgrade
|
# files from legacy upgrades that have CRLF line endings. Since upgrade
|
||||||
# resolution relies on object hashes, we must suppress line ending conversion
|
# resolution relies on object hashes, we must suppress line ending conversion
|
||||||
|
|||||||
15
.github/labeler.yml
vendored
15
.github/labeler.yml
vendored
@@ -6,14 +6,23 @@
|
|||||||
- csharp/**/*
|
- csharp/**/*
|
||||||
- change-notes/**/*csharp*
|
- change-notes/**/*csharp*
|
||||||
|
|
||||||
|
Go:
|
||||||
|
- go/**/*
|
||||||
|
- change-notes/**/*go.*
|
||||||
|
|
||||||
Java:
|
Java:
|
||||||
- java/**/*
|
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/kotlin-explorer/**/*', '!java/ql/test/kotlin/**/*' ]
|
||||||
- change-notes/**/*java.*
|
- change-notes/**/*java.*
|
||||||
|
|
||||||
JS:
|
JS:
|
||||||
- any: [ 'javascript/**/*', '!javascript/ql/experimental/adaptivethreatmodeling/**/*' ]
|
- any: [ 'javascript/**/*', '!javascript/ql/experimental/adaptivethreatmodeling/**/*' ]
|
||||||
- change-notes/**/*javascript*
|
- change-notes/**/*javascript*
|
||||||
|
|
||||||
|
Kotlin:
|
||||||
|
- java/kotlin-extractor/**/*
|
||||||
|
- java/kotlin-explorer/**/*
|
||||||
|
- java/ql/test/kotlin/**/*
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
- python/**/*
|
- python/**/*
|
||||||
- change-notes/**/*python*
|
- change-notes/**/*python*
|
||||||
@@ -21,7 +30,7 @@ Python:
|
|||||||
Ruby:
|
Ruby:
|
||||||
- ruby/**/*
|
- ruby/**/*
|
||||||
- change-notes/**/*ruby*
|
- change-notes/**/*ruby*
|
||||||
|
|
||||||
Swift:
|
Swift:
|
||||||
- swift/**/*
|
- swift/**/*
|
||||||
- change-notes/**/*swift*
|
- change-notes/**/*swift*
|
||||||
@@ -31,5 +40,5 @@ documentation:
|
|||||||
- "**/*.md"
|
- "**/*.md"
|
||||||
- docs/**/*
|
- docs/**/*
|
||||||
|
|
||||||
"QL-for-QL":
|
"QL-for-QL":
|
||||||
- ql/**/*
|
- ql/**/*
|
||||||
|
|||||||
14
.github/problem-matchers/codeql-query-format.json
vendored
Normal file
14
.github/problem-matchers/codeql-query-format.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "codeql-query-format",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^((.*) would change by autoformatting\\.)$",
|
||||||
|
"file": 2,
|
||||||
|
"message": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
17
.github/problem-matchers/codeql-syntax-check.json
vendored
Normal file
17
.github/problem-matchers/codeql-syntax-check.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "codeql-syntax-check",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^((ERROR|WARNING): .* \\((.*):(\\d+),(\\d+)-\\d+\\))$",
|
||||||
|
"message": 1,
|
||||||
|
"file": 3,
|
||||||
|
"line": 4,
|
||||||
|
"col": 5,
|
||||||
|
"severity": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
.github/problem-matchers/codeql-test-run.json
vendored
Normal file
14
.github/problem-matchers/codeql-test-run.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "codeql-test-run",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "(\\[.*\\] FAILED\\((RESULT|COMPILATION)\\) (.*))$",
|
||||||
|
"file": 3,
|
||||||
|
"message": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
.github/problem-matchers/make.json
vendored
Normal file
13
.github/problem-matchers/make.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "make",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^(make: \\*\\*\\* .*)$",
|
||||||
|
"message": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
git log -1 --format='%H'
|
git log -1 --format='%H'
|
||||||
working-directory: base
|
working-directory: base
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
- name: Clone self (github/codeql)
|
- name: Clone self (github/codeql)
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
path: codeqlModels
|
path: codeqlModels
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
|
|||||||
2
.github/workflows/csv-coverage-update.yml
vendored
2
.github/workflows/csv-coverage-update.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
path: ql
|
path: ql
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
|
|||||||
2
.github/workflows/csv-coverage.yml
vendored
2
.github/workflows/csv-coverage.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
path: codeqlModels
|
path: codeqlModels
|
||||||
ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }}
|
ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }}
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
|
|||||||
162
.github/workflows/go-tests.yml
vendored
Normal file
162
.github/workflows/go-tests.yml
vendored
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
name: "Go: Run Tests"
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "go/**"
|
||||||
|
- .github/workflows/go-tests.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
test-linux:
|
||||||
|
name: Test Linux (Ubuntu)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Set up Go 1.18.1
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.18.1
|
||||||
|
id: go
|
||||||
|
|
||||||
|
- name: Set up CodeQL CLI
|
||||||
|
run: |
|
||||||
|
echo "Removing old CodeQL Directory..."
|
||||||
|
rm -rf $HOME/codeql
|
||||||
|
echo "Done"
|
||||||
|
cd $HOME
|
||||||
|
echo "Downloading CodeQL CLI..."
|
||||||
|
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
|
||||||
|
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
|
||||||
|
echo "Done"
|
||||||
|
echo "Unpacking CodeQL CLI..."
|
||||||
|
unzip -q codeql-linux64.zip
|
||||||
|
rm -f codeql-linux64.zip
|
||||||
|
echo "Done"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Enable problem matchers in repository
|
||||||
|
shell: bash
|
||||||
|
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql make
|
||||||
|
|
||||||
|
- name: Check that all QL and Go code is autoformatted
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql make check-formatting
|
||||||
|
|
||||||
|
- name: Compile qhelp files to markdown
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown
|
||||||
|
|
||||||
|
- name: Upload qhelp markdown
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: qhelp-markdown
|
||||||
|
path: go/qhelp-out/**/*.md
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql make test
|
||||||
|
|
||||||
|
test-mac:
|
||||||
|
name: Test MacOS
|
||||||
|
runs-on: macOS-latest
|
||||||
|
steps:
|
||||||
|
- name: Set up Go 1.18.1
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.18.1
|
||||||
|
id: go
|
||||||
|
|
||||||
|
- name: Set up CodeQL CLI
|
||||||
|
run: |
|
||||||
|
echo "Removing old CodeQL Directory..."
|
||||||
|
rm -rf $HOME/codeql
|
||||||
|
echo "Done"
|
||||||
|
cd $HOME
|
||||||
|
echo "Downloading CodeQL CLI..."
|
||||||
|
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
|
||||||
|
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-osx64.zip "$LATEST"
|
||||||
|
echo "Done"
|
||||||
|
echo "Unpacking CodeQL CLI..."
|
||||||
|
unzip -q codeql-osx64.zip
|
||||||
|
rm -f codeql-osx64.zip
|
||||||
|
echo "Done"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Enable problem matchers in repository
|
||||||
|
shell: bash
|
||||||
|
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
cd go
|
||||||
|
env PATH=$PATH:$HOME/codeql make test
|
||||||
|
|
||||||
|
test-win:
|
||||||
|
name: Test Windows
|
||||||
|
runs-on: windows-2019
|
||||||
|
steps:
|
||||||
|
- name: Set up Go 1.18.1
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.18.1
|
||||||
|
id: go
|
||||||
|
|
||||||
|
- name: Set up CodeQL CLI
|
||||||
|
run: |
|
||||||
|
echo "Removing old CodeQL Directory..."
|
||||||
|
rm -rf $HOME/codeql
|
||||||
|
echo "Done"
|
||||||
|
cd "$HOME"
|
||||||
|
echo "Downloading CodeQL CLI..."
|
||||||
|
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
|
||||||
|
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-win64.zip "$LATEST"
|
||||||
|
echo "Done"
|
||||||
|
echo "Unpacking CodeQL CLI..."
|
||||||
|
unzip -q -o codeql-win64.zip
|
||||||
|
unzip -q -o codeql-win64.zip codeql/codeql.exe
|
||||||
|
rm -f codeql-win64.zip
|
||||||
|
echo "Done"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
shell:
|
||||||
|
bash
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Enable problem matchers in repository
|
||||||
|
shell: bash
|
||||||
|
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
$Env:Path += ";$HOME\codeql"
|
||||||
|
cd go
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
$Env:Path += ";$HOME\codeql"
|
||||||
|
cd go
|
||||||
|
make test
|
||||||
3
.github/workflows/js-ml-tests.yml
vendored
3
.github/workflows/js-ml-tests.yml
vendored
@@ -5,6 +5,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
||||||
- .github/workflows/js-ml-tests.yml
|
- .github/workflows/js-ml-tests.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- "rc/*"
|
- "rc/*"
|
||||||
@@ -12,6 +13,8 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
||||||
- .github/workflows/js-ml-tests.yml
|
- .github/workflows/js-ml-tests.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
|
|||||||
3
.github/workflows/labeler.yml
vendored
3
.github/workflows/labeler.yml
vendored
@@ -4,6 +4,9 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
triage:
|
triage:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/labeler@v4
|
- uses: actions/labeler@v4
|
||||||
|
|||||||
2
.github/workflows/mad_modelDiff.yml
vendored
2
.github/workflows/mad_modelDiff.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
|||||||
DATABASE=$2
|
DATABASE=$2
|
||||||
cd codeql-$QL_VARIANT
|
cd codeql-$QL_VARIANT
|
||||||
SHORTNAME=`basename $DATABASE`
|
SHORTNAME=`basename $DATABASE`
|
||||||
python java/ql/src/utils/model-generator/GenerateFlowModel.py $DATABASE $MODELS/${SHORTNAME}.qll
|
python java/ql/src/utils/model-generator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $MODELS/${SHORTNAME}.qll
|
||||||
mv $MODELS/${SHORTNAME}.qll $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.qll
|
mv $MODELS/${SHORTNAME}.qll $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.qll
|
||||||
cd ..
|
cd ..
|
||||||
}
|
}
|
||||||
|
|||||||
2
.github/workflows/mad_regenerate-models.yml
vendored
2
.github/workflows/mad_regenerate-models.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
ref: ["placeholder"]
|
ref: ["placeholder"]
|
||||||
include:
|
include:
|
||||||
- slug: "apache/commons-io"
|
- slug: "apache/commons-io"
|
||||||
ref: "8985de8fe74f6622a419b37a6eed0dbc484dc128"
|
ref: "13258ce2d07aa0e764bbaa8020af4dcd3a02a620"
|
||||||
exclude:
|
exclude:
|
||||||
- slug: "placeholder"
|
- slug: "placeholder"
|
||||||
ref: "placeholder"
|
ref: "placeholder"
|
||||||
|
|||||||
2
.github/workflows/ql-for-ql-build.yml
vendored
2
.github/workflows/ql-for-ql-build.yml
vendored
@@ -140,7 +140,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
folder: [cpp, csharp, java, javascript, python, ql, ruby, swift]
|
folder: [cpp, csharp, java, javascript, python, ql, ruby, swift, go]
|
||||||
|
|
||||||
needs:
|
needs:
|
||||||
- package
|
- package
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
repo:
|
repo:
|
||||||
- github/codeql
|
- github/codeql
|
||||||
- github/codeql-go
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -77,7 +76,7 @@ jobs:
|
|||||||
path: stats
|
path: stats
|
||||||
- run: |
|
- run: |
|
||||||
python -m pip install --user lxml
|
python -m pip install --user lxml
|
||||||
find stats -name 'stats.xml' -print0 | sort -z | xargs -0 python ql/scripts/merge_stats.py --output ql/ql/src/ql.dbscheme.stats --normalise ql_tokeninfo
|
find stats -name 'stats.xml' -print0 | sort -z | xargs -0 python ruby/scripts/merge_stats.py --output ql/ql/src/ql.dbscheme.stats --normalise ql_tokeninfo
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ql.dbscheme.stats
|
name: ql.dbscheme.stats
|
||||||
|
|||||||
2
.github/workflows/ql-for-ql-tests.yml
vendored
2
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -5,10 +5,12 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- "ql/**"
|
- "ql/**"
|
||||||
|
- codeql-workspace.yml
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- "ql/**"
|
- "ql/**"
|
||||||
|
- codeql-workspace.yml
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
|||||||
9
.github/workflows/query-list.yml
vendored
9
.github/workflows/query-list.yml
vendored
@@ -5,6 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- 'rc/**'
|
- 'rc/**'
|
||||||
|
tags:
|
||||||
|
- 'codeql-cli/*'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/query-list.yml'
|
- '.github/workflows/query-list.yml'
|
||||||
@@ -20,13 +22,8 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
path: codeql
|
path: codeql
|
||||||
- name: Clone github/codeql-go
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'github/codeql-go'
|
|
||||||
path: codeql-go
|
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
|
|||||||
2
.github/workflows/ruby-build.yml
vendored
2
.github/workflows/ruby-build.yml
vendored
@@ -5,6 +5,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "ruby/**"
|
- "ruby/**"
|
||||||
- .github/workflows/ruby-build.yml
|
- .github/workflows/ruby-build.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- "rc/*"
|
- "rc/*"
|
||||||
@@ -12,6 +13,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "ruby/**"
|
- "ruby/**"
|
||||||
- .github/workflows/ruby-build.yml
|
- .github/workflows/ruby-build.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- "rc/*"
|
- "rc/*"
|
||||||
|
|||||||
2
.github/workflows/ruby-qltest.yml
vendored
2
.github/workflows/ruby-qltest.yml
vendored
@@ -5,6 +5,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "ruby/**"
|
- "ruby/**"
|
||||||
- .github/workflows/ruby-qltest.yml
|
- .github/workflows/ruby-qltest.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- "rc/*"
|
- "rc/*"
|
||||||
@@ -12,6 +13,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "ruby/**"
|
- "ruby/**"
|
||||||
- .github/workflows/ruby-qltest.yml
|
- .github/workflows/ruby-qltest.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- "rc/*"
|
- "rc/*"
|
||||||
|
|||||||
5
.github/workflows/swift-codegen.yml
vendored
5
.github/workflows/swift-codegen.yml
vendored
@@ -22,11 +22,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
bazel run //swift/codegen
|
bazel run //swift/codegen
|
||||||
git add swift
|
git add swift
|
||||||
git diff --exit-code --stat HEAD
|
git diff --exit-code HEAD
|
||||||
- name: Generate C++ files
|
- name: Generate C++ files
|
||||||
run: |
|
run: |
|
||||||
bazel run //swift/codegen:trapgen -- --cpp-output=$PWD/swift-generated-headers
|
bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/swift-generated-headers
|
||||||
bazel run //swift/codegen:cppgen -- --cpp-output=$PWD/swift-generated-headers
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: swift-generated-headers
|
name: swift-generated-headers
|
||||||
|
|||||||
1
.github/workflows/swift-qltest.yml
vendored
1
.github/workflows/swift-qltest.yml
vendored
@@ -5,6 +5,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "swift/**"
|
- "swift/**"
|
||||||
- .github/workflows/swift-qltest.yml
|
- .github/workflows/swift-qltest.yml
|
||||||
|
- codeql-workspace.yml
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
defaults:
|
defaults:
|
||||||
|
|||||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -9,6 +9,7 @@
|
|||||||
# qltest projects and artifacts
|
# qltest projects and artifacts
|
||||||
*/ql/test/**/*.testproj
|
*/ql/test/**/*.testproj
|
||||||
*/ql/test/**/*.actual
|
*/ql/test/**/*.actual
|
||||||
|
*/ql/test/**/go.sum
|
||||||
|
|
||||||
# Visual studio temporaries, except a file used by QL4VS
|
# Visual studio temporaries, except a file used by QL4VS
|
||||||
.vs/*
|
.vs/*
|
||||||
@@ -42,3 +43,21 @@ csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
|||||||
|
|
||||||
# CLion project files
|
# CLion project files
|
||||||
/.clwb
|
/.clwb
|
||||||
|
|
||||||
|
# Go build artifacts
|
||||||
|
go/build/*
|
||||||
|
|
||||||
|
# Go binaries
|
||||||
|
go/tools/bin
|
||||||
|
go/tools/linux64
|
||||||
|
go/tools/osx64
|
||||||
|
go/tools/win64
|
||||||
|
go/tools/tokenizer.jar
|
||||||
|
go/main
|
||||||
|
|
||||||
|
# node_modules folders except in the JS test suite
|
||||||
|
node_modules/
|
||||||
|
!/javascript/ql/test/**/node_modules/
|
||||||
|
|
||||||
|
# Temporary folders for working with generated models
|
||||||
|
.model-temp
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ path_classifiers:
|
|||||||
test:
|
test:
|
||||||
- csharp/ql/src
|
- csharp/ql/src
|
||||||
- csharp/ql/test
|
- csharp/ql/test
|
||||||
|
- go/ql/test
|
||||||
- javascript/extractor/parser-tests
|
- javascript/extractor/parser-tests
|
||||||
- javascript/extractor/tests
|
- javascript/extractor/tests
|
||||||
- javascript/ql/src
|
- javascript/ql/src
|
||||||
@@ -13,6 +14,9 @@ path_classifiers:
|
|||||||
- python/ql/src
|
- python/ql/src
|
||||||
- python/ql/test
|
- python/ql/test
|
||||||
|
|
||||||
|
example:
|
||||||
|
- go/ql/src
|
||||||
|
|
||||||
queries:
|
queries:
|
||||||
- include: "*"
|
- include: "*"
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ repos:
|
|||||||
|
|
||||||
- id: sync-files
|
- id: sync-files
|
||||||
name: Fix files required to be identical
|
name: Fix files required to be identical
|
||||||
files: \.(qll?|qhelp)$
|
files: \.(qll?|qhelp|swift)$
|
||||||
language: system
|
language: system
|
||||||
entry: python3 config/sync-files.py --latest
|
entry: python3 config/sync-files.py --latest
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
@@ -40,7 +40,7 @@ repos:
|
|||||||
name: Run Swift checked in code generation
|
name: Run Swift checked in code generation
|
||||||
files: ^swift/(codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements))
|
files: ^swift/(codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements))
|
||||||
language: system
|
language: system
|
||||||
entry: bazel run //swift/codegen
|
entry: bazel run //swift/codegen -- --quiet
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
|
|
||||||
- id: swift-codegen-unit-tests
|
- id: swift-codegen-unit-tests
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/cpp/ @github/codeql-c-analysis
|
/cpp/ @github/codeql-c-analysis
|
||||||
/csharp/ @github/codeql-csharp
|
/csharp/ @github/codeql-csharp
|
||||||
|
/go/ @github/codeql-go
|
||||||
/java/ @github/codeql-java
|
/java/ @github/codeql-java
|
||||||
/javascript/ @github/codeql-javascript
|
/javascript/ @github/codeql-javascript
|
||||||
/python/ @github/codeql-python
|
/python/ @github/codeql-python
|
||||||
@@ -27,8 +28,8 @@
|
|||||||
# QL for QL reviewers
|
# QL for QL reviewers
|
||||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||||
|
|
||||||
# Bazel
|
# Bazel (excluding BUILD.bazel files)
|
||||||
**/*.bazel @github/codeql-ci-reviewers
|
WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||||
**/*.bzl @github/codeql-ci-reviewers
|
**/*.bzl @github/codeql-ci-reviewers
|
||||||
|
|
||||||
# Documentation etc
|
# Documentation etc
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
|
|
||||||
# Workflows
|
# Workflows
|
||||||
/.github/workflows/ @github/codeql-ci-reviewers
|
/.github/workflows/ @github/codeql-ci-reviewers
|
||||||
|
/.github/workflows/go-* @github/codeql-go
|
||||||
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
|
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
|
||||||
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
||||||
/.github/workflows/ruby-* @github/codeql-ruby
|
/.github/workflows/ruby-* @github/codeql-ruby
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# CodeQL
|
# CodeQL
|
||||||
|
|
||||||
This open source repository contains the standard CodeQL libraries and queries that power [GitHub Advanced Security](https://github.com/features/security/code) and the other application security products that [GitHub](https://github.com/features/security/) makes available to its customers worldwide. For the queries, libraries, and extractor that power Go analysis, visit the [CodeQL for Go repository](https://github.com/github/codeql-go).
|
This open source repository contains the standard CodeQL libraries and queries that power [GitHub Advanced Security](https://github.com/features/security/code) and the other application security products that [GitHub](https://github.com/features/security/) makes available to its customers worldwide.
|
||||||
|
|
||||||
## How do I learn CodeQL and run queries?
|
## How do I learn CodeQL and run queries?
|
||||||
|
|
||||||
|
|||||||
32
codeql-workspace.yml
Normal file
32
codeql-workspace.yml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
provide:
|
||||||
|
- "*/ql/src/qlpack.yml"
|
||||||
|
- "*/ql/lib/qlpack.yml"
|
||||||
|
- "*/ql/test/qlpack.yml"
|
||||||
|
- "*/ql/examples/qlpack.yml"
|
||||||
|
- "*/ql/consistency-queries/qlpack.yml"
|
||||||
|
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
||||||
|
- "go/ql/config/legacy-support/qlpack.yml"
|
||||||
|
- "go/build/codeql-extractor-go/codeql-extractor.yml"
|
||||||
|
- "javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml"
|
||||||
|
# This pack is explicitly excluded from the workspace since most users
|
||||||
|
# will want to use a version of this pack from the package cache. Internal
|
||||||
|
# users can uncomment the following line and place a custom ML model
|
||||||
|
# in the corresponding pack to test a custom ML model within their local
|
||||||
|
# checkout.
|
||||||
|
# - "javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml"
|
||||||
|
- "javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml"
|
||||||
|
- "javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml"
|
||||||
|
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
|
||||||
|
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
|
||||||
|
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"
|
||||||
|
- "misc/legacy-support/*/qlpack.yml"
|
||||||
|
- "misc/suite-helpers/qlpack.yml"
|
||||||
|
- "ruby/extractor-pack/codeql-extractor.yml"
|
||||||
|
- "swift/extractor-pack/codeql-extractor.yml"
|
||||||
|
- "ql/extractor-pack/codeql-extractor.ym"
|
||||||
|
|
||||||
|
versionPolicies:
|
||||||
|
default:
|
||||||
|
requireChangeNotes: true
|
||||||
|
committedPrereleaseSuffix: dev
|
||||||
|
committedVersion: nextPatchRelease
|
||||||
@@ -22,13 +22,15 @@
|
|||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
||||||
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForLibraries.qll"
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForLibraries.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
|
||||||
],
|
],
|
||||||
"DataFlow Java/C++/C#/Python Common": [
|
"DataFlow Java/C++/C#/Python Common": [
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
|
||||||
@@ -36,7 +38,8 @@
|
|||||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
|
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll"
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll"
|
||||||
],
|
],
|
||||||
"TaintTracking::Configuration Java/C++/C#/Python": [
|
"TaintTracking::Configuration Java/C++/C#/Python": [
|
||||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||||
@@ -57,7 +60,8 @@
|
|||||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforlibraries/TaintTrackingImpl.qll"
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforlibraries/TaintTrackingImpl.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
|
||||||
],
|
],
|
||||||
"DataFlow Java/C++/C#/Python Consistency checks": [
|
"DataFlow Java/C++/C#/Python Consistency checks": [
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
|
||||||
@@ -65,13 +69,15 @@
|
|||||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
|
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll"
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll"
|
||||||
],
|
],
|
||||||
"DataFlow Java/C# Flow Summaries": [
|
"DataFlow Java/C# Flow Summaries": [
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll"
|
"python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
|
||||||
],
|
],
|
||||||
"SsaReadPosition Java/C#": [
|
"SsaReadPosition Java/C#": [
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||||
@@ -386,7 +392,8 @@
|
|||||||
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
|
"go/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||||
],
|
],
|
||||||
"C++ ExternalAPIs": [
|
"C++ ExternalAPIs": [
|
||||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||||
@@ -459,7 +466,8 @@
|
|||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
|
||||||
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll",
|
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
|
||||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll"
|
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/SsaImplCommon.qll"
|
||||||
],
|
],
|
||||||
"CryptoAlgorithms Python/JS/Ruby": [
|
"CryptoAlgorithms Python/JS/Ruby": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||||
@@ -501,7 +509,8 @@
|
|||||||
],
|
],
|
||||||
"CFG": [
|
"CFG": [
|
||||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll"
|
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplShared.qll"
|
||||||
],
|
],
|
||||||
"TypeTracker": [
|
"TypeTracker": [
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
|
||||||
@@ -520,7 +529,8 @@
|
|||||||
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
|
||||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll"
|
"python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll",
|
||||||
|
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
|
||||||
],
|
],
|
||||||
"IncompleteUrlSubstringSanitization": [
|
"IncompleteUrlSubstringSanitization": [
|
||||||
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
|
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
|
||||||
@@ -538,7 +548,8 @@
|
|||||||
],
|
],
|
||||||
"ApiGraphModels": [
|
"ApiGraphModels": [
|
||||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
|
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
|
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll",
|
||||||
|
"python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll"
|
||||||
],
|
],
|
||||||
"TaintedFormatStringQuery Ruby/JS": [
|
"TaintedFormatStringQuery Ruby/JS": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
|
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
|
||||||
@@ -555,5 +566,25 @@
|
|||||||
"HttpToFileAccessCustomizations JS/Ruby": [
|
"HttpToFileAccessCustomizations JS/Ruby": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
|
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
|
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
|
||||||
|
],
|
||||||
|
"Typo database": [
|
||||||
|
"javascript/ql/src/Expressions/TypoDatabase.qll",
|
||||||
|
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
|
||||||
|
],
|
||||||
|
"Swift declarations test file": [
|
||||||
|
"swift/ql/test/extractor-tests/declarations/declarations.swift",
|
||||||
|
"swift/ql/test/library-tests/parent/declarations.swift"
|
||||||
|
],
|
||||||
|
"Swift statements test file": [
|
||||||
|
"swift/ql/test/extractor-tests/statements/statements.swift",
|
||||||
|
"swift/ql/test/library-tests/parent/statements.swift"
|
||||||
|
],
|
||||||
|
"Swift expressions test file": [
|
||||||
|
"swift/ql/test/extractor-tests/expressions/expressions.swift",
|
||||||
|
"swift/ql/test/library-tests/parent/expressions.swift"
|
||||||
|
],
|
||||||
|
"Swift patterns test file": [
|
||||||
|
"swift/ql/test/extractor-tests/patterns/patterns.swift",
|
||||||
|
"swift/ql/test/library-tests/parent/patterns.swift"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
2115
cpp/downgrades/19e31bf071f588bb7efd1e4d5a185ce4f6fbbd84/old.dbscheme
Normal file
2115
cpp/downgrades/19e31bf071f588bb7efd1e4d5a185ce4f6fbbd84/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: Add relation for tracking C++ braced initializers
|
||||||
|
compatibility: full
|
||||||
|
braced_initialisers.rel: delete
|
||||||
@@ -1,3 +1,21 @@
|
|||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||||
|
|
||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
### Deprecated APIs
|
||||||
|
|
||||||
|
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.
|
||||||
|
|
||||||
|
## 0.2.1
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: feature
|
|
||||||
---
|
|
||||||
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: deprecated
|
|
||||||
---
|
|
||||||
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: feature
|
||||||
|
---
|
||||||
|
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: deprecated
|
||||||
|
---
|
||||||
|
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: fix
|
||||||
|
---
|
||||||
|
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
|
||||||
1
cpp/ql/lib/change-notes/released/0.2.1.md
Normal file
1
cpp/ql/lib/change-notes/released/0.2.1.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
## 0.2.1
|
||||||
9
cpp/ql/lib/change-notes/released/0.2.2.md
Normal file
9
cpp/ql/lib/change-notes/released/0.2.2.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
### Deprecated APIs
|
||||||
|
|
||||||
|
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.
|
||||||
5
cpp/ql/lib/change-notes/released/0.2.3.md
Normal file
5
cpp/ql/lib/change-notes/released/0.2.3.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.2.0
|
lastReleaseVersion: 0.2.3
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 0.2.1-dev
|
version: 0.3.0-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Field extends MemberVariable {
|
|||||||
int getByteOffset() { fieldoffsets(underlyingElement(this), result, _) }
|
int getByteOffset() { fieldoffsets(underlyingElement(this), result, _) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the byte offset within `mostDerivedClass` of each occurence of this
|
* Gets the byte offset within `mostDerivedClass` of each occurrence of this
|
||||||
* field within `mostDerivedClass` itself or a base class subobject of
|
* field within `mostDerivedClass` itself or a base class subobject of
|
||||||
* `mostDerivedClass`.
|
* `mostDerivedClass`.
|
||||||
* Note that for fields of virtual base classes, and non-virtual base classes
|
* Note that for fields of virtual base classes, and non-virtual base classes
|
||||||
|
|||||||
@@ -51,4 +51,7 @@ class Initializer extends ControlFlowNode, @initialiser {
|
|||||||
override Function getControlFlowScope() { result = this.getExpr().getEnclosingFunction() }
|
override Function getControlFlowScope() { result = this.getExpr().getEnclosingFunction() }
|
||||||
|
|
||||||
override Stmt getEnclosingStmt() { result = this.getExpr().getEnclosingStmt() }
|
override Stmt getEnclosingStmt() { result = this.getExpr().getEnclosingStmt() }
|
||||||
|
|
||||||
|
/** Holds if the initializer used the C++ braced initializer notation. */
|
||||||
|
predicate isBraced() { braced_initialisers(underlyingElement(this)) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
|||||||
}
|
}
|
||||||
|
|
||||||
override TypeDeclarationEntry getADeclarationEntry() {
|
override TypeDeclarationEntry getADeclarationEntry() {
|
||||||
if type_decls(_, underlyingElement(this), _)
|
if type_decls(_, unresolveElement(this), _)
|
||||||
then type_decls(unresolveElement(result), underlyingElement(this), _)
|
then type_decls(underlyingElement(result), unresolveElement(this), _)
|
||||||
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ private predicate callsVariadicFormatter(
|
|||||||
) {
|
) {
|
||||||
// calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
|
// calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
|
||||||
exists(FunctionCall fc, int format, int output |
|
exists(FunctionCall fc, int format, int output |
|
||||||
variadicFormatter(fc.getTarget(), type, format, output) and
|
variadicFormatter(pragma[only_bind_into](fc.getTarget()), type, format, output) and
|
||||||
fc.getEnclosingFunction() = f and
|
fc.getEnclosingFunction() = f and
|
||||||
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
||||||
fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess()
|
fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess()
|
||||||
@@ -176,7 +176,7 @@ private predicate callsVariadicFormatter(
|
|||||||
or
|
or
|
||||||
// calls a variadic formatter with only `formatParamIndex` linked
|
// calls a variadic formatter with only `formatParamIndex` linked
|
||||||
exists(FunctionCall fc, string calledType, int format, int output |
|
exists(FunctionCall fc, string calledType, int format, int output |
|
||||||
variadicFormatter(fc.getTarget(), calledType, format, output) and
|
variadicFormatter(pragma[only_bind_into](fc.getTarget()), calledType, format, output) and
|
||||||
fc.getEnclosingFunction() = f and
|
fc.getEnclosingFunction() = f and
|
||||||
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
||||||
not fc.getArgument(output) = f.getParameter(_).getAnAccess() and
|
not fc.getArgument(output) = f.getParameter(_).getAnAccess() and
|
||||||
@@ -872,7 +872,7 @@ class FormatLiteral extends Literal {
|
|||||||
|
|
||||||
private Type getConversionType1(int n) {
|
private Type getConversionType1(int n) {
|
||||||
exists(string cnv | cnv = this.getConversionChar(n) |
|
exists(string cnv | cnv = this.getConversionChar(n) |
|
||||||
cnv.regexpMatch("d|i") and
|
cnv = ["d", "i"] and
|
||||||
result = this.getIntegralConversion(n) and
|
result = this.getIntegralConversion(n) and
|
||||||
not result.getUnderlyingType().(IntegralType).isExplicitlySigned() and
|
not result.getUnderlyingType().(IntegralType).isExplicitlySigned() and
|
||||||
not result.getUnderlyingType().(IntegralType).isExplicitlyUnsigned()
|
not result.getUnderlyingType().(IntegralType).isExplicitlyUnsigned()
|
||||||
@@ -912,7 +912,7 @@ class FormatLiteral extends Literal {
|
|||||||
|
|
||||||
private Type getConversionType2(int n) {
|
private Type getConversionType2(int n) {
|
||||||
exists(string cnv | cnv = this.getConversionChar(n) |
|
exists(string cnv | cnv = this.getConversionChar(n) |
|
||||||
cnv.regexpMatch("o|u|x|X") and
|
cnv = ["o", "u", "x", "X"] and
|
||||||
result = this.getIntegralConversion(n) and
|
result = this.getIntegralConversion(n) and
|
||||||
result.getUnderlyingType().(IntegralType).isUnsigned()
|
result.getUnderlyingType().(IntegralType).isUnsigned()
|
||||||
)
|
)
|
||||||
@@ -920,7 +920,7 @@ class FormatLiteral extends Literal {
|
|||||||
|
|
||||||
private Type getConversionType3(int n) {
|
private Type getConversionType3(int n) {
|
||||||
exists(string cnv | cnv = this.getConversionChar(n) |
|
exists(string cnv | cnv = this.getConversionChar(n) |
|
||||||
cnv.regexpMatch("a|A|e|E|f|F|g|G") and result = this.getFloatingPointConversion(n)
|
cnv = ["a", "A", "e", "E", "f", "F", "g", "G"] and result = this.getFloatingPointConversion(n)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -970,7 +970,7 @@ private predicate subEdge(Pos p1, Node n1, Node n2, Pos p2) {
|
|||||||
private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2) {
|
private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2) {
|
||||||
subEdge(p1, n1, n2, p2)
|
subEdge(p1, n1, n2, p2)
|
||||||
or
|
or
|
||||||
// If `n1` has sub-nodes to accomodate destructors, but there are none to be
|
// If `n1` has sub-nodes to accommodate destructors, but there are none to be
|
||||||
// called, connect the "before destructors" node directly to the "after
|
// called, connect the "before destructors" node directly to the "after
|
||||||
// destructors" node. For performance, only do this when the nodes exist.
|
// destructors" node. For performance, only do this when the nodes exist.
|
||||||
exists(Pos afterDtors | afterDtors.isAfterDestructors() | subEdge(afterDtors, n1, _, _)) and
|
exists(Pos afterDtors | afterDtors.isAfterDestructors() | subEdge(afterDtors, n1, _, _)) and
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,10 +216,9 @@ private module LambdaFlow {
|
|||||||
or
|
or
|
||||||
// jump step
|
// jump step
|
||||||
exists(Node mid, DataFlowType t0 |
|
exists(Node mid, DataFlowType t0 |
|
||||||
revLambdaFlow(lambdaCall, kind, mid, t0, _, _, _) and
|
revLambdaFlow(lambdaCall, kind, mid, t0, _, _, lastCall) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = true and
|
toJump = true
|
||||||
lastCall = TDataFlowCallNone()
|
|
||||||
|
|
|
|
||||||
jumpStepCached(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -305,7 +304,7 @@ cached
|
|||||||
private module Cached {
|
private module Cached {
|
||||||
/**
|
/**
|
||||||
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
|
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
|
||||||
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
|
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and thereby
|
||||||
* collapsing the two stages.
|
* collapsing the two stages.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
@@ -789,24 +788,31 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
||||||
|
|
||||||
|
cached
|
||||||
|
predicate storeSet(
|
||||||
|
Node node1, ContentSet c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
|
) {
|
||||||
|
storeStep(node1, c, node2) and
|
||||||
|
contentType = getNodeDataFlowType(node1) and
|
||||||
|
containerType = getNodeDataFlowType(node2)
|
||||||
|
or
|
||||||
|
exists(Node n1, Node n2 |
|
||||||
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
|
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||||
|
|
|
||||||
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
|
or
|
||||||
|
readSet(n2, c, n1) and
|
||||||
|
contentType = getNodeDataFlowType(n1) and
|
||||||
|
containerType = getNodeDataFlowType(n2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate store(
|
private predicate store(
|
||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
exists(ContentSet cs | c = cs.getAStoreContent() |
|
exists(ContentSet cs |
|
||||||
storeStep(node1, cs, node2) and
|
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||||
contentType = getNodeDataFlowType(node1) and
|
|
||||||
containerType = getNodeDataFlowType(node2)
|
|
||||||
or
|
|
||||||
exists(Node n1, Node n2 |
|
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
|
||||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
|
||||||
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, cs, contentType), n1)
|
|
||||||
or
|
|
||||||
readSet(n2, cs, n1) and
|
|
||||||
contentType = getNodeDataFlowType(n1) and
|
|
||||||
containerType = getNodeDataFlowType(n2)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -850,6 +850,34 @@ class ContentSet instanceof Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||||
|
*
|
||||||
|
* The expression `e` is expected to be a syntactic part of the guard `g`.
|
||||||
|
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||||
|
* the argument `x`.
|
||||||
|
*/
|
||||||
|
signature predicate guardChecksSig(GuardCondition g, Expr e, boolean branch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||||
|
*
|
||||||
|
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||||
|
* in data flow and taint tracking.
|
||||||
|
*/
|
||||||
|
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||||
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
|
ExprNode getABarrierNode() {
|
||||||
|
exists(GuardCondition g, SsaDefinition def, Variable v, boolean branch |
|
||||||
|
result.getExpr() = def.getAUse(v) and
|
||||||
|
guardChecks(g, def.getAUse(v), branch) and
|
||||||
|
g.controls(result.getExpr().getBasicBlock(), branch)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* A guard that validates some expression.
|
* A guard that validates some expression.
|
||||||
*
|
*
|
||||||
* To use this in a configuration, extend the class and provide a
|
* To use this in a configuration, extend the class and provide a
|
||||||
@@ -858,7 +886,7 @@ class ContentSet instanceof Content {
|
|||||||
*
|
*
|
||||||
* It is important that all extending classes in scope are disjoint.
|
* It is important that all extending classes in scope are disjoint.
|
||||||
*/
|
*/
|
||||||
class BarrierGuard extends GuardCondition {
|
deprecated class BarrierGuard extends GuardCondition {
|
||||||
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
|
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
|
||||||
abstract predicate checks(Expr e, boolean b);
|
abstract predicate checks(Expr e, boolean b);
|
||||||
|
|
||||||
|
|||||||
@@ -549,7 +549,7 @@ module FlowVar_internal {
|
|||||||
bb = this.(Loop).getStmt() and
|
bb = this.(Loop).getStmt() and
|
||||||
v = this.getARelevantVariable()
|
v = this.getARelevantVariable()
|
||||||
or
|
or
|
||||||
this.reachesWithoutAssignment(bb.getAPredecessor(), v) and
|
this.reachesWithoutAssignment(pragma[only_bind_out](bb.getAPredecessor()), v) and
|
||||||
this.bbInLoop(bb)
|
this.bbInLoop(bb)
|
||||||
) and
|
) and
|
||||||
not assignsToVar(bb, v)
|
not assignsToVar(bb, v)
|
||||||
|
|||||||
@@ -47,12 +47,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
|||||||
*/
|
*/
|
||||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
|
||||||
* but not in local taint.
|
|
||||||
*/
|
|
||||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||||
|
|||||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
|||||||
|
|
||||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||||
|
|
||||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
this.isSanitizerGuard(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||||
* when the flow state is `state`.
|
* when the flow state is `state`.
|
||||||
*/
|
*/
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
deprecated final override predicate isBarrierGuard(
|
||||||
|
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||||
|
) {
|
||||||
this.isSanitizerGuard(guard, state)
|
this.isSanitizerGuard(guard, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
|||||||
|
|
||||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||||
|
|
||||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
this.isSanitizerGuard(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||||
* when the flow state is `state`.
|
* when the flow state is `state`.
|
||||||
*/
|
*/
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
deprecated final override predicate isBarrierGuard(
|
||||||
|
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||||
|
) {
|
||||||
this.isSanitizerGuard(guard, state)
|
this.isSanitizerGuard(guard, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class Expr extends StmtParent, @expr {
|
|||||||
/** Gets the enclosing variable of this expression, if any. */
|
/** Gets the enclosing variable of this expression, if any. */
|
||||||
Variable getEnclosingVariable() { result = exprEnclosingElement(this) }
|
Variable getEnclosingVariable() { result = exprEnclosingElement(this) }
|
||||||
|
|
||||||
|
/** Gets the enclosing variable or function of this expression. */
|
||||||
|
Declaration getEnclosingDeclaration() { result = exprEnclosingElement(this) }
|
||||||
|
|
||||||
/** Gets a child of this expression. */
|
/** Gets a child of this expression. */
|
||||||
Expr getAChild() { exists(int n | result = this.getChild(n)) }
|
Expr getAChild() { exists(int n | result = this.getChild(n)) }
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,7 @@
|
|||||||
* qualified.
|
* qualified.
|
||||||
*
|
*
|
||||||
* This file contains classes that mirror the standard AST classes for C++, but
|
* This file contains classes that mirror the standard AST classes for C++, but
|
||||||
* these classes are only concerned with naming. The other difference is that
|
* these classes are only concerned with naming.
|
||||||
* these classes don't use the `ResolveClass.qll` mechanisms like
|
|
||||||
* `unresolveElement` because these classes should eventually be part of the
|
|
||||||
* implementation of `ResolveClass.qll`, allowing it to match up classes when
|
|
||||||
* their qualified names and parameters match.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private import semmle.code.cpp.Declaration as D
|
private import semmle.code.cpp.Declaration as D
|
||||||
|
|||||||
@@ -115,15 +115,13 @@ private module Cached {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate isClass(@usertype t) {
|
predicate isClass(@usertype t) {
|
||||||
(
|
usertypes(t, _, 1) or
|
||||||
usertypes(t, _, 1) or
|
usertypes(t, _, 2) or
|
||||||
usertypes(t, _, 2) or
|
usertypes(t, _, 3) or
|
||||||
usertypes(t, _, 3) or
|
usertypes(t, _, 6) or
|
||||||
usertypes(t, _, 6) or
|
usertypes(t, _, 10) or
|
||||||
usertypes(t, _, 10) or
|
usertypes(t, _, 11) or
|
||||||
usertypes(t, _, 11) or
|
usertypes(t, _, 12)
|
||||||
usertypes(t, _, 12)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
|||||||
/** Holds if data flow out of `node` is prohibited. */
|
/** Holds if data flow out of `node` is prohibited. */
|
||||||
predicate isBarrierOut(Node node) { none() }
|
predicate isBarrierOut(Node node) { none() }
|
||||||
|
|
||||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||||
* the flow state is `state`
|
* the flow state is `state`
|
||||||
*/
|
*/
|
||||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||||
|
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||||
|
abstract predicate guardedNode(Node n, Configuration config);
|
||||||
|
|
||||||
|
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||||
|
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||||
|
exists(BarrierGuard g |
|
||||||
|
config.isBarrierGuard(g, state) and
|
||||||
|
n = g.getAGuardedNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
|||||||
not config.isSink(n) and
|
not config.isSink(n) and
|
||||||
not config.isSink(n, _)
|
not config.isSink(n, _)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||||
config.isBarrierGuard(g) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
|||||||
exists(Node n | node.asNode() = n |
|
exists(Node n | node.asNode() = n |
|
||||||
config.isBarrier(n, state)
|
config.isBarrier(n, state)
|
||||||
or
|
or
|
||||||
exists(BarrierGuard g |
|
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||||
config.isBarrierGuard(g, state) and
|
|
||||||
n = g.getAGuardedNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3854,16 +3877,11 @@ class PathNode extends TPathNode {
|
|||||||
/** Gets the associated configuration. */
|
/** Gets the associated configuration. */
|
||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private PathNode getASuccessorIfHidden() {
|
|
||||||
this.(PathNodeImpl).isHidden() and
|
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a successor of this node, if any. */
|
/** Gets a successor of this node, if any. */
|
||||||
final PathNode getASuccessor() {
|
final PathNode getASuccessor() {
|
||||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
|
||||||
not this.(PathNodeImpl).isHidden() and
|
reach(this) and
|
||||||
not result.(PathNodeImpl).isHidden()
|
reach(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this node is a source. */
|
/** Holds if this node is a source. */
|
||||||
@@ -3871,7 +3889,18 @@ class PathNode extends TPathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract private class PathNodeImpl extends PathNode {
|
abstract private class PathNodeImpl extends PathNode {
|
||||||
abstract PathNode getASuccessorImpl();
|
abstract PathNodeImpl getASuccessorImpl();
|
||||||
|
|
||||||
|
private PathNodeImpl getASuccessorIfHidden() {
|
||||||
|
this.isHidden() and
|
||||||
|
result = this.getASuccessorImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
final PathNodeImpl getANonHiddenSuccessor() {
|
||||||
|
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||||
|
not this.isHidden() and
|
||||||
|
not result.isHidden()
|
||||||
|
}
|
||||||
|
|
||||||
abstract NodeEx getNodeEx();
|
abstract NodeEx getNodeEx();
|
||||||
|
|
||||||
@@ -3914,15 +3943,17 @@ abstract private class PathNodeImpl extends PathNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink. */
|
/** Holds if `n` can reach a sink. */
|
||||||
private predicate directReach(PathNode n) {
|
private predicate directReach(PathNodeImpl n) {
|
||||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
|
||||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||||
|
|
||||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
|
||||||
|
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||||
|
|
||||||
@@ -3931,7 +3962,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
|||||||
*/
|
*/
|
||||||
module PathGraph {
|
module PathGraph {
|
||||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
|
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
|
||||||
|
|
||||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||||
query predicate nodes(PathNode n, string key, string val) {
|
query predicate nodes(PathNode n, string key, string val) {
|
||||||
@@ -4049,7 +4080,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
|
|||||||
|
|
||||||
override Configuration getConfiguration() { result = config }
|
override Configuration getConfiguration() { result = config }
|
||||||
|
|
||||||
override PathNode getASuccessorImpl() { none() }
|
override PathNodeImpl getASuccessorImpl() { none() }
|
||||||
|
|
||||||
override predicate isSource() { sourceNode(node, state, config) }
|
override predicate isSource() { sourceNode(node, state, config) }
|
||||||
}
|
}
|
||||||
@@ -4365,8 +4396,8 @@ private module Subpaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
|
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
|
||||||
succ = pred.getASuccessor() and
|
succ = pred.getANonHiddenSuccessor() and
|
||||||
succNode = succ.getNodeEx()
|
succNode = succ.getNodeEx()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,9 +4406,9 @@ private module Subpaths {
|
|||||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||||
*/
|
*/
|
||||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
|
||||||
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
|
||||||
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
|
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
|
||||||
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
|
||||||
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
hasSuccessor(pragma[only_bind_into](arg), par, p) and
|
||||||
not ret.isHidden() and
|
not ret.isHidden() and
|
||||||
@@ -4390,12 +4421,12 @@ private module Subpaths {
|
|||||||
/**
|
/**
|
||||||
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
|
||||||
*/
|
*/
|
||||||
predicate retReach(PathNode n) {
|
predicate retReach(PathNodeImpl n) {
|
||||||
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
|
||||||
or
|
or
|
||||||
exists(PathNode mid |
|
exists(PathNodeImpl mid |
|
||||||
retReach(mid) and
|
retReach(mid) and
|
||||||
n.getASuccessor() = mid and
|
n.getANonHiddenSuccessor() = mid and
|
||||||
not subpaths(_, mid, _, _)
|
not subpaths(_, mid, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,10 +216,9 @@ private module LambdaFlow {
|
|||||||
or
|
or
|
||||||
// jump step
|
// jump step
|
||||||
exists(Node mid, DataFlowType t0 |
|
exists(Node mid, DataFlowType t0 |
|
||||||
revLambdaFlow(lambdaCall, kind, mid, t0, _, _, _) and
|
revLambdaFlow(lambdaCall, kind, mid, t0, _, _, lastCall) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = true and
|
toJump = true
|
||||||
lastCall = TDataFlowCallNone()
|
|
||||||
|
|
|
|
||||||
jumpStepCached(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -305,7 +304,7 @@ cached
|
|||||||
private module Cached {
|
private module Cached {
|
||||||
/**
|
/**
|
||||||
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
|
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
|
||||||
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
|
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and thereby
|
||||||
* collapsing the two stages.
|
* collapsing the two stages.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
@@ -789,24 +788,31 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
||||||
|
|
||||||
|
cached
|
||||||
|
predicate storeSet(
|
||||||
|
Node node1, ContentSet c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
|
) {
|
||||||
|
storeStep(node1, c, node2) and
|
||||||
|
contentType = getNodeDataFlowType(node1) and
|
||||||
|
containerType = getNodeDataFlowType(node2)
|
||||||
|
or
|
||||||
|
exists(Node n1, Node n2 |
|
||||||
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
|
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||||
|
|
|
||||||
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
|
or
|
||||||
|
readSet(n2, c, n1) and
|
||||||
|
contentType = getNodeDataFlowType(n1) and
|
||||||
|
containerType = getNodeDataFlowType(n2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate store(
|
private predicate store(
|
||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
exists(ContentSet cs | c = cs.getAStoreContent() |
|
exists(ContentSet cs |
|
||||||
storeStep(node1, cs, node2) and
|
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||||
contentType = getNodeDataFlowType(node1) and
|
|
||||||
containerType = getNodeDataFlowType(node2)
|
|
||||||
or
|
|
||||||
exists(Node n1, Node n2 |
|
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
|
||||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
|
||||||
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, cs, contentType), n1)
|
|
||||||
or
|
|
||||||
readSet(n2, cs, n1) and
|
|
||||||
contentType = getNodeDataFlowType(n1) and
|
|
||||||
containerType = getNodeDataFlowType(n2)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ private module Cached {
|
|||||||
* along the chain of addresses computed by `StoreNodeInstr.getInner` to identify field writes
|
* along the chain of addresses computed by `StoreNodeInstr.getInner` to identify field writes
|
||||||
* and call `storeStep` accordingly (i.e., for an expression like `a.b.c = x`, we visit `c`, then
|
* and call `storeStep` accordingly (i.e., for an expression like `a.b.c = x`, we visit `c`, then
|
||||||
* `b`, then `a`).
|
* `b`, then `a`).
|
||||||
* 2. Flow is transfered from a `WriteSideEffectInstruction` to a `StoreNodeOperand` after flow
|
* 2. Flow is transferred from a `WriteSideEffectInstruction` to a `StoreNodeOperand` after flow
|
||||||
* returns to a caller. Flow will then proceed to the defining instruction of the operand (because
|
* returns to a caller. Flow will then proceed to the defining instruction of the operand (because
|
||||||
* the `StoreNodeInstr` computed by `StoreNodeOperand.getInner()` is the `StoreNode` containing
|
* the `StoreNodeInstr` computed by `StoreNodeOperand.getInner()` is the `StoreNode` containing
|
||||||
* the defining instruction), and then along the chain computed by `StoreNodeInstr.getInner` like
|
* the defining instruction), and then along the chain computed by `StoreNodeInstr.getInner` like
|
||||||
@@ -100,7 +100,7 @@ class Node extends TIRDataFlowNode {
|
|||||||
Declaration getEnclosingCallable() { none() } // overridden in subclasses
|
Declaration getEnclosingCallable() { none() } // overridden in subclasses
|
||||||
|
|
||||||
/** Gets the function to which this node belongs, if any. */
|
/** Gets the function to which this node belongs, if any. */
|
||||||
Function getFunction() { none() } // overridden in subclasses
|
Declaration getFunction() { none() } // overridden in subclasses
|
||||||
|
|
||||||
/** Gets the type of this node. */
|
/** Gets the type of this node. */
|
||||||
IRType getType() { none() } // overridden in subclasses
|
IRType getType() { none() } // overridden in subclasses
|
||||||
@@ -196,7 +196,7 @@ class InstructionNode extends Node, TInstructionNode {
|
|||||||
|
|
||||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||||
|
|
||||||
override Function getFunction() { result = instr.getEnclosingFunction() }
|
override Declaration getFunction() { result = instr.getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result = instr.getResultIRType() }
|
override IRType getType() { result = instr.getResultIRType() }
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ class OperandNode extends Node, TOperandNode {
|
|||||||
|
|
||||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||||
|
|
||||||
override Function getFunction() { result = op.getUse().getEnclosingFunction() }
|
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result = op.getIRType() }
|
override IRType getType() { result = op.getIRType() }
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ class StoreNodeInstr extends StoreNode, TStoreNodeInstr {
|
|||||||
/** Gets the underlying instruction. */
|
/** Gets the underlying instruction. */
|
||||||
Instruction getInstruction() { result = instr }
|
Instruction getInstruction() { result = instr }
|
||||||
|
|
||||||
override Function getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result = this.getInstruction().getResultIRType() }
|
override IRType getType() { result = this.getInstruction().getResultIRType() }
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ class StoreNodeOperand extends StoreNode, TStoreNodeOperand {
|
|||||||
/** Gets the underlying operand. */
|
/** Gets the underlying operand. */
|
||||||
Operand getOperand() { result = operand }
|
Operand getOperand() { result = operand }
|
||||||
|
|
||||||
override Function getFunction() { result = operand.getDef().getEnclosingFunction() }
|
override Declaration getFunction() { result = operand.getDef().getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result = operand.getIRType() }
|
override IRType getType() { result = operand.getIRType() }
|
||||||
|
|
||||||
@@ -384,7 +384,7 @@ class ReadNode extends Node, TReadNode {
|
|||||||
|
|
||||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||||
|
|
||||||
override Function getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result = this.getInstruction().getResultIRType() }
|
override IRType getType() { result = this.getInstruction().getResultIRType() }
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
|||||||
|
|
||||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||||
|
|
||||||
override Function getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||||
|
|
||||||
override IRType getType() { result instanceof IRVoidType }
|
override IRType getType() { result instanceof IRVoidType }
|
||||||
|
|
||||||
@@ -673,7 +673,7 @@ class VariableNode extends Node, TVariableNode {
|
|||||||
/** Gets the variable corresponding to this node. */
|
/** Gets the variable corresponding to this node. */
|
||||||
Variable getVariable() { result = v }
|
Variable getVariable() { result = v }
|
||||||
|
|
||||||
override Function getFunction() { none() }
|
override Declaration getFunction() { none() }
|
||||||
|
|
||||||
override Declaration getEnclosingCallable() {
|
override Declaration getEnclosingCallable() {
|
||||||
// When flow crosses from one _enclosing callable_ to another, the
|
// When flow crosses from one _enclosing callable_ to another, the
|
||||||
@@ -1092,6 +1092,56 @@ class ContentSet instanceof Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||||
|
*
|
||||||
|
* The expression `e` is expected to be a syntactic part of the guard `g`.
|
||||||
|
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||||
|
* the argument `x`.
|
||||||
|
*/
|
||||||
|
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||||
|
*
|
||||||
|
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||||
|
* in data flow and taint tracking.
|
||||||
|
*/
|
||||||
|
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||||
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
|
ExprNode getABarrierNode() {
|
||||||
|
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||||
|
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||||
|
result.asInstruction() = value.getAnInstruction() and
|
||||||
|
g.controls(result.asInstruction().getBlock(), edge)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
|
||||||
|
*/
|
||||||
|
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of barrier nodes for a guard that validates an instruction.
|
||||||
|
*
|
||||||
|
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||||
|
* in data flow and taint tracking.
|
||||||
|
*/
|
||||||
|
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
||||||
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
|
ExprNode getABarrierNode() {
|
||||||
|
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||||
|
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
||||||
|
result.asInstruction() = value.getAnInstruction() and
|
||||||
|
g.controls(result.asInstruction().getBlock(), edge)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* A guard that validates some instruction.
|
* A guard that validates some instruction.
|
||||||
*
|
*
|
||||||
* To use this in a configuration, extend the class and provide a
|
* To use this in a configuration, extend the class and provide a
|
||||||
@@ -1100,7 +1150,7 @@ class ContentSet instanceof Content {
|
|||||||
*
|
*
|
||||||
* It is important that all extending classes in scope are disjoint.
|
* It is important that all extending classes in scope are disjoint.
|
||||||
*/
|
*/
|
||||||
class BarrierGuard extends IRGuardCondition {
|
deprecated class BarrierGuard extends IRGuardCondition {
|
||||||
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
|
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
|
||||||
predicate checksInstr(Instruction instr, boolean b) { none() }
|
predicate checksInstr(Instruction instr, boolean b) { none() }
|
||||||
|
|
||||||
|
|||||||
@@ -94,12 +94,6 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
|||||||
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
|
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
|
||||||
or
|
or
|
||||||
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
|
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
|
||||||
or
|
|
||||||
exists(DataFlow::BarrierGuard guard |
|
|
||||||
any(DataFlow::Configuration cfg).isBarrierGuard(guard) and
|
|
||||||
node = guard.getAGuardedNode() and
|
|
||||||
kind = "guard(" + guard.getResultId() + ")"
|
|
||||||
)
|
|
||||||
|
|
|
|
||||||
kind, ", "
|
kind, ", "
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -163,12 +163,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
|||||||
*/
|
*/
|
||||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
|
||||||
* but not in local taint.
|
|
||||||
*/
|
|
||||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
|
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
|
||||||
* modeled function.
|
* modeled function.
|
||||||
|
|||||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
|||||||
|
|
||||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||||
|
|
||||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
this.isSanitizerGuard(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||||
* when the flow state is `state`.
|
* when the flow state is `state`.
|
||||||
*/
|
*/
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
deprecated final override predicate isBarrierGuard(
|
||||||
|
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||||
|
) {
|
||||||
this.isSanitizerGuard(guard, state)
|
this.isSanitizerGuard(guard, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
|||||||
|
|
||||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||||
|
|
||||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
this.isSanitizerGuard(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||||
* when the flow state is `state`.
|
* when the flow state is `state`.
|
||||||
*/
|
*/
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
deprecated final override predicate isBarrierGuard(
|
||||||
|
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||||
|
) {
|
||||||
this.isSanitizerGuard(guard, state)
|
this.isSanitizerGuard(guard, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
|||||||
|
|
||||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||||
|
|
||||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
/**
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||||
|
*/
|
||||||
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
this.isSanitizerGuard(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||||
|
*
|
||||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||||
* when the flow state is `state`.
|
* when the flow state is `state`.
|
||||||
*/
|
*/
|
||||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
deprecated final override predicate isBarrierGuard(
|
||||||
|
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||||
|
) {
|
||||||
this.isSanitizerGuard(guard, state)
|
this.isSanitizerGuard(guard, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class DefaultEdge extends EdgeKind, TDefaultEdge {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A "case" edge, representing the successor of a `Switch` instruction when the
|
* A "case" edge, representing the successor of a `Switch` instruction when the
|
||||||
* the condition value matches a correponding `case` label.
|
* the condition value matches a corresponding `case` label.
|
||||||
*/
|
*/
|
||||||
class CaseEdge extends EdgeKind, TCaseEdge {
|
class CaseEdge extends EdgeKind, TCaseEdge {
|
||||||
string minValue;
|
string minValue;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class IRConfiguration extends TIRConfiguration {
|
|||||||
/**
|
/**
|
||||||
* Holds if IR should be created for function `func`. By default, holds for all functions.
|
* Holds if IR should be created for function `func`. By default, holds for all functions.
|
||||||
*/
|
*/
|
||||||
predicate shouldCreateIRForFunction(Language::Function func) { any() }
|
predicate shouldCreateIRForFunction(Language::Declaration func) { any() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the strings used as part of an IR dump should be generated for function `func`.
|
* Holds if the strings used as part of an IR dump should be generated for function `func`.
|
||||||
@@ -25,7 +25,7 @@ class IRConfiguration extends TIRConfiguration {
|
|||||||
* of debug strings for IR that will not be dumped. We still generate the actual IR for these
|
* of debug strings for IR that will not be dumped. We still generate the actual IR for these
|
||||||
* functions, however, to preserve the results of any interprocedural analysis.
|
* functions, however, to preserve the results of any interprocedural analysis.
|
||||||
*/
|
*/
|
||||||
predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() }
|
predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { any() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration()
|
private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration()
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock {
|
|||||||
/**
|
/**
|
||||||
* Gets the `Function` that contains this block.
|
* Gets the `Function` that contains this block.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() {
|
final Language::Declaration getEnclosingFunction() {
|
||||||
result = getFirstInstruction(this).getEnclosingFunction()
|
result = getFirstInstruction(this).getEnclosingFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -524,4 +524,23 @@ module InstructionConsistency {
|
|||||||
"' has a `this` argument operand that is not an address, in function '$@'." and
|
"' has a `this` argument operand that is not an address, in function '$@'." and
|
||||||
irFunc = getInstructionIRFunction(instr, irFuncText)
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query predicate nonUniqueIRVariable(
|
||||||
|
Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText
|
||||||
|
) {
|
||||||
|
exists(VariableInstruction vi, IRVariable v1, IRVariable v2 |
|
||||||
|
instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2
|
||||||
|
) and
|
||||||
|
message =
|
||||||
|
"Variable instruction '" + instr.toString() +
|
||||||
|
"' has multiple associated variables, in function '$@'." and
|
||||||
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
|
or
|
||||||
|
instr.getOpcode() instanceof Opcode::VariableAddress and
|
||||||
|
not instr instanceof VariableInstruction and
|
||||||
|
message =
|
||||||
|
"Variable address instruction '" + instr.toString() +
|
||||||
|
"' has no associated variable, in function '$@'." and
|
||||||
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ private import Imports::IRType
|
|||||||
* by the AST-to-IR translation (`IRTempVariable`).
|
* by the AST-to-IR translation (`IRTempVariable`).
|
||||||
*/
|
*/
|
||||||
class IRVariable extends TIRVariable {
|
class IRVariable extends TIRVariable {
|
||||||
Language::Function func;
|
Language::Declaration func;
|
||||||
|
|
||||||
IRVariable() {
|
IRVariable() {
|
||||||
this = TIRUserVariable(_, _, func) or
|
this = TIRUserVariable(_, _, func) or
|
||||||
@@ -79,7 +79,7 @@ class IRVariable extends TIRVariable {
|
|||||||
/**
|
/**
|
||||||
* Gets the function that references this variable.
|
* Gets the function that references this variable.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() { result = func }
|
final Language::Declaration getEnclosingFunction() { result = func }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
|
|||||||
|
|
||||||
final override string toString() { result = "#ellipsis" }
|
final override string toString() { result = "#ellipsis" }
|
||||||
|
|
||||||
final override int getIndex() { result = func.getNumberOfParameters() }
|
final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction {
|
|||||||
/**
|
/**
|
||||||
* Gets the function that contains this instruction.
|
* Gets the function that contains this instruction.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() {
|
final Language::Declaration getEnclosingFunction() {
|
||||||
result = this.getEnclosingIRFunction().getFunction()
|
result = this.getEnclosingIRFunction().getFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
|||||||
* Holds if the IR for `func` should be printed. By default, holds for all
|
* Holds if the IR for `func` should be printed. By default, holds for all
|
||||||
* functions.
|
* functions.
|
||||||
*/
|
*/
|
||||||
predicate shouldPrintFunction(Language::Function func) { any() }
|
predicate shouldPrintFunction(Language::Declaration decl) { any() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
|
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
|
||||||
*/
|
*/
|
||||||
private class FilteredIRConfiguration extends IRConfiguration {
|
private class FilteredIRConfiguration extends IRConfiguration {
|
||||||
override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) {
|
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
|
||||||
shouldPrintFunction(func)
|
shouldPrintFunction(func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate shouldPrintFunction(Language::Function func) {
|
private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
|
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class ValueNumber extends TValueNumber {
|
|||||||
final Instruction getAnInstruction() { this = valueNumber(result) }
|
final Instruction getAnInstruction() { this = valueNumber(result) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets one of the instructions that was assigned this value number. The chosen instuction is
|
* Gets one of the instructions that was assigned this value number. The chosen instruction is
|
||||||
* deterministic but arbitrary. Intended for use only in debugging.
|
* deterministic but arbitrary. Intended for use only in debugging.
|
||||||
*/
|
*/
|
||||||
final Instruction getExampleInstruction() {
|
final Instruction getExampleInstruction() {
|
||||||
|
|||||||
@@ -1005,7 +1005,7 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
|||||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publically importing those modules in the
|
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||||
* `DebugSSA` module, which is then imported by PrintSSA.
|
* `DebugSSA` module, which is then imported by PrintSSA.
|
||||||
*/
|
*/
|
||||||
module DebugSsa {
|
module DebugSsa {
|
||||||
|
|||||||
@@ -5,23 +5,28 @@
|
|||||||
private import IRFunctionBaseInternal
|
private import IRFunctionBaseInternal
|
||||||
|
|
||||||
private newtype TIRFunction =
|
private newtype TIRFunction =
|
||||||
MkIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) }
|
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
|
||||||
|
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The IR for a function. This base class contains only the predicates that are the same between all
|
* The IR for a function. This base class contains only the predicates that are the same between all
|
||||||
* phases of the IR. Each instantiation of `IRFunction` extends this class.
|
* phases of the IR. Each instantiation of `IRFunction` extends this class.
|
||||||
*/
|
*/
|
||||||
class IRFunctionBase extends TIRFunction {
|
class IRFunctionBase extends TIRFunction {
|
||||||
Language::Function func;
|
Language::Declaration decl;
|
||||||
|
|
||||||
IRFunctionBase() { this = MkIRFunction(func) }
|
IRFunctionBase() {
|
||||||
|
this = TFunctionIRFunction(decl)
|
||||||
|
or
|
||||||
|
this = TVarInitIRFunction(decl)
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
final string toString() { result = "IR: " + func.toString() }
|
final string toString() { result = "IR: " + decl.toString() }
|
||||||
|
|
||||||
/** Gets the function whose IR is represented. */
|
/** Gets the function whose IR is represented. */
|
||||||
final Language::Function getFunction() { result = func }
|
final Language::Declaration getFunction() { result = decl }
|
||||||
|
|
||||||
/** Gets the location of the function. */
|
/** Gets the location of the function. */
|
||||||
final Language::Location getLocation() { result = func.getLocation() }
|
final Language::Location getLocation() { result = decl.getLocation() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ private import TIRVariableInternal
|
|||||||
private import Imports::TempVariableTag
|
private import Imports::TempVariableTag
|
||||||
|
|
||||||
newtype TIRVariable =
|
newtype TIRVariable =
|
||||||
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) {
|
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Declaration func) {
|
||||||
Construction::hasUserVariable(func, var, type)
|
Construction::hasUserVariable(func, var, type)
|
||||||
} or
|
} or
|
||||||
TIRTempVariable(
|
TIRTempVariable(
|
||||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
Language::Declaration func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||||
) {
|
) {
|
||||||
Construction::hasTempVariable(func, ast, tag, type)
|
Construction::hasTempVariable(func, ast, tag, type)
|
||||||
} or
|
} or
|
||||||
TIRDynamicInitializationFlag(
|
TIRDynamicInitializationFlag(
|
||||||
Language::Function func, Language::Variable var, Language::LanguageType type
|
Language::Declaration func, Language::Variable var, Language::LanguageType type
|
||||||
) {
|
) {
|
||||||
Construction::hasDynamicInitializationFlag(func, var, type)
|
Construction::hasDynamicInitializationFlag(func, var, type)
|
||||||
} or
|
} or
|
||||||
TIRStringLiteral(
|
TIRStringLiteral(
|
||||||
Language::Function func, Language::AST ast, Language::LanguageType type,
|
Language::Declaration func, Language::AST ast, Language::LanguageType type,
|
||||||
Language::StringLiteral literal
|
Language::StringLiteral literal
|
||||||
) {
|
) {
|
||||||
Construction::hasStringLiteral(func, ast, type, literal)
|
Construction::hasStringLiteral(func, ast, type, literal)
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock {
|
|||||||
/**
|
/**
|
||||||
* Gets the `Function` that contains this block.
|
* Gets the `Function` that contains this block.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() {
|
final Language::Declaration getEnclosingFunction() {
|
||||||
result = getFirstInstruction(this).getEnclosingFunction()
|
result = getFirstInstruction(this).getEnclosingFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -524,4 +524,23 @@ module InstructionConsistency {
|
|||||||
"' has a `this` argument operand that is not an address, in function '$@'." and
|
"' has a `this` argument operand that is not an address, in function '$@'." and
|
||||||
irFunc = getInstructionIRFunction(instr, irFuncText)
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query predicate nonUniqueIRVariable(
|
||||||
|
Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText
|
||||||
|
) {
|
||||||
|
exists(VariableInstruction vi, IRVariable v1, IRVariable v2 |
|
||||||
|
instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2
|
||||||
|
) and
|
||||||
|
message =
|
||||||
|
"Variable instruction '" + instr.toString() +
|
||||||
|
"' has multiple associated variables, in function '$@'." and
|
||||||
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
|
or
|
||||||
|
instr.getOpcode() instanceof Opcode::VariableAddress and
|
||||||
|
not instr instanceof VariableInstruction and
|
||||||
|
message =
|
||||||
|
"Variable address instruction '" + instr.toString() +
|
||||||
|
"' has no associated variable, in function '$@'." and
|
||||||
|
irFunc = getInstructionIRFunction(instr, irFuncText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ private import Imports::IRType
|
|||||||
* by the AST-to-IR translation (`IRTempVariable`).
|
* by the AST-to-IR translation (`IRTempVariable`).
|
||||||
*/
|
*/
|
||||||
class IRVariable extends TIRVariable {
|
class IRVariable extends TIRVariable {
|
||||||
Language::Function func;
|
Language::Declaration func;
|
||||||
|
|
||||||
IRVariable() {
|
IRVariable() {
|
||||||
this = TIRUserVariable(_, _, func) or
|
this = TIRUserVariable(_, _, func) or
|
||||||
@@ -79,7 +79,7 @@ class IRVariable extends TIRVariable {
|
|||||||
/**
|
/**
|
||||||
* Gets the function that references this variable.
|
* Gets the function that references this variable.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() { result = func }
|
final Language::Declaration getEnclosingFunction() { result = func }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
|
|||||||
|
|
||||||
final override string toString() { result = "#ellipsis" }
|
final override string toString() { result = "#ellipsis" }
|
||||||
|
|
||||||
final override int getIndex() { result = func.getNumberOfParameters() }
|
final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction {
|
|||||||
/**
|
/**
|
||||||
* Gets the function that contains this instruction.
|
* Gets the function that contains this instruction.
|
||||||
*/
|
*/
|
||||||
final Language::Function getEnclosingFunction() {
|
final Language::Declaration getEnclosingFunction() {
|
||||||
result = this.getEnclosingIRFunction().getFunction()
|
result = this.getEnclosingIRFunction().getFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
|||||||
* Holds if the IR for `func` should be printed. By default, holds for all
|
* Holds if the IR for `func` should be printed. By default, holds for all
|
||||||
* functions.
|
* functions.
|
||||||
*/
|
*/
|
||||||
predicate shouldPrintFunction(Language::Function func) { any() }
|
predicate shouldPrintFunction(Language::Declaration decl) { any() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
|
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
|
||||||
*/
|
*/
|
||||||
private class FilteredIRConfiguration extends IRConfiguration {
|
private class FilteredIRConfiguration extends IRConfiguration {
|
||||||
override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) {
|
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
|
||||||
shouldPrintFunction(func)
|
shouldPrintFunction(func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate shouldPrintFunction(Language::Function func) {
|
private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
|
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class ValueNumber extends TValueNumber {
|
|||||||
final Instruction getAnInstruction() { this = valueNumber(result) }
|
final Instruction getAnInstruction() { this = valueNumber(result) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets one of the instructions that was assigned this value number. The chosen instuction is
|
* Gets one of the instructions that was assigned this value number. The chosen instruction is
|
||||||
* deterministic but arbitrary. Intended for use only in debugging.
|
* deterministic but arbitrary. Intended for use only in debugging.
|
||||||
*/
|
*/
|
||||||
final Instruction getExampleInstruction() {
|
final Instruction getExampleInstruction() {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ private import TranslatedElement
|
|||||||
private import TranslatedExpr
|
private import TranslatedExpr
|
||||||
private import TranslatedStmt
|
private import TranslatedStmt
|
||||||
private import TranslatedFunction
|
private import TranslatedFunction
|
||||||
|
private import TranslatedGlobalVar
|
||||||
|
|
||||||
TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
|
TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
|
||||||
instruction = TRawInstruction(result, _)
|
instruction = TRawInstruction(result, _)
|
||||||
@@ -35,29 +36,41 @@ module Raw {
|
|||||||
cached
|
cached
|
||||||
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
|
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
|
||||||
|
|
||||||
|
cached
|
||||||
|
predicate varHasIRFunc(GlobalOrNamespaceVariable var) {
|
||||||
|
var.hasInitializer() and
|
||||||
|
(
|
||||||
|
not var.getType().isDeeplyConst()
|
||||||
|
or
|
||||||
|
var.getInitializer().getExpr() instanceof StringLiteral
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate hasInstruction(TranslatedElement element, InstructionTag tag) {
|
predicate hasInstruction(TranslatedElement element, InstructionTag tag) {
|
||||||
element.hasInstruction(_, tag, _)
|
element.hasInstruction(_, tag, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate hasUserVariable(Function func, Variable var, CppType type) {
|
predicate hasUserVariable(Declaration decl, Variable var, CppType type) {
|
||||||
getTranslatedFunction(func).hasUserVariable(var, type)
|
getTranslatedFunction(decl).hasUserVariable(var, type)
|
||||||
|
or
|
||||||
|
getTranslatedVarInit(decl).hasUserVariable(var, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
|
predicate hasTempVariable(Declaration decl, Locatable ast, TempVariableTag tag, CppType type) {
|
||||||
exists(TranslatedElement element |
|
exists(TranslatedElement element |
|
||||||
element.getAst() = ast and
|
element.getAst() = ast and
|
||||||
func = element.getFunction() and
|
decl = element.getFunction() and
|
||||||
element.hasTempVariable(tag, type)
|
element.hasTempVariable(tag, type)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) {
|
predicate hasStringLiteral(Declaration decl, Locatable ast, CppType type, StringLiteral literal) {
|
||||||
literal = ast and
|
literal = ast and
|
||||||
literal.getEnclosingFunction() = func and
|
literal.getEnclosingDeclaration() = decl and
|
||||||
getTypeForPRValue(literal.getType()) = type
|
getTypeForPRValue(literal.getType()) = type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
|||||||
/** DEPRECATED: Alias for getAst */
|
/** DEPRECATED: Alias for getAst */
|
||||||
deprecated override Locatable getAST() { result = getAst() }
|
deprecated override Locatable getAST() { result = getAst() }
|
||||||
|
|
||||||
final override Function getFunction() { result = getExpr().getEnclosingFunction() }
|
final override Declaration getFunction() { result = getExpr().getEnclosingDeclaration() }
|
||||||
|
|
||||||
final override TranslatedElement getChild(int i) {
|
final override TranslatedElement getChild(int i) {
|
||||||
result =
|
result =
|
||||||
@@ -375,7 +375,7 @@ abstract class TranslatedSideEffect extends TranslatedElement {
|
|||||||
kind instanceof GotoEdge
|
kind instanceof GotoEdge
|
||||||
}
|
}
|
||||||
|
|
||||||
final override Function getFunction() { result = getParent().getFunction() }
|
final override Declaration getFunction() { result = getParent().getFunction() }
|
||||||
|
|
||||||
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
||||||
tag = OnlyInstructionTag() and
|
tag = OnlyInstructionTag() and
|
||||||
@@ -436,13 +436,6 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
|||||||
result = index
|
result = index
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the `TranslatedFunction` containing this expression.
|
|
||||||
*/
|
|
||||||
final TranslatedFunction getEnclosingFunction() {
|
|
||||||
result = getTranslatedFunction(call.getEnclosingFunction())
|
|
||||||
}
|
|
||||||
|
|
||||||
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
||||||
opcode = sideEffectOpcode and
|
opcode = sideEffectOpcode and
|
||||||
(
|
(
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user