Merge branch 'main' into jorgectf/python/deserialization

This commit is contained in:
Rasmus Wriedt Larsen
2021-10-28 12:31:34 +02:00
1929 changed files with 197823 additions and 20995 deletions

View File

@@ -1,8 +1,11 @@
{ "provide": [ "*/ql/src/qlpack.yml",
{ "provide": [ "ruby/.codeqlmanifest.json",
"*/ql/src/qlpack.yml",
"*/ql/lib/qlpack.yml",
"*/ql/test/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/upgrades/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml" ] }

View File

@@ -1,9 +1,14 @@
{
"extensions": [
"rust-lang.rust",
"bungcip.better-toml",
"github.vscode-codeql",
"slevesque.vscode-zipexplorer"
],
"settings": {
"files.watcherExclude": {
"**/target/**": true
},
"codeQL.runningQueries.memory": 2048
}
}

14
.github/actions/fetch-codeql/action.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: Fetch CodeQL
description: Fetches the latest version of CodeQL
runs:
using: composite
steps:
- name: Fetch CodeQL
shell: bash
run: |
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
unzip -q codeql-linux64.zip
echo "${{ github.workspace }}/codeql" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ github.token }}

18
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "ruby/node-types"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/generator"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/extractor"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "ruby/autobuilder"
schedule:
interval: "daily"

4
.github/labeler.yml vendored
View File

@@ -18,6 +18,10 @@ Python:
- python/**/*
- change-notes/**/*python*
Ruby:
- ruby/**/*
- change-notes/**/*ruby*
documentation:
- "**/*.qhelp"
- "**/*.md"

View File

@@ -6,6 +6,8 @@ on:
- '.github/workflows/csv-coverage-pr-comment.yml'
- '*/ql/src/**/*.ql'
- '*/ql/src/**/*.qll'
- '*/ql/lib/**/*.ql'
- '*/ql/lib/**/*.qll'
- 'misc/scripts/library-coverage/*.py'
# input data files
- '*/documentation/library-coverage/cwe-sink.csv'

39
.github/workflows/qhelp-pr-preview.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Query help preview
on:
pull_request:
branches:
- main
- 'rc/*'
paths:
- "ruby/**/*.qhelp"
jobs:
qhelp:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- name: Determine changed files
id: changes
run: |
echo -n "::set-output name=qhelp_files::"
(git diff --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep .qhelp$ | grep -v .inc.qhelp;
git diff --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep .inc.qhelp$ | xargs -d '\n' -rn1 basename | xargs -d '\n' -rn1 git grep -l) |
sort -u | xargs -d '\n' -n1 printf "'%s' "
- uses: ./.github/actions/fetch-codeql
- name: QHelp preview
if: ${{ steps.changes.outputs.qhelp_files }}
run: |
( echo "QHelp previews:";
for path in ${{ steps.changes.outputs.qhelp_files }} ; do
echo "<details> <summary>${path}</summary>"
echo
codeql generate query-help --format=markdown ${path}
echo "</details>"
done) | gh pr comment "${{ github.event.pull_request.number }}" -F -
env:
GITHUB_TOKEN: ${{ github.token }}

232
.github/workflows/ruby-build.yml vendored Normal file
View File

@@ -0,0 +1,232 @@
name: "Ruby: Build"
on:
push:
paths:
- 'ruby/**'
branches:
- main
- 'rc/*'
pull_request:
paths:
- 'ruby/**'
branches:
- main
- 'rc/*'
workflow_dispatch:
inputs:
tag:
description: "Version tag to create"
required: false
env:
CARGO_TERM_COLOR: always
defaults:
run:
working-directory: ruby
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Install GNU tar
if: runner.os == 'macOS'
run: |
brew install gnu-tar
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
ruby/target
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- name: Release build
run: cargo build --release
- name: Generate dbscheme
if: ${{ matrix.os == 'ubuntu-latest' }}
run: target/release/ruby-generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v2
if: ${{ matrix.os == 'ubuntu-latest' }}
with:
name: ruby.dbscheme
path: ruby/ql/lib/ruby.dbscheme
- uses: actions/upload-artifact@v2
if: ${{ matrix.os == 'ubuntu-latest' }}
with:
name: TreeSitter.qll
path: ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v2
with:
name: extractor-${{ matrix.os }}
path: |
ruby/target/release/ruby-autobuilder
ruby/target/release/ruby-autobuilder.exe
ruby/target/release/ruby-extractor
ruby/target/release/ruby-extractor.exe
retention-days: 1
compile-queries:
runs-on: ubuntu-latest
env:
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
steps:
- uses: actions/checkout@v2
- name: Fetch CodeQL
run: |
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
unzip -q codeql-linux64.zip
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Build Query Pack
run: |
codeql/codeql pack create ql/lib --output target/packs
codeql/codeql pack install ql/src
codeql/codeql pack create ql/src --output target/packs
PACK_FOLDER=$(readlink -f target/packs/codeql/ruby-queries/*)
codeql/codeql generate query-help --format=sarifv2.1.0 --output="${PACK_FOLDER}/rules.sarif" ql/src
(cd ql/src; find queries \( -name '*.qhelp' -o -name '*.rb' -o -name '*.erb' \) -exec bash -c 'mkdir -p "'"${PACK_FOLDER}"'/$(dirname "{}")"' \; -exec cp "{}" "${PACK_FOLDER}/{}" \;)
- name: Compile with previous CodeQL versions
run: |
for version in $(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | tail -3 | head -2); do
rm -f codeql-linux64.zip
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$version"
rm -rf codeql; unzip -q codeql-linux64.zip
codeql/codeql query compile target/packs/*
done
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/upload-artifact@v2
with:
name: codeql-ruby-queries
path: |
ruby/target/packs/*
retention-days: 1
package:
runs-on: ubuntu-latest
needs: [build, compile-queries]
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: ruby.dbscheme
path: ruby/ruby
- uses: actions/download-artifact@v2
with:
name: extractor-ubuntu-latest
path: ruby/linux64
- uses: actions/download-artifact@v2
with:
name: extractor-windows-latest
path: ruby/win64
- uses: actions/download-artifact@v2
with:
name: extractor-macos-latest
path: ruby/osx64
- run: |
mkdir -p ruby
cp -r codeql-extractor.yml tools ql/lib/ruby.dbscheme.stats ruby/
mkdir -p ruby/tools/{linux64,osx64,win64}
cp linux64/ruby-autobuilder ruby/tools/linux64/autobuilder
cp osx64/ruby-autobuilder ruby/tools/osx64/autobuilder
cp win64/ruby-autobuilder.exe ruby/tools/win64/autobuilder.exe
cp linux64/ruby-extractor ruby/tools/linux64/extractor
cp osx64/ruby-extractor ruby/tools/osx64/extractor
cp win64/ruby-extractor.exe ruby/tools/win64/extractor.exe
chmod +x ruby/tools/{linux64,osx64}/{autobuilder,extractor}
zip -rq codeql-ruby.zip ruby
- uses: actions/upload-artifact@v2
with:
name: codeql-ruby-pack
path: ruby/codeql-ruby.zip
retention-days: 1
- uses: actions/download-artifact@v2
with:
name: codeql-ruby-queries
path: ruby/qlpacks
- run: |
echo '{
"provide": [
"ruby/codeql-extractor.yml",
"qlpacks/*/*/*/qlpack.yml"
]
}' > .codeqlmanifest.json
zip -rq codeql-ruby-bundle.zip .codeqlmanifest.json ruby qlpacks
- uses: actions/upload-artifact@v2
with:
name: codeql-ruby-bundle
path: ruby/codeql-ruby-bundle.zip
retention-days: 1
test:
defaults:
run:
working-directory: ${{ github.workspace }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
needs: [package]
steps:
- uses: actions/checkout@v2
with:
repository: Shopify/example-ruby-app
ref: 67a0decc5eb550f3a9228eda53925c3afd40dfe9
- name: Fetch CodeQL
shell: bash
run: |
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql.zip "$LATEST"
unzip -q codeql.zip
env:
GITHUB_TOKEN: ${{ github.token }}
working-directory: ${{ runner.temp }}
- name: Download Ruby bundle
uses: actions/download-artifact@v2
with:
name: codeql-ruby-bundle
path: ${{ runner.temp }}
- name: Unzip Ruby bundle
shell: bash
run: unzip -q -d "${{ runner.temp }}/ruby-bundle" "${{ runner.temp }}/codeql-ruby-bundle.zip"
- name: Prepare test files
shell: bash
run: |
echo "import ruby select count(File f)" > "test.ql"
echo "| 4 |" > "test.expected"
echo 'name: sample-tests
version: 0.0.0
dependencies:
codeql/ruby-all: 0.0.1
extractor: ruby
tests: .
' > qlpack.yml
- name: Run QL test
shell: bash
run: |
"${{ runner.temp }}/codeql/codeql" test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" .
- name: Create database
shell: bash
run: |
"${{ runner.temp }}/codeql/codeql" database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root . ../database
- name: Analyze database
shell: bash
run: |
"${{ runner.temp }}/codeql/codeql" database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls

View File

@@ -0,0 +1,71 @@
name: "Ruby: Collect database stats"
on:
push:
branches:
- main
- 'rc/*'
paths:
- ruby/ql/lib/ruby.dbscheme
pull_request:
branches:
- main
- 'rc/*'
paths:
- ruby/ql/lib/ruby.dbscheme
workflow_dispatch:
jobs:
measure:
env:
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
strategy:
fail-fast: false
matrix:
repo: [rails/rails, discourse/discourse, spree/spree]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- uses: ./ruby/actions/create-extractor-pack
- name: Checkout ${{ matrix.repo }}
uses: actions/checkout@v2
with:
repository: ${{ matrix.repo }}
path: ${{ github.workspace }}/repo
- name: Create database
run: |
codeql database create \
--search-path "${{ github.workspace }}/ruby" \
--threads 4 \
--language ruby --source-root "${{ github.workspace }}/repo" \
"${{ runner.temp }}/database"
- name: Measure database
run: |
mkdir -p "stats/${{ matrix.repo }}"
codeql dataset measure --threads 4 --output "stats/${{ matrix.repo }}/stats.xml" "${{ runner.temp }}/database/db-ruby"
- uses: actions/upload-artifact@v2
with:
name: measurements
path: stats
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: measure
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: measurements
path: stats
- run: |
python -m pip install --user lxml
find stats -name 'stats.xml' | sort | xargs python ruby/scripts/merge_stats.py --output ruby/ql/lib/ruby.dbscheme.stats --normalise ruby_tokeninfo
- uses: actions/upload-artifact@v2
with:
name: ruby.dbscheme.stats
path: ruby/ql/lib/ruby.dbscheme.stats

48
.github/workflows/ruby-qltest.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: "Ruby: Run QL Tests"
on:
push:
paths:
- 'ruby/**'
branches:
- main
- 'rc/*'
pull_request:
paths:
- 'ruby/**'
branches:
- main
- 'rc/*'
env:
CARGO_TERM_COLOR: always
defaults:
run:
working-directory: ruby
jobs:
qltest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- uses: ./ruby/actions/create-extractor-pack
- name: Run QL tests
run: |
codeql test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" --consistency-queries ql/consistency-queries ql/test
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib/upgrades
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme

20
.github/workflows/sync-files.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Check synchronized files
on:
push:
branches:
- main
- 'rc/*'
pull_request:
branches:
- main
- 'rc/*'
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check synchronized files
run: python config/sync-files.py

3
.gitignore vendored
View File

@@ -24,3 +24,6 @@
/codeql/
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
# Avoid committing cached package components
.codeql

View File

@@ -3,6 +3,7 @@
/java/ @github/codeql-java
/javascript/ @github/codeql-javascript
/python/ @github/codeql-python
/ruby/ @github/codeql-ruby
# Make @xcorail (GitHub Security Lab) a code owner for experimental queries so he gets pinged when we promote a query out of experimental
/cpp/**/experimental/**/* @github/codeql-c-analysis @xcorail
@@ -10,6 +11,7 @@
/java/**/experimental/**/* @github/codeql-java @xcorail
/javascript/**/experimental/**/* @github/codeql-javascript @xcorail
/python/**/experimental/**/* @github/codeql-python @xcorail
/ruby/**/experimental/**/* @github/codeql-ruby @xcorail
# Notify members of codeql-go about PRs to the shared data-flow library files
/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @github/codeql-java @github/codeql-go
@@ -22,4 +24,4 @@
/docs/codeql-cli/ @github/codeql-cli-reviewers
/docs/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
/docs/ql-language-reference/ @github/codeql-frontend-reviewers
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers

View File

@@ -24,14 +24,17 @@
"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/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/DataFlowImpl2.qll"
],
"DataFlow Java/C++/C#/Python Common": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
"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"
],
"TaintTracking::Configuration Java/C++/C#/Python": [
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
@@ -49,18 +52,21 @@
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
"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"
],
"DataFlow Java/C++/C#/Python Consistency checks": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
"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"
],
"DataFlow Java/C# Flow Summaries": [
"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"
],
"SsaReadPosition Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
@@ -367,8 +373,10 @@
],
"Inline Test Expectations": [
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"csharp/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"
],
"C++ ExternalAPIs": [
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
@@ -440,7 +448,8 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/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"
],
"CryptoAlgorithms Python/JS": [
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
@@ -460,6 +469,23 @@
],
"ReDoS Polynomial Python/JS": [
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll"
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll",
"ruby/ql/lib/codeql/ruby/regexp/SuperlinearBackTracking.qll"
],
"CFG": [
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll"
],
"TypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
],
"CodeQL Tutorial": [
"cpp/ql/lib/tutorial.qll",
"csharp/ql/lib/tutorial.qll",
"java/ql/lib/tutorial.qll",
"javascript/ql/lib/tutorial.qll",
"python/ql/lib/tutorial.qll",
"ruby/ql/lib/tutorial.qll"
]
}
}

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* A new query (`cpp/cleartext-transmission`) has been added. This is similar to the `cpp/cleartext-storage-file`, `cpp/cleartext-storage-buffer` and `cpp/cleartext-storage-database` queries but looks for cases where sensitive information is most likely transmitted over a network.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The "Uncontrolled data used in OS command" (`cpp/command-line-injection`) query has been enhanced to reduce false positive results and its `@precision` increased to `high`

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* Increase precision to high for the "Static buffer overflow" query
(`cpp/static-buffer-overflow`). This means the query is run and displayed by default on Code Scanning and LGTM.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Several improvements made to the `NullTermination.qll` library and the 'Potential improper null termination' (cpp/improper-null-termination). These changes reduce the number of false positive results for this query and related query 'User-controlled data may not be null terminated' (cpp/user-controlled-null-termination-tainted).

View File

@@ -0,0 +1,3 @@
codescanning
* Problems with extraction that in most cases won't break the analysis in a significant way are now reported as warnings rather than errors.
* The failed extractor invocations query now has severity `error`.

View File

@@ -52,11 +52,8 @@ module PrivateCleartextWrite {
class WriteSink extends Sink {
WriteSink() {
exists(FileWrite f, BufferWrite b |
this.asExpr() = f.getASource()
or
this.asExpr() = b.getAChild()
)
this.asExpr() = any(FileWrite f).getASource() or
this.asExpr() = any(BufferWrite b).getAChild()
}
}
}

View File

@@ -13,26 +13,25 @@ import cpp
/** A string for `match` that identifies strings that look like they represent private data. */
private string privateNames() {
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
// Government identifiers, such as Social Security Numbers
result = "%social%security%number%" or
// Contact information, such as home addresses and telephone numbers
result = "%postcode%" or
result = "%zipcode%" or
// result = "%telephone%" or
// Geographic location - where the user is (or was)
result = "%latitude%" or
result = "%longitude%" or
// Financial data - such as credit card numbers, salary, bank accounts, and debts
result = "%creditcard%" or
result = "%salary%" or
result = "%bankaccount%" or
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
// result = "%email%" or
// result = "%mobile%" or
result = "%employer%" or
// Health - medical conditions, insurance status, prescription records
result = "%medical%"
result =
[
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
// Government identifiers, such as Social Security Numbers
"%social%security%number%",
// Contact information, such as home addresses and telephone numbers
"%postcode%", "%zipcode%",
// result = "%telephone%" or
// Geographic location - where the user is (or was)
"%latitude%", "%longitude%",
// Financial data - such as credit card numbers, salary, bank accounts, and debts
"%creditcard%", "%salary%", "%bankaccount%",
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
// result = "%email%" or
// result = "%mobile%" or
"%employer%",
// Health - medical conditions, insurance status, prescription records
"%medical%"
]
}
/** An expression that might contain private data. */

View File

@@ -15,7 +15,7 @@ class ExternalData extends @externalDataElement {
* Gets the path of the file this data was loaded from, with its
* extension replaced by `.ql`.
*/
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
string getQueryPath() { result = this.getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
/** Gets the number of fields in this data item. */
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
@@ -24,22 +24,22 @@ class ExternalData extends @externalDataElement {
string getField(int i) { externalData(this, _, i, result) }
/** Gets the integer value of the `i`th field of this data item. */
int getFieldAsInt(int i) { result = getField(i).toInt() }
int getFieldAsInt(int i) { result = this.getField(i).toInt() }
/** Gets the floating-point value of the `i`th field of this data item. */
float getFieldAsFloat(int i) { result = getField(i).toFloat() }
float getFieldAsFloat(int i) { result = this.getField(i).toFloat() }
/** Gets the value of the `i`th field of this data item, interpreted as a date. */
date getFieldAsDate(int i) { result = getField(i).toDate() }
date getFieldAsDate(int i) { result = this.getField(i).toDate() }
/** Gets a textual representation of this data item. */
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
string toString() { result = this.getQueryPath() + ": " + this.buildTupleString(0) }
/** Gets a textual representation of this data item, starting with the `n`th field. */
private string buildTupleString(int n) {
n = getNumFields() - 1 and result = getField(n)
n = this.getNumFields() - 1 and result = this.getField(n)
or
n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1)
n < this.getNumFields() - 1 and result = this.getField(n) + "," + this.buildTupleString(n + 1)
}
}
@@ -53,8 +53,8 @@ class DefectExternalData extends ExternalData {
}
/** Gets the URL associated with this data item. */
string getURL() { result = getField(0) }
string getURL() { result = this.getField(0) }
/** Gets the message associated with this data item. */
string getMessage() { result = getField(1) }
string getMessage() { result = this.getField(1) }
}

View File

@@ -269,13 +269,13 @@ class Class extends UserType {
* DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that
* `= default` members are no longer included.
*/
deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() }
deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() }
/**
* DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to
* reflect that `= default` members are no longer included.
*/
deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() }
deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() }
/**
* Holds if this class, struct or union has an implicitly-declared copy
@@ -487,7 +487,7 @@ class Class extends UserType {
exists(ClassDerivation cd |
// Add the offset of the direct base class and the offset of `baseClass`
// within that direct base class.
cd = getADerivation() and
cd = this.getADerivation() and
result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset()
)
}
@@ -502,12 +502,12 @@ class Class extends UserType {
*/
int getABaseClassByteOffset(Class baseClass) {
// Handle the non-virtual case.
result = getANonVirtualBaseClassByteOffset(baseClass)
result = this.getANonVirtualBaseClassByteOffset(baseClass)
or
exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase |
// Look for the base class as a non-virtual base of a direct or indirect
// virtual base, adding the two offsets.
getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
this.getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and
result = virtualBaseOffset + offsetFromVirtualBase
)
@@ -623,11 +623,11 @@ class Class extends UserType {
* inherits one).
*/
predicate isPolymorphic() {
exists(MemberFunction f | f.getDeclaringType() = getABaseClass*() and f.isVirtual())
exists(MemberFunction f | f.getDeclaringType() = this.getABaseClass*() and f.isVirtual())
}
override predicate involvesTemplateParameter() {
getATemplateArgument().(Type).involvesTemplateParameter()
this.getATemplateArgument().(Type).involvesTemplateParameter()
}
/** Holds if this class, struct or union was declared 'final'. */
@@ -765,7 +765,7 @@ class ClassDerivation extends Locatable, @derivation {
* };
* ```
*/
Class getBaseClass() { result = getBaseType().getUnderlyingType() }
Class getBaseClass() { result = this.getBaseType().getUnderlyingType() }
override string getAPrimaryQlClass() { result = "ClassDerivation" }
@@ -818,7 +818,7 @@ class ClassDerivation extends Locatable, @derivation {
predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) }
/** Holds if the derivation is for a virtual base class. */
predicate isVirtual() { hasSpecifier("virtual") }
predicate isVirtual() { this.hasSpecifier("virtual") }
/** Gets the location of the derivation. */
override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) }
@@ -846,7 +846,7 @@ class ClassDerivation extends Locatable, @derivation {
* ```
*/
class LocalClass extends Class {
LocalClass() { isLocal() }
LocalClass() { this.isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
@@ -989,9 +989,9 @@ class ClassTemplateSpecialization extends Class {
TemplateClass getPrimaryTemplate() {
// Ignoring template arguments, the primary template has the same name
// as each of its specializations.
result.getSimpleName() = getSimpleName() and
result.getSimpleName() = this.getSimpleName() and
// It is in the same namespace as its specializations.
result.getNamespace() = getNamespace() and
result.getNamespace() = this.getNamespace() and
// It is distinguished by the fact that each of its template arguments
// is a distinct template parameter.
count(TemplateParameter tp | tp = result.getATemplateArgument()) =
@@ -1108,7 +1108,7 @@ deprecated class Interface extends Class {
* ```
*/
class VirtualClassDerivation extends ClassDerivation {
VirtualClassDerivation() { hasSpecifier("virtual") }
VirtualClassDerivation() { this.hasSpecifier("virtual") }
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
}
@@ -1136,7 +1136,7 @@ class VirtualBaseClass extends Class {
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
/** A class/struct that is derived from this one using virtual inheritance. */
Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() }
Class getAVirtuallyDerivedClass() { result = this.getAVirtualDerivation().getDerivedClass() }
}
/**
@@ -1155,7 +1155,7 @@ class ProxyClass extends UserType {
override string getAPrimaryQlClass() { result = "ProxyClass" }
/** Gets the location of the proxy class. */
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
/** Gets the template parameter for which this is the proxy class. */
TemplateParameter getTemplateParameter() {

View File

@@ -184,7 +184,7 @@ class Declaration extends Locatable, @declaration {
predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */
predicate isDefined() { hasDefinition() }
predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() }
@@ -209,7 +209,7 @@ class Declaration extends Locatable, @declaration {
predicate isStatic() { this.hasSpecifier("static") }
/** Holds if this declaration is a member of a class/struct/union. */
predicate isMember() { hasDeclaringType() }
predicate isMember() { this.hasDeclaringType() }
/** Holds if this declaration is a member of a class/struct/union. */
predicate hasDeclaringType() { exists(this.getDeclaringType()) }
@@ -226,14 +226,14 @@ class Declaration extends Locatable, @declaration {
* When called on a template, this will return a template parameter type for
* both typed and non-typed parameters.
*/
final Locatable getATemplateArgument() { result = getTemplateArgument(_) }
final Locatable getATemplateArgument() { result = this.getTemplateArgument(_) }
/**
* Gets a template argument used to instantiate this declaration from a template.
* When called on a template, this will return a non-typed template
* parameter value.
*/
final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) }
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
/**
* Gets the `i`th template argument used to instantiate this declaration from a
@@ -252,9 +252,9 @@ class Declaration extends Locatable, @declaration {
* `getTemplateArgument(1)` return `1`.
*/
final Locatable getTemplateArgument(int index) {
if exists(getTemplateArgumentValue(index))
then result = getTemplateArgumentValue(index)
else result = getTemplateArgumentType(index)
if exists(this.getTemplateArgumentValue(index))
then result = this.getTemplateArgumentValue(index)
else result = this.getTemplateArgumentType(index)
}
/**
@@ -275,14 +275,13 @@ class Declaration extends Locatable, @declaration {
* `getTemplateArgumentKind(0)`.
*/
final Locatable getTemplateArgumentKind(int index) {
if exists(getTemplateArgumentValue(index))
then result = getTemplateArgumentType(index)
else none()
exists(this.getTemplateArgumentValue(index)) and
result = this.getTemplateArgumentType(index)
}
/** Gets the number of template arguments for this declaration. */
final int getNumberOfTemplateArguments() {
result = count(int i | exists(getTemplateArgument(i)))
result = count(int i | exists(this.getTemplateArgument(i)))
}
private Type getTemplateArgumentType(int index) {
@@ -328,9 +327,9 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
* available), or the name declared by this entry otherwise.
*/
string getCanonicalName() {
if getDeclaration().hasDefinition()
then result = getDeclaration().getDefinition().getName()
else result = getName()
if this.getDeclaration().hasDefinition()
then result = this.getDeclaration().getDefinition().getName()
else result = this.getName()
}
/**
@@ -371,18 +370,18 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
/**
* Holds if this declaration entry has a specifier with the given name.
*/
predicate hasSpecifier(string specifier) { getASpecifier() = specifier }
predicate hasSpecifier(string specifier) { this.getASpecifier() = specifier }
/** Holds if this declaration entry is a definition. */
predicate isDefinition() { none() } // overridden in subclasses
override string toString() {
if isDefinition()
then result = "definition of " + getName()
if this.isDefinition()
then result = "definition of " + this.getName()
else
if getName() = getCanonicalName()
then result = "declaration of " + getName()
else result = "declaration of " + getCanonicalName() + " as " + getName()
if this.getName() = this.getCanonicalName()
then result = "declaration of " + this.getName()
else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
}
}
@@ -581,7 +580,7 @@ private class DirectAccessHolder extends Element {
// transitive closure with a restricted base case.
this.thisCanAccessClassStep(base, derived)
or
exists(Class between | thisCanAccessClassTrans(base, between) |
exists(Class between | this.thisCanAccessClassTrans(base, between) |
isDirectPublicBaseOf(between, derived) or
this.thisCanAccessClassStep(between, derived)
)

View File

@@ -61,7 +61,7 @@ class ElementBase extends @element {
/**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/
final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
/**
* Gets the name of a primary CodeQL class to which this element belongs.
@@ -206,9 +206,9 @@ class Element extends ElementBase {
/** Gets the closest `Element` enclosing this one. */
cached
Element getEnclosingElement() {
result = getEnclosingElementPref()
result = this.getEnclosingElementPref()
or
not exists(getEnclosingElementPref()) and
not exists(this.getEnclosingElementPref()) and
(
this = result.(Class).getAMember()
or
@@ -281,7 +281,7 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
* ```
*/
class StaticAssert extends Locatable, @static_assert {
override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" }
override string toString() { result = "static_assert(..., \"" + this.getMessage() + "\")" }
/**
* Gets the expression which this static assertion ensures is true.

View File

@@ -85,7 +85,7 @@ class Enum extends UserType, IntegralOrEnumType {
* ```
*/
class LocalEnum extends Enum {
LocalEnum() { isLocal() }
LocalEnum() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalEnum" }
}

View File

@@ -38,7 +38,7 @@ class Container extends Locatable, @container {
* DEPRECATED: Use `getLocation` instead.
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://help.semmle.com/QL/learn-ql/ql/locations.html#providing-urls).
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
deprecated string getURL() { none() } // overridden by subclasses
@@ -52,7 +52,7 @@ class Container extends Locatable, @container {
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
@@ -79,7 +79,7 @@ class Container extends Locatable, @container {
* </table>
*/
string getBaseName() {
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
}
/**
@@ -105,7 +105,9 @@ class Container extends Locatable, @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
* </table>
*/
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) }
string getExtension() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
}
/**
* Gets the stem of this container, that is, the prefix of its base name up to
@@ -124,7 +126,9 @@ class Container extends Locatable, @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) }
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() {
@@ -135,20 +139,20 @@ class Container extends Locatable, @container {
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = getAChildContainer() }
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = getAFile() and
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = getAChildContainer() }
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = getAFolder() and
result = this.getAFolder() and
result.getBaseName() = baseName
}
@@ -157,7 +161,7 @@ class Container extends Locatable, @container {
*
* This is the absolute path of the container.
*/
override string toString() { result = getAbsolutePath() }
override string toString() { result = this.getAbsolutePath() }
}
/**

View File

@@ -43,26 +43,26 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/
string getFullSignature() {
exists(string name, string templateArgs, string args |
result = name + templateArgs + args + " -> " + getType().toString() and
name = getQualifiedName() and
result = name + templateArgs + args + " -> " + this.getType().toString() and
name = this.getQualifiedName() and
(
if exists(getATemplateArgument())
if exists(this.getATemplateArgument())
then
templateArgs =
"<" +
concat(int i |
exists(getTemplateArgument(i))
exists(this.getTemplateArgument(i))
|
getTemplateArgument(i).toString(), ", " order by i
this.getTemplateArgument(i).toString(), ", " order by i
) + ">"
else templateArgs = ""
) and
args =
"(" +
concat(int i |
exists(getParameter(i))
exists(this.getParameter(i))
|
getParameter(i).getType().toString(), ", " order by i
this.getParameter(i).getType().toString(), ", " order by i
) + ")"
)
}
@@ -70,7 +70,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
/** Gets a specifier of this function. */
override Specifier getASpecifier() {
funspecifiers(underlyingElement(this), unresolveElement(result)) or
result.hasName(getADeclarationEntry().getASpecifier())
result.hasName(this.getADeclarationEntry().getASpecifier())
}
/** Gets an attribute of this function. */
@@ -149,7 +149,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Holds if this function is declared with `__attribute__((naked))` or
* `__declspec(naked)`.
*/
predicate isNaked() { getAnAttribute().hasName("naked") }
predicate isNaked() { this.getAnAttribute().hasName("naked") }
/**
* Holds if this function has a trailing return type.
@@ -172,7 +172,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the return type of this function after specifiers have been deeply
* stripped and typedefs have been resolved.
*/
Type getUnspecifiedType() { result = getType().getUnspecifiedType() }
Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() }
/**
* Gets the nth parameter of this function. There is no result for the
@@ -206,7 +206,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
int getEffectiveNumberOfParameters() {
// This method is overridden in `MemberFunction`, where the result is
// adjusted to account for the implicit `this` parameter.
result = getNumberOfParameters()
result = this.getNumberOfParameters()
}
/**
@@ -216,7 +216,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* return `int p1, int p2`.
*/
string getParameterString() {
result = concat(int i | | min(getParameter(i).getTypedName()), ", " order by i)
result = concat(int i | | min(this.getParameter(i).getTypedName()), ", " order by i)
}
/** Gets a call to this function. */
@@ -229,7 +229,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/
override FunctionDeclarationEntry getADeclarationEntry() {
if fun_decls(_, underlyingElement(this), _, _, _)
then declEntry(result)
then this.declEntry(result)
else
exists(Function f |
this.isConstructedFrom(f) and
@@ -250,7 +250,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the location of a `FunctionDeclarationEntry` corresponding to this
* declaration.
*/
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
/** Holds if this Function is a Template specialization. */
predicate isSpecialization() {
@@ -265,14 +265,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if any.
*/
override FunctionDeclarationEntry getDefinition() {
result = getADeclarationEntry() and
result = this.getADeclarationEntry() and
result.isDefinition()
}
/** Gets the location of the definition, if any. */
override Location getDefinitionLocation() {
if exists(getDefinition())
then result = getDefinition().getLocation()
if exists(this.getDefinition())
then result = this.getDefinition().getLocation()
else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation())
}
@@ -281,7 +281,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if possible.)
*/
override Location getLocation() {
if exists(getDefinition())
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
@@ -299,7 +299,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
BlockStmt getBlock() { result.getParentScope() = this }
/** Holds if this function has an entry point. */
predicate hasEntryPoint() { exists(getEntryPoint()) }
predicate hasEntryPoint() { exists(this.getEntryPoint()) }
/**
* Gets the first node in this function's control flow graph.
@@ -392,7 +392,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Holds if this function has C linkage, as specified by one of its
* declaration entries. For example: `extern "C" void foo();`.
*/
predicate hasCLinkage() { getADeclarationEntry().hasCLinkage() }
predicate hasCLinkage() { this.getADeclarationEntry().hasCLinkage() }
/**
* Holds if this function is constructed from `f` as a result
@@ -409,27 +409,27 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* several functions that are not linked together have been compiled. An
* example would be a project with many 'main' functions.
*/
predicate isMultiplyDefined() { strictcount(getFile()) > 1 }
predicate isMultiplyDefined() { strictcount(this.getFile()) > 1 }
/** Holds if this function is a varargs function. */
predicate isVarargs() { hasSpecifier("varargs") }
predicate isVarargs() { this.hasSpecifier("varargs") }
/** Gets a type that is specified to be thrown by the function. */
Type getAThrownType() { result = getADeclarationEntry().getAThrownType() }
Type getAThrownType() { result = this.getADeclarationEntry().getAThrownType() }
/**
* Gets the `i`th type specified to be thrown by the function.
*/
Type getThrownType(int i) { result = getADeclarationEntry().getThrownType(i) }
Type getThrownType(int i) { result = this.getADeclarationEntry().getThrownType(i) }
/** Holds if the function has an exception specification. */
predicate hasExceptionSpecification() { getADeclarationEntry().hasExceptionSpecification() }
predicate hasExceptionSpecification() { this.getADeclarationEntry().hasExceptionSpecification() }
/** Holds if this function has a `throw()` exception specification. */
predicate isNoThrow() { getADeclarationEntry().isNoThrow() }
predicate isNoThrow() { this.getADeclarationEntry().isNoThrow() }
/** Holds if this function has a `noexcept` exception specification. */
predicate isNoExcept() { getADeclarationEntry().isNoExcept() }
predicate isNoExcept() { this.getADeclarationEntry().isNoExcept() }
/**
* Gets a function that overloads this one.
@@ -539,7 +539,7 @@ private predicate candGetAnOverloadNonMember(string name, Namespace namespace, F
*/
class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
/** Gets the function which is being declared or defined. */
override Function getDeclaration() { result = getFunction() }
override Function getDeclaration() { result = this.getFunction() }
override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" }
@@ -586,7 +586,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* case, catch) plus the number of branching expressions (`?`, `&&`,
* `||`) plus one.
*/
int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(getBlock()) }
int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(this.getBlock()) }
/**
* If this is a function definition, get the block containing the
@@ -594,7 +594,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
*/
BlockStmt getBlock() {
this.isDefinition() and
result = getFunction().getBlock() and
result = this.getFunction().getBlock() and
result.getFile() = this.getFile()
}
@@ -604,7 +604,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
*/
pragma[noopt]
int getNumberOfLines() {
exists(BlockStmt b, Location l, int start, int end, int diff | b = getBlock() |
exists(BlockStmt b, Location l, int start, int end, int diff | b = this.getBlock() |
l = b.getLocation() and
start = l.getStartLine() and
end = l.getEndLine() and
@@ -618,7 +618,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* declaration.
*/
ParameterDeclarationEntry getAParameterDeclarationEntry() {
result = getParameterDeclarationEntry(_)
result = this.getParameterDeclarationEntry(_)
}
/**
@@ -639,7 +639,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
* return 'int p1, int p2'.
*/
string getParameterString() {
result = concat(int i | | min(getParameterDeclarationEntry(i).getTypedName()), ", " order by i)
result =
concat(int i | | min(this.getParameterDeclarationEntry(i).getTypedName()), ", " order by i)
}
/**
@@ -647,10 +648,10 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
*
* `extern "C" void foo();`
*/
predicate hasCLinkage() { getASpecifier() = "c_linkage" }
predicate hasCLinkage() { this.getASpecifier() = "c_linkage" }
/** Holds if this declaration entry has a void parameter list. */
predicate hasVoidParamList() { getASpecifier() = "void_param_list" }
predicate hasVoidParamList() { this.getASpecifier() = "void_param_list" }
/** Holds if this declaration is also a definition of its function. */
override predicate isDefinition() { fun_def(underlyingElement(this)) }
@@ -665,7 +666,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
predicate isImplicit() { fun_implicit(underlyingElement(this)) }
/** Gets a type that is specified to be thrown by the declared function. */
Type getAThrownType() { result = getThrownType(_) }
Type getAThrownType() { result = this.getThrownType(_) }
/**
* Gets the `i`th type specified to be thrown by the declared function
@@ -690,8 +691,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
predicate hasExceptionSpecification() {
fun_decl_throws(underlyingElement(this), _, _) or
fun_decl_noexcept(underlyingElement(this), _) or
isNoThrow() or
isNoExcept()
this.isNoThrow() or
this.isNoExcept()
}
/**
@@ -763,7 +764,7 @@ class Operator extends Function {
*/
class TemplateFunction extends Function {
TemplateFunction() {
is_function_template(underlyingElement(this)) and exists(getATemplateArgument())
is_function_template(underlyingElement(this)) and exists(this.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "TemplateFunction" }

View File

@@ -23,7 +23,7 @@ class Include extends PreprocessorDirective, @ppd_include {
* Gets the token which occurs after `#include`, for example `"filename"`
* or `<filename>`.
*/
string getIncludeText() { result = getHead() }
string getIncludeText() { result = this.getHead() }
/** Gets the file directly included by this `#include`. */
File getIncludedFile() { includes(underlyingElement(this), unresolveElement(result)) }
@@ -53,7 +53,7 @@ class Include extends PreprocessorDirective, @ppd_include {
* ```
*/
class IncludeNext extends Include, @ppd_include_next {
override string toString() { result = "#include_next " + getIncludeText() }
override string toString() { result = "#include_next " + this.getIncludeText() }
}
/**
@@ -65,5 +65,5 @@ class IncludeNext extends Include, @ppd_include_next {
* ```
*/
class Import extends Include, @ppd_objc_import {
override string toString() { result = "#import " + getIncludeText() }
override string toString() { result = "#import " + this.getIncludeText() }
}

View File

@@ -34,8 +34,8 @@ class Initializer extends ControlFlowNode, @initialiser {
override predicate fromSource() { not this.getLocation() instanceof UnknownLocation }
override string toString() {
if exists(getDeclaration())
then result = "initializer for " + max(getDeclaration().getName())
if exists(this.getDeclaration())
then result = "initializer for " + max(this.getDeclaration().getName())
else result = "initializer"
}

View File

@@ -61,7 +61,7 @@ class Location extends @location {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -79,8 +79,8 @@ class Location extends @location {
/** Holds if location `l` is completely contained within this one. */
predicate subsumes(Location l) {
exists(File f | f = getFile() |
exists(int thisStart, int thisEnd | charLoc(f, thisStart, thisEnd) |
exists(File f | f = this.getFile() |
exists(int thisStart, int thisEnd | this.charLoc(f, thisStart, thisEnd) |
exists(int lStart, int lEnd | l.charLoc(f, lStart, lEnd) |
thisStart <= lStart and lEnd <= thisEnd
)
@@ -97,10 +97,10 @@ class Location extends @location {
* see `subsumes`.
*/
predicate charLoc(File f, int start, int end) {
f = getFile() and
f = this.getFile() and
exists(int maxCols | maxCols = maxCols(f) |
start = getStartLine() * maxCols + getStartColumn() and
end = getEndLine() * maxCols + getEndColumn()
start = this.getStartLine() * maxCols + this.getStartColumn() and
end = this.getEndLine() * maxCols + this.getEndColumn()
)
}
}
@@ -144,7 +144,7 @@ class Locatable extends Element { }
* expressions, one for statements and one for other program elements.
*/
class UnknownLocation extends Location {
UnknownLocation() { getFile().getAbsolutePath() = "" }
UnknownLocation() { this.getFile().getAbsolutePath() = "" }
}
/**

View File

@@ -44,10 +44,10 @@ class Macro extends PreprocessorDirective, @ppd_define {
* Gets the name of the macro. For example, `MAX` in
* `#define MAX(x,y) (((x)>(y))?(x):(y))`.
*/
string getName() { result = getHead().splitAt("(", 0) }
string getName() { result = this.getHead().splitAt("(", 0) }
/** Holds if the macro has name `name`. */
predicate hasName(string name) { getName() = name }
predicate hasName(string name) { this.getName() = name }
}
/**
@@ -130,7 +130,7 @@ class MacroAccess extends Locatable, @macroinvocation {
override string toString() { result = this.getMacro().getHead() }
/** Gets the name of the accessed macro. */
string getMacroName() { result = getMacro().getName() }
string getMacroName() { result = this.getMacro().getName() }
}
/**
@@ -197,8 +197,8 @@ class MacroInvocation extends MacroAccess {
* expression. In other cases, it may have multiple results or no results.
*/
Expr getExpr() {
result = getAnExpandedElement() and
not result.getParent() = getAnExpandedElement() and
result = this.getAnExpandedElement() and
not result.getParent() = this.getAnExpandedElement() and
not result instanceof Conversion
}
@@ -208,8 +208,8 @@ class MacroInvocation extends MacroAccess {
* element is not a statement (for example if it is an expression).
*/
Stmt getStmt() {
result = getAnExpandedElement() and
not result.getParent() = getAnExpandedElement()
result = this.getAnExpandedElement() and
not result.getParent() = this.getAnExpandedElement()
}
/**
@@ -278,7 +278,7 @@ deprecated class MacroInvocationExpr extends Expr {
MacroInvocation getInvocation() { result.getExpr() = this }
/** Gets the name of the invoked macro. */
string getMacroName() { result = getInvocation().getMacroName() }
string getMacroName() { result = this.getInvocation().getMacroName() }
}
/**
@@ -298,7 +298,7 @@ deprecated class MacroInvocationStmt extends Stmt {
MacroInvocation getInvocation() { result.getStmt() = this }
/** Gets the name of the invoked macro. */
string getMacroName() { result = getInvocation().getMacroName() }
string getMacroName() { result = this.getInvocation().getMacroName() }
}
/** Holds if `l` is the location of a macro. */

View File

@@ -36,7 +36,9 @@ class MemberFunction extends Function {
* `this` parameter.
*/
override int getEffectiveNumberOfParameters() {
if isStatic() then result = getNumberOfParameters() else result = getNumberOfParameters() + 1
if this.isStatic()
then result = this.getNumberOfParameters()
else result = this.getNumberOfParameters() + 1
}
/** Holds if this member is private. */
@@ -49,13 +51,13 @@ class MemberFunction extends Function {
predicate isPublic() { this.hasSpecifier("public") }
/** Holds if this declaration has the lvalue ref-qualifier */
predicate isLValueRefQualified() { hasSpecifier("&") }
predicate isLValueRefQualified() { this.hasSpecifier("&") }
/** Holds if this declaration has the rvalue ref-qualifier */
predicate isRValueRefQualified() { hasSpecifier("&&") }
predicate isRValueRefQualified() { this.hasSpecifier("&&") }
/** Holds if this declaration has a ref-qualifier */
predicate isRefQualified() { isLValueRefQualified() or isRValueRefQualified() }
predicate isRefQualified() { this.isLValueRefQualified() or this.isRValueRefQualified() }
/** Holds if this function overrides that function. */
predicate overrides(MemberFunction that) {
@@ -73,10 +75,10 @@ class MemberFunction extends Function {
* class body.
*/
FunctionDeclarationEntry getClassBodyDeclarationEntry() {
if strictcount(getADeclarationEntry()) = 1
then result = getDefinition()
if strictcount(this.getADeclarationEntry()) = 1
then result = this.getDefinition()
else (
result = getADeclarationEntry() and result != getDefinition()
result = this.getADeclarationEntry() and result != this.getDefinition()
)
}
@@ -198,7 +200,7 @@ class Constructor extends MemberFunction {
* compiler-generated action which initializes a base class or member
* variable.
*/
ConstructorInit getAnInitializer() { result = getInitializer(_) }
ConstructorInit getAnInitializer() { result = this.getInitializer(_) }
/**
* Gets an entry in the constructor's initializer list, or a
@@ -220,8 +222,8 @@ class ImplicitConversionFunction extends MemberFunction {
functions(underlyingElement(this), _, 4)
or
// ConversionConstructor (deprecated)
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and
not hasSpecifier("explicit")
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
not this.hasSpecifier("explicit")
}
/** Gets the type this `ImplicitConversionFunction` takes as input. */
@@ -248,8 +250,8 @@ class ImplicitConversionFunction extends MemberFunction {
*/
deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction {
ConversionConstructor() {
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and
not hasSpecifier("explicit")
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
not this.hasSpecifier("explicit")
}
override string getAPrimaryQlClass() {
@@ -301,15 +303,15 @@ class CopyConstructor extends Constructor {
hasCopySignature(this) and
(
// The rest of the parameters all have default values
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer())
forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
or
// or this is a template class, in which case the default values have
// not been extracted even if they exist. In that case, we assume that
// there are default values present since that is the most common case
// in real-world code.
getDeclaringType() instanceof TemplateClass
this.getDeclaringType() instanceof TemplateClass
) and
not exists(getATemplateArgument())
not exists(this.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "CopyConstructor" }
@@ -325,8 +327,8 @@ class CopyConstructor extends Constructor {
// type-checked for each template instantiation; if an argument in an
// instantiation fails to type-check then the corresponding parameter has
// no default argument in the instantiation.
getDeclaringType() instanceof TemplateClass and
getNumberOfParameters() > 1
this.getDeclaringType() instanceof TemplateClass and
this.getNumberOfParameters() > 1
}
}
@@ -358,15 +360,15 @@ class MoveConstructor extends Constructor {
hasMoveSignature(this) and
(
// The rest of the parameters all have default values
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer())
forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
or
// or this is a template class, in which case the default values have
// not been extracted even if they exist. In that case, we assume that
// there are default values present since that is the most common case
// in real-world code.
getDeclaringType() instanceof TemplateClass
this.getDeclaringType() instanceof TemplateClass
) and
not exists(getATemplateArgument())
not exists(this.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "MoveConstructor" }
@@ -382,8 +384,8 @@ class MoveConstructor extends Constructor {
// type-checked for each template instantiation; if an argument in an
// instantiation fails to type-check then the corresponding parameter has
// no default argument in the instantiation.
getDeclaringType() instanceof TemplateClass and
getNumberOfParameters() > 1
this.getDeclaringType() instanceof TemplateClass and
this.getNumberOfParameters() > 1
}
}
@@ -426,7 +428,7 @@ class Destructor extends MemberFunction {
* Gets a compiler-generated action which destructs a base class or member
* variable.
*/
DestructorDestruction getADestruction() { result = getDestruction(_) }
DestructorDestruction getADestruction() { result = this.getDestruction(_) }
/**
* Gets a compiler-generated action which destructs a base class or member
@@ -475,16 +477,16 @@ class ConversionOperator extends MemberFunction, ImplicitConversionFunction {
*/
class CopyAssignmentOperator extends Operator {
CopyAssignmentOperator() {
hasName("operator=") and
this.hasName("operator=") and
(
hasCopySignature(this)
or
// Unlike CopyConstructor, this member allows a non-reference
// parameter.
getParameter(0).getUnspecifiedType() = getDeclaringType()
this.getParameter(0).getUnspecifiedType() = this.getDeclaringType()
) and
not exists(this.getParameter(1)) and
not exists(getATemplateArgument())
not exists(this.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
@@ -507,10 +509,10 @@ class CopyAssignmentOperator extends Operator {
*/
class MoveAssignmentOperator extends Operator {
MoveAssignmentOperator() {
hasName("operator=") and
this.hasName("operator=") and
hasMoveSignature(this) and
not exists(this.getParameter(1)) and
not exists(getATemplateArgument())
not exists(this.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }

View File

@@ -38,8 +38,8 @@ class Namespace extends NameQualifyingElement, @namespace {
* unless the namespace has exactly one declaration entry.
*/
override Location getLocation() {
if strictcount(getADeclarationEntry()) = 1
then result = getADeclarationEntry().getLocation()
if strictcount(this.getADeclarationEntry()) = 1
then result = this.getADeclarationEntry().getLocation()
else result instanceof UnknownDefaultLocation
}
@@ -50,7 +50,7 @@ class Namespace extends NameQualifyingElement, @namespace {
predicate hasName(string name) { name = this.getName() }
/** Holds if this namespace is anonymous. */
predicate isAnonymous() { hasName("(unnamed namespace)") }
predicate isAnonymous() { this.hasName("(unnamed namespace)") }
/** Gets the name of the parent namespace, if it exists. */
private string getParentName() {
@@ -60,9 +60,9 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Gets the qualified name of this namespace. For example: `a::b`. */
string getQualifiedName() {
if exists(getParentName())
then result = getParentNamespace().getQualifiedName() + "::" + getName()
else result = getName()
if exists(this.getParentName())
then result = this.getParentNamespace().getQualifiedName() + "::" + this.getName()
else result = this.getName()
}
/** Gets the parent namespace, if any. */
@@ -99,7 +99,7 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Gets a version of the `QualifiedName` that is more suitable for display purposes. */
string getFriendlyName() { result = this.getQualifiedName() }
final override string toString() { result = getFriendlyName() }
final override string toString() { result = this.getFriendlyName() }
/** Gets a declaration of (part of) this namespace. */
NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this }

View File

@@ -40,12 +40,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/
override string getName() {
exists(VariableDeclarationEntry vde |
vde = getANamedDeclarationEntry() and result = vde.getName()
vde = this.getANamedDeclarationEntry() and result = vde.getName()
|
vde.isDefinition() or not getANamedDeclarationEntry().isDefinition()
vde.isDefinition() or not this.getANamedDeclarationEntry().isDefinition()
)
or
not exists(getANamedDeclarationEntry()) and
not exists(this.getANamedDeclarationEntry()) and
result = "(unnamed parameter " + this.getIndex().toString() + ")"
}
@@ -58,8 +58,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/
string getTypedName() {
exists(string typeString, string nameString |
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and
(if exists(getName()) then nameString = getName() else nameString = "") and
(
if exists(this.getType().getName())
then typeString = this.getType().getName()
else typeString = ""
) and
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
(
if typeString != "" and nameString != ""
then result = typeString + " " + nameString
@@ -69,7 +73,7 @@ class Parameter extends LocalScopeVariable, @parameter {
}
private VariableDeclarationEntry getANamedDeclarationEntry() {
result = getAnEffectiveDeclarationEntry() and result.getName() != ""
result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
}
/**
@@ -82,13 +86,13 @@ class Parameter extends LocalScopeVariable, @parameter {
* own).
*/
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
if getFunction().isConstructedFrom(_)
if this.getFunction().isConstructedFrom(_)
then
exists(Function prototypeInstantiation |
prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
getFunction().isConstructedFrom(prototypeInstantiation)
prototypeInstantiation.getParameter(this.getIndex()) = result.getVariable() and
this.getFunction().isConstructedFrom(prototypeInstantiation)
)
else result = getADeclarationEntry()
else result = this.getADeclarationEntry()
}
/**
@@ -114,7 +118,7 @@ class Parameter extends LocalScopeVariable, @parameter {
* `getName()` is not "(unnamed parameter i)" (where `i` is the index
* of the parameter).
*/
predicate isNamed() { exists(getANamedDeclarationEntry()) }
predicate isNamed() { exists(this.getANamedDeclarationEntry()) }
/**
* Gets the function to which this parameter belongs, if it is a function
@@ -157,9 +161,9 @@ class Parameter extends LocalScopeVariable, @parameter {
*/
override Location getLocation() {
exists(VariableDeclarationEntry vde |
vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation()
vde = this.getAnEffectiveDeclarationEntry() and result = vde.getLocation()
|
vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition()
vde.isDefinition() or not this.getAnEffectiveDeclarationEntry().isDefinition()
)
}
}

View File

@@ -29,8 +29,8 @@ class PreprocessorDirective extends Locatable, @preprocdirect {
PreprocessorBranch getAGuard() {
exists(PreprocessorEndif e, int line |
result.getEndIf() = e and
e.getFile() = getFile() and
result.getFile() = getFile() and
e.getFile() = this.getFile() and
result.getFile() = this.getFile() and
line = this.getLocation().getStartLine() and
result.getLocation().getStartLine() < line and
line < e.getLocation().getEndLine()
@@ -69,7 +69,9 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
* directives in different translation units, then there can be more than
* one result.
*/
PreprocessorEndif getEndIf() { preprocpair(unresolveElement(getIf()), unresolveElement(result)) }
PreprocessorEndif getEndIf() {
preprocpair(unresolveElement(this.getIf()), unresolveElement(result))
}
/**
* Gets the next `#elif`, `#else` or `#endif` matching this branching
@@ -137,7 +139,7 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
* which evaluated it, or was not taken by any translation unit which
* evaluated it.
*/
predicate wasPredictable() { not (wasTaken() and wasNotTaken()) }
predicate wasPredictable() { not (this.wasTaken() and this.wasNotTaken()) }
}
/**
@@ -268,7 +270,7 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
/**
* Gets the name of the macro that is undefined.
*/
string getName() { result = getHead() }
string getName() { result = this.getHead() }
}
/**

View File

@@ -105,8 +105,8 @@ private class DumpType extends Type {
// for a `SpecifiedType`, insert the qualifiers after
// `getDeclaratorSuffixBeforeQualifiers()`.
result =
getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() +
getDeclaratorSuffix()
this.getTypeSpecifier() + this.getDeclaratorPrefix() +
this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
}
/**
@@ -147,29 +147,35 @@ private class DumpType extends Type {
}
private class BuiltInDumpType extends DumpType, BuiltInType {
override string getTypeSpecifier() { result = toString() }
override string getTypeSpecifier() { result = this.toString() }
}
private class IntegralDumpType extends BuiltInDumpType, IntegralType {
override string getTypeSpecifier() { result = getCanonicalArithmeticType().toString() }
override string getTypeSpecifier() { result = this.getCanonicalArithmeticType().toString() }
}
private class DerivedDumpType extends DumpType, DerivedType {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorSuffixBeforeQualifiers() {
result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
}
private class DecltypeDumpType extends DumpType, Decltype {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() }
override string getDeclaratorPrefix() {
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
}
private class PointerIshDumpType extends DerivedDumpType {
@@ -180,10 +186,10 @@ private class PointerIshDumpType extends DerivedDumpType {
override string getDeclaratorPrefix() {
exists(string declarator |
result = getBaseType().(DumpType).getDeclaratorPrefix() + declarator and
if getBaseType().getUnspecifiedType() instanceof ArrayType
then declarator = "(" + getDeclaratorToken() + ")"
else declarator = getDeclaratorToken()
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + declarator and
if this.getBaseType().getUnspecifiedType() instanceof ArrayType
then declarator = "(" + this.getDeclaratorToken() + ")"
else declarator = this.getDeclaratorToken()
)
}
@@ -206,13 +212,13 @@ private class RValueReferenceDumpType extends PointerIshDumpType, RValueReferenc
}
private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() {
exists(string declarator, string parenDeclarator, Type baseType |
declarator = getClass().(DumpType).getTypeIdentityString() + "::*" and
result = getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and
baseType = getBaseType().getUnspecifiedType() and
declarator = this.getClass().(DumpType).getTypeIdentityString() + "::*" and
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and
baseType = this.getBaseType().getUnspecifiedType() and
if baseType instanceof ArrayType or baseType instanceof RoutineType
then parenDeclarator = "(" + declarator
else parenDeclarator = declarator
@@ -221,38 +227,44 @@ private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
override string getDeclaratorSuffixBeforeQualifiers() {
exists(Type baseType |
baseType = getBaseType().getUnspecifiedType() and
baseType = this.getBaseType().getUnspecifiedType() and
if baseType instanceof ArrayType or baseType instanceof RoutineType
then result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
then result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
)
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
}
private class ArrayDumpType extends DerivedDumpType, ArrayType {
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() }
override string getDeclaratorPrefix() {
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
}
override string getDeclaratorSuffixBeforeQualifiers() {
if exists(getArraySize())
if exists(this.getArraySize())
then
result =
"[" + getArraySize().toString() + "]" +
getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
"[" + this.getArraySize().toString() + "]" +
this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = "[]" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
}
}
private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointerIshType {
override string getDeclaratorSuffixBeforeQualifiers() {
result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
override string getDeclaratorPrefix() {
result = getBaseType().(DumpType).getDeclaratorPrefix() + "(" + getDeclaratorToken()
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + "(" + this.getDeclaratorToken()
}
/**
@@ -274,10 +286,10 @@ private class BlockDumpType extends FunctionPointerIshDumpType, BlockType {
}
private class RoutineDumpType extends DumpType, RoutineType {
override string getTypeSpecifier() { result = getReturnType().(DumpType).getTypeSpecifier() }
override string getTypeSpecifier() { result = this.getReturnType().(DumpType).getTypeSpecifier() }
override string getDeclaratorPrefix() {
result = getReturnType().(DumpType).getDeclaratorPrefix()
result = this.getReturnType().(DumpType).getDeclaratorPrefix()
}
language[monotonicAggregates]
@@ -285,39 +297,41 @@ private class RoutineDumpType extends DumpType, RoutineType {
result =
"(" +
concat(int i |
exists(getParameterType(i))
exists(this.getParameterType(i))
|
getParameterTypeString(getParameterType(i)), ", " order by i
getParameterTypeString(this.getParameterType(i)), ", " order by i
) + ")"
}
override string getDeclaratorSuffix() {
result =
getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getReturnType().(DumpType).getDeclaratorSuffix()
this.getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
this.getReturnType().(DumpType).getDeclaratorSuffix()
}
}
private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType {
override string getDeclaratorPrefix() {
exists(string basePrefix |
basePrefix = getBaseType().(DumpType).getDeclaratorPrefix() and
if getBaseType().getUnspecifiedType() instanceof RoutineType
basePrefix = this.getBaseType().(DumpType).getDeclaratorPrefix() and
if this.getBaseType().getUnspecifiedType() instanceof RoutineType
then result = basePrefix
else result = basePrefix + " " + getSpecifierString()
else result = basePrefix + " " + this.getSpecifierString()
)
}
override string getDeclaratorSuffixBeforeQualifiers() {
exists(string baseSuffix |
baseSuffix = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and
if getBaseType().getUnspecifiedType() instanceof RoutineType
then result = baseSuffix + " " + getSpecifierString()
baseSuffix = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and
if this.getBaseType().getUnspecifiedType() instanceof RoutineType
then result = baseSuffix + " " + this.getSpecifierString()
else result = baseSuffix
)
}
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
override string getDeclaratorSuffix() {
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
}
}
private class UserDumpType extends DumpType, DumpDeclaration, UserType {
@@ -330,18 +344,18 @@ private class UserDumpType extends DumpType, DumpDeclaration, UserType {
// "lambda [] type at line 12, col. 40"
// Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names
// from different compilation units.
simpleName = "(" + min(getSimpleName()) + ")"
else simpleName = getSimpleName()
simpleName = "(" + min(this.getSimpleName()) + ")"
else simpleName = this.getSimpleName()
) and
result = getScopePrefix(this) + simpleName + getTemplateArgumentsString()
result = getScopePrefix(this) + simpleName + this.getTemplateArgumentsString()
)
}
override string getTypeSpecifier() { result = getIdentityString() }
override string getTypeSpecifier() { result = this.getIdentityString() }
}
private class DumpProxyClass extends UserDumpType, ProxyClass {
override string getIdentityString() { result = getName() }
override string getIdentityString() { result = this.getName() }
}
private class DumpVariable extends DumpDeclaration, Variable {
@@ -360,9 +374,9 @@ private class DumpVariable extends DumpDeclaration, Variable {
private class DumpFunction extends DumpDeclaration, Function {
override string getIdentityString() {
result =
getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " +
getScopePrefix(this) + getName() + getTemplateArgumentsString() +
getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix()
this.getType().(DumpType).getTypeSpecifier() + this.getType().(DumpType).getDeclaratorPrefix()
+ " " + getScopePrefix(this) + this.getName() + this.getTemplateArgumentsString() +
this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
}
language[monotonicAggregates]
@@ -370,28 +384,29 @@ private class DumpFunction extends DumpDeclaration, Function {
result =
"(" +
concat(int i |
exists(getParameter(i).getType())
exists(this.getParameter(i).getType())
|
getParameterTypeString(getParameter(i).getType()), ", " order by i
) + ")" + getQualifierString()
getParameterTypeString(this.getParameter(i).getType()), ", " order by i
) + ")" + this.getQualifierString()
}
private string getQualifierString() {
if exists(getACVQualifier())
if exists(this.getACVQualifier())
then
result = " " + strictconcat(string qualifier | qualifier = getACVQualifier() | qualifier, " ")
result =
" " + strictconcat(string qualifier | qualifier = this.getACVQualifier() | qualifier, " ")
else result = ""
}
private string getACVQualifier() {
result = getASpecifier().getName() and
result = this.getASpecifier().getName() and
result = ["const", "volatile"]
}
private string getDeclaratorSuffix() {
result =
getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getType().(DumpType).getDeclaratorSuffix()
this.getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
this.getType().(DumpType).getDeclaratorSuffix()
}
}

View File

@@ -31,11 +31,7 @@ class Specifier extends Element, @specifier {
* A C/C++ function specifier: `inline`, `virtual`, or `explicit`.
*/
class FunctionSpecifier extends Specifier {
FunctionSpecifier() {
this.hasName("inline") or
this.hasName("virtual") or
this.hasName("explicit")
}
FunctionSpecifier() { this.hasName(["inline", "virtual", "explicit"]) }
override string getAPrimaryQlClass() { result = "FunctionSpecifier" }
}
@@ -45,13 +41,7 @@ class FunctionSpecifier extends Specifier {
* or `mutable".
*/
class StorageClassSpecifier extends Specifier {
StorageClassSpecifier() {
this.hasName("auto") or
this.hasName("register") or
this.hasName("static") or
this.hasName("extern") or
this.hasName("mutable")
}
StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
}
@@ -60,11 +50,7 @@ class StorageClassSpecifier extends Specifier {
* A C++ access specifier: `public`, `protected`, or `private`.
*/
class AccessSpecifier extends Specifier {
AccessSpecifier() {
this.hasName("public") or
this.hasName("protected") or
this.hasName("private")
}
AccessSpecifier() { this.hasName(["public", "protected", "private"]) }
/**
* Gets the visibility of a field with access specifier `this` if it is
@@ -140,7 +126,7 @@ class Attribute extends Element, @attribute {
AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i }
/** Gets an argument of the attribute. */
AttributeArgument getAnArgument() { result = getArgument(_) }
AttributeArgument getAnArgument() { result = this.getArgument(_) }
}
/**
@@ -166,7 +152,7 @@ class StdAttribute extends Attribute, @stdattribute {
* Holds if this attribute has the given namespace and name.
*/
predicate hasQualifiedName(string namespace, string name) {
namespace = getNamespace() and hasName(name)
namespace = this.getNamespace() and this.hasName(name)
}
}
@@ -184,7 +170,7 @@ class Declspec extends Attribute, @declspec { }
*/
class MicrosoftAttribute extends Attribute, @msattribute {
AttributeArgument getNamedArgument(string name) {
result = getAnArgument() and result.getName() = name
result = this.getAnArgument() and result.getName() = name
}
}
@@ -212,13 +198,13 @@ class AlignAs extends Attribute, @alignas {
* ```
*/
class FormatAttribute extends GnuAttribute {
FormatAttribute() { getName() = "format" }
FormatAttribute() { this.getName() = "format" }
/**
* Gets the archetype of this format attribute, for example
* `"printf"`.
*/
string getArchetype() { result = getArgument(0).getValueText() }
string getArchetype() { result = this.getArgument(0).getValueText() }
/**
* Gets the index in (1-based) format attribute notation associated
@@ -236,7 +222,7 @@ class FormatAttribute extends GnuAttribute {
* Gets the (0-based) index of the format string,
* according to this attribute.
*/
int getFormatIndex() { result = getArgument(1).getValueInt() - firstArgumentNumber() }
int getFormatIndex() { result = this.getArgument(1).getValueInt() - this.firstArgumentNumber() }
/**
* Gets the (0-based) index of the first format argument (if any),
@@ -244,8 +230,8 @@ class FormatAttribute extends GnuAttribute {
*/
int getFirstFormatArgIndex() {
exists(int val |
val = getArgument(2).getValueInt() and
result = val - firstArgumentNumber() and
val = this.getArgument(2).getValueInt() and
result = val - this.firstArgumentNumber() and
not val = 0 // indicates a `vprintf` style format function with arguments not directly available.
)
}
@@ -277,7 +263,7 @@ class AttributeArgument extends Element, @attribute_arg {
/**
* Gets the value of this argument, if its value is integral.
*/
int getValueInt() { result = getValueText().toInt() }
int getValueInt() { result = this.getValueText().toInt() }
/**
* Gets the value of this argument, if its value is a type.
@@ -304,11 +290,11 @@ class AttributeArgument extends Element, @attribute_arg {
then result = "empty argument"
else
exists(string prefix, string tail |
(if exists(getName()) then prefix = getName() + "=" else prefix = "") and
(if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and
(
if exists(@attribute_arg_type self | self = underlyingElement(this))
then tail = getValueType().getName()
else tail = getValueText()
then tail = this.getValueType().getName()
else tail = this.getValueText()
) and
result = prefix + tail
)

View File

@@ -41,7 +41,7 @@ class Struct extends Class {
* ```
*/
class LocalStruct extends Struct {
LocalStruct() { isLocal() }
LocalStruct() { this.isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" }
}

View File

@@ -10,8 +10,8 @@ import semmle.code.cpp.File
*/
private class GoogleTestHeader extends File {
GoogleTestHeader() {
getBaseName() = "gtest.h" and
getParentContainer().getBaseName() = "gtest"
this.getBaseName() = "gtest.h" and
this.getParentContainer().getBaseName() = "gtest"
}
}
@@ -30,8 +30,8 @@ private class GoogleTest extends MacroInvocation {
*/
private class BoostTestFolder extends Folder {
BoostTestFolder() {
getBaseName() = "test" and
getParentContainer().getBaseName() = "boost"
this.getBaseName() = "test" and
this.getParentContainer().getBaseName() = "boost"
}
}
@@ -49,7 +49,7 @@ private class BoostTest extends MacroInvocation {
* The `cppunit` directory.
*/
private class CppUnitFolder extends Folder {
CppUnitFolder() { getBaseName() = "cppunit" }
CppUnitFolder() { this.getBaseName() = "cppunit" }
}
/**
@@ -57,8 +57,8 @@ private class CppUnitFolder extends Folder {
*/
private class CppUnitClass extends Class {
CppUnitClass() {
getFile().getParentContainer+() instanceof CppUnitFolder and
getNamespace().getParentNamespace*().getName() = "CppUnit"
this.getFile().getParentContainer+() instanceof CppUnitFolder and
this.getNamespace().getParentNamespace*().getName() = "CppUnit"
}
}

View File

@@ -81,7 +81,7 @@ class Type extends Locatable, @type {
* Holds if this type refers to type `t` (by default,
* a type always refers to itself).
*/
predicate refersTo(Type t) { refersToDirectly*(t) }
predicate refersTo(Type t) { this.refersToDirectly*(t) }
/**
* Holds if this type refers to type `t` directly.
@@ -1080,11 +1080,11 @@ class DerivedType extends Type, @derivedtype {
override predicate refersToDirectly(Type t) { t = this.getBaseType() }
override predicate involvesReference() { getBaseType().involvesReference() }
override predicate involvesReference() { this.getBaseType().involvesReference() }
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override Type stripType() { result = getBaseType().stripType() }
override Type stripType() { result = this.getBaseType().stripType() }
/**
* Holds if this type has the `__autoreleasing` specifier or if it points to
@@ -1165,33 +1165,35 @@ class Decltype extends Type, @decltype {
*/
predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) }
override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() }
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
override Type stripType() { result = getBaseType().stripType() }
override Type stripType() { result = this.getBaseType().stripType() }
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() }
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
override Location getLocation() { result = getExpr().getLocation() }
override Location getLocation() { result = this.getExpr().getLocation() }
override string toString() { result = "decltype(...)" }
override string getName() { none() }
override int getSize() { result = getBaseType().getSize() }
override int getSize() { result = this.getBaseType().getSize() }
override int getAlignment() { result = getBaseType().getAlignment() }
override int getAlignment() { result = this.getBaseType().getAlignment() }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() {
result = "decltype resulting in {" + this.getBaseType().explain() + "}"
}
override predicate involvesReference() { getBaseType().involvesReference() }
override predicate involvesReference() { this.getBaseType().involvesReference() }
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() }
@@ -1223,7 +1225,7 @@ class PointerType extends DerivedType {
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
override Type resolveTypedefs() {
result.(PointerType).getBaseType() = getBaseType().resolveTypedefs()
result.(PointerType).getBaseType() = this.getBaseType().resolveTypedefs()
}
}
@@ -1240,7 +1242,9 @@ class ReferenceType extends DerivedType {
override string getAPrimaryQlClass() { result = "ReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" }
@@ -1251,7 +1255,7 @@ class ReferenceType extends DerivedType {
override predicate involvesReference() { any() }
override Type resolveTypedefs() {
result.(ReferenceType).getBaseType() = getBaseType().resolveTypedefs()
result.(ReferenceType).getBaseType() = this.getBaseType().resolveTypedefs()
}
}
@@ -1330,11 +1334,11 @@ class SpecifiedType extends DerivedType {
}
override Type resolveTypedefs() {
result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() and
result.getASpecifier() = getASpecifier()
result.(SpecifiedType).getBaseType() = this.getBaseType().resolveTypedefs() and
result.getASpecifier() = this.getASpecifier()
}
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
}
/**
@@ -1433,7 +1437,8 @@ class GNUVectorType extends DerivedType {
override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) }
override string explain() {
result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}"
result =
"GNU " + this.getNumElements() + " element vector of {" + this.getBaseType().explain() + "}"
}
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
@@ -1468,7 +1473,9 @@ class FunctionReferenceType extends FunctionPointerIshType {
override string getAPrimaryQlClass() { result = "FunctionReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
override int getPointerIndirectionLevel() {
result = this.getBaseType().getPointerIndirectionLevel()
}
override string explain() {
result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}"
@@ -1535,8 +1542,8 @@ class FunctionPointerIshType extends DerivedType {
int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) }
override predicate involvesTemplateParameter() {
getReturnType().involvesTemplateParameter() or
getAParameterType().involvesTemplateParameter()
this.getReturnType().involvesTemplateParameter() or
this.getAParameterType().involvesTemplateParameter()
}
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
@@ -1581,7 +1588,7 @@ class PointerToMemberType extends Type, @ptrtomember {
this.getBaseType().explain() + "}"
}
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
}
@@ -1650,7 +1657,6 @@ class RoutineType extends Type, @routinetype {
i = 0 and result = "" and not exists(this.getAParameterType())
or
(
exists(this.getParameterType(i)) and
if i < max(int j | exists(this.getParameterType(j)))
then
// Not the last one
@@ -1671,8 +1677,8 @@ class RoutineType extends Type, @routinetype {
override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type
override predicate involvesTemplateParameter() {
getReturnType().involvesTemplateParameter() or
getAParameterType().involvesTemplateParameter()
this.getReturnType().involvesTemplateParameter() or
this.getAParameterType().involvesTemplateParameter()
}
}

View File

@@ -25,7 +25,7 @@ class TypedefType extends UserType {
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
override int getSize() { result = this.getBaseType().getSize() }
@@ -43,11 +43,11 @@ class TypedefType extends UserType {
result = this.getBaseType().getASpecifier()
}
override predicate involvesReference() { getBaseType().involvesReference() }
override predicate involvesReference() { this.getBaseType().involvesReference() }
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() }
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
override Type stripType() { result = getBaseType().stripType() }
override Type stripType() { result = this.getBaseType().stripType() }
}
/**
@@ -90,7 +90,7 @@ class UsingAliasTypedefType extends TypedefType {
* ```
*/
class LocalTypedefType extends TypedefType {
LocalTypedefType() { isLocal() }
LocalTypedefType() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalTypedefType" }
}

View File

@@ -37,7 +37,7 @@ class Union extends Struct {
* ```
*/
class LocalUnion extends Union {
LocalUnion() { isLocal() }
LocalUnion() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalUnion" }
}

View File

@@ -30,19 +30,19 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* Gets the simple name of this type, without any template parameters. For example
* if the name of the type is `"myType<int>"`, the simple name is just `"myType"`.
*/
string getSimpleName() { result = getName().regexpReplaceAll("<.*", "") }
string getSimpleName() { result = this.getName().regexpReplaceAll("<.*", "") }
override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) }
/** Holds if this type is anonymous. */
predicate isAnonymous() { getName().matches("(unnamed%") }
predicate isAnonymous() { this.getName().matches("(unnamed%") }
override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) }
override Specifier getASpecifier() { result = Type.super.getASpecifier() }
override Location getLocation() {
if hasDefinition()
if this.hasDefinition()
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
@@ -53,16 +53,16 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
}
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
override TypeDeclarationEntry getDefinition() {
result = getADeclarationEntry() and
result = this.getADeclarationEntry() and
result.isDefinition()
}
override Location getDefinitionLocation() {
if exists(getDefinition())
then result = getDefinition().getLocation()
if exists(this.getDefinition())
then result = this.getDefinition().getLocation()
else
exists(Class t |
this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation()
@@ -80,7 +80,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* Holds if this is a local type (that is, a type that has a directly-enclosing
* function).
*/
predicate isLocal() { exists(getEnclosingFunction()) }
predicate isLocal() { exists(this.getEnclosingFunction()) }
/*
* Dummy implementations of inherited methods. This class must not be
@@ -107,9 +107,9 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* ```
*/
class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
override UserType getDeclaration() { result = getType() }
override UserType getDeclaration() { result = this.getType() }
override string getName() { result = getType().getName() }
override string getName() { result = this.getType().getName() }
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }

View File

@@ -104,17 +104,17 @@ class Variable extends Declaration, @variable {
override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this }
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
override VariableDeclarationEntry getDefinition() {
result = getADeclarationEntry() and
result = this.getADeclarationEntry() and
result.isDefinition()
}
override Location getDefinitionLocation() { result = getDefinition().getLocation() }
override Location getDefinitionLocation() { result = this.getDefinition().getLocation() }
override Location getLocation() {
if exists(getDefinition())
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
@@ -199,7 +199,7 @@ class Variable extends Declaration, @variable {
* ```
*/
class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
override Variable getDeclaration() { result = getVariable() }
override Variable getDeclaration() { result = this.getVariable() }
override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" }
@@ -276,32 +276,33 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
int getIndex() { param_decl_bind(underlyingElement(this), result, _) }
private string getAnonymousParameterDescription() {
not exists(getName()) and
not exists(this.getName()) and
exists(string idx |
idx =
((getIndex() + 1).toString() + "th")
((this.getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")
.replaceAll("11st", "11th")
.replaceAll("12nd", "12th")
.replaceAll("13rd", "13th") and
if exists(getCanonicalName())
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
if exists(this.getCanonicalName())
then
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter"
)
}
override string toString() {
isDefinition() and
result = "definition of " + getName()
this.isDefinition() and
result = "definition of " + this.getName()
or
not isDefinition() and
if getName() = getCanonicalName()
then result = "declaration of " + getName()
else result = "declaration of " + getCanonicalName() + " as " + getName()
not this.isDefinition() and
if this.getName() = this.getCanonicalName()
then result = "declaration of " + this.getName()
else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
or
result = getAnonymousParameterDescription()
result = this.getAnonymousParameterDescription()
}
/**
@@ -311,8 +312,12 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
*/
string getTypedName() {
exists(string typeString, string nameString |
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and
(if exists(getName()) then nameString = getName() else nameString = "") and
(
if exists(this.getType().getName())
then typeString = this.getType().getName()
else typeString = ""
) and
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
if typeString != "" and nameString != ""
then result = typeString + " " + nameString
else result = typeString + nameString
@@ -540,7 +545,7 @@ class MemberVariable extends Variable, @membervariable {
}
/** Holds if this member is mutable. */
predicate isMutable() { getADeclarationEntry().hasSpecifier("mutable") }
predicate isMutable() { this.getADeclarationEntry().hasSpecifier("mutable") }
private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) }
}

View File

@@ -24,7 +24,7 @@ class XMLLocatable extends @xmllocatable, TXMLLocatable {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
}
/** Gets the text value contained in this XML parent. */
string getTextValue() { result = allCharactersString() }
string getTextValue() { result = this.allCharactersString() }
/** Gets a printable representation of this XML parent. */
string toString() { result = this.getName() }
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
*
* Gets the path of this XML file.
*/
deprecated string getPath() { result = getAbsolutePath() }
deprecated string getPath() { result = this.getAbsolutePath() }
/**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
*
* Gets the path of the folder that contains this XML file.
*/
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) }
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
*/
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
/** Holds if this XML element has the given `name`. */
predicate hasName(string name) { name = getName() }
predicate hasName(string name) { name = this.getName() }
/** Gets the name of this XML element. */
override string getName() { xmlElements(this, result, _, _, _) }
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
}
/**

View File

@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
* char data[1]; // v
* };
* ```
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
* In addition, if the size of the structure is taken, there must be at least one instance
* where a `c` pointer is allocated with additional space.
* For example, holds for `c` if it occurs as
* ```
* malloc(sizeof(c) + 100 * sizeof(char))
* ```
* but not if it only ever occurs as
* ```
* malloc(sizeof(c))
* ```
* This requires that `v` is an array of size 0 or 1.
*/
predicate memberMayBeVarSize(Class c, MemberVariable v) {
exists(int i |
// `v` is the last field in `c`
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
v = c.getCanonicalMember(i) and
// v is an array of size at most 1
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
not c instanceof Union
) and
// If the size is taken, then arithmetic is performed on the result at least once
(
// `sizeof(c)` is not taken
not exists(SizeofOperator so |
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
)
or
// or `sizeof(c)` is taken
exists(SizeofOperator so |
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
// and arithmetic is performed on the result
so.getParent*() instanceof AddExpr
)
)
c = v.getDeclaringType() and
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
}
/**
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
why = bufferVar and
not memberMayBeVarSize(_, bufferVar) and
not exists(Union bufferType |
bufferType.getAMemberVariable() = why and
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
) and
not result = 0 // zero sized arrays are likely to have special usage, for example
or
// behaving a bit like a 'union' overlapping other fields.
@@ -85,13 +48,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
)
or
exists(Union bufferType |
bufferType.getAMemberVariable() = why and
why = bufferVar and
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
result = bufferType.getSize()
)
)
or
// buffer is a fixed size dynamic allocation

View File

@@ -375,8 +375,8 @@ class Wchar_t extends Type {
class MicrosoftInt8Type extends IntegralType {
MicrosoftInt8Type() {
this instanceof CharType and
not isExplicitlyUnsigned() and
not isExplicitlySigned()
not this.isExplicitlyUnsigned() and
not this.isExplicitlySigned()
}
}
@@ -391,8 +391,8 @@ class MicrosoftInt8Type extends IntegralType {
class MicrosoftInt16Type extends IntegralType {
MicrosoftInt16Type() {
this instanceof ShortType and
not isExplicitlyUnsigned() and
not isExplicitlySigned()
not this.isExplicitlyUnsigned() and
not this.isExplicitlySigned()
}
}
@@ -407,8 +407,8 @@ class MicrosoftInt16Type extends IntegralType {
class MicrosoftInt32Type extends IntegralType {
MicrosoftInt32Type() {
this instanceof IntType and
not isExplicitlyUnsigned() and
not isExplicitlySigned()
not this.isExplicitlyUnsigned() and
not this.isExplicitlySigned()
}
}
@@ -423,8 +423,8 @@ class MicrosoftInt32Type extends IntegralType {
class MicrosoftInt64Type extends IntegralType {
MicrosoftInt64Type() {
this instanceof LongLongType and
not isExplicitlyUnsigned() and
not isExplicitlySigned()
not this.isExplicitlyUnsigned() and
not this.isExplicitlySigned()
}
}

View File

@@ -33,7 +33,7 @@ DependencyOptions getDependencyOptions() { any() }
class DependsSource extends Element {
DependsSource() {
// not inside a template instantiation
not exists(Element other | isFromTemplateInstantiation(other)) or
not exists(Element other | this.isFromTemplateInstantiation(other)) or
// allow DeclarationEntrys of template specializations
this.(DeclarationEntry).getDeclaration().(Function).isConstructedFrom(_) or
this.(DeclarationEntry).getDeclaration().(Class).isConstructedFrom(_)

View File

@@ -1,6 +1,7 @@
import cpp
private import semmle.code.cpp.models.interfaces.ArrayFunction
private import semmle.code.cpp.models.implementations.Strcat
import semmle.code.cpp.dataflow.DataFlow
private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) {
exists(StackVariable v0, Expr val |
@@ -45,22 +46,28 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) {
ae.getRValue().getAChild*() = va
)
or
// Function call: library function, varargs function, function
// containing assembler code, or function where the relevant
// parameter is potentially added a null terminator.
// Function calls...
exists(Call c, Function f, int i |
e = c and
f = c.getTarget() and
not functionArgumentMustBeNullTerminated(f, i) and
c.getAnArgumentSubExpr(i) = va
|
not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i)
// library function
not f.hasEntryPoint()
or
// function where the relevant parameter is potentially added a null terminator
mayAddNullTerminator(_, f.getParameter(i).getAnAccess())
or
// varargs function
f.isVarargs() and i >= f.getNumberOfParameters()
or
// function containing assembler code
exists(AsmStmt s | s.getEnclosingFunction() = f)
or
// function where the relevant parameter is returned (leaking it to be potentially null terminated elsewhere)
DataFlow::localFlow(DataFlow::parameterNode(f.getParameter(i)),
DataFlow::exprNode(any(ReturnStmt rs).getExpr()))
)
or
// Call without target (e.g., function pointer call)

View File

@@ -8,7 +8,7 @@ import semmle.code.cpp.commons.StringAnalysis
import semmle.code.cpp.models.interfaces.FormattingFunction
class PrintfFormatAttribute extends FormatAttribute {
PrintfFormatAttribute() { getArchetype() = ["printf", "__printf__"] }
PrintfFormatAttribute() { this.getArchetype() = ["printf", "__printf__"] }
}
/**
@@ -20,13 +20,13 @@ class AttributeFormattingFunction extends FormattingFunction {
AttributeFormattingFunction() {
exists(PrintfFormatAttribute printf_attrib |
printf_attrib = getAnAttribute() and
printf_attrib = this.getAnAttribute() and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
)
}
override int getFormatParameterIndex() {
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() |
forex(PrintfFormatAttribute printf_attrib | printf_attrib = this.getAnAttribute() |
result = printf_attrib.getFormatIndex()
)
}
@@ -132,7 +132,7 @@ deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
class UserDefinedFormattingFunction extends FormattingFunction {
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _, _, _) }
UserDefinedFormattingFunction() { this.isVarargs() and callsVariadicFormatter(this, _, _, _) }
override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) }
@@ -191,7 +191,7 @@ class FormattingFunctionCall extends Expr {
exists(int i |
result = this.getArgument(i) and
n >= 0 and
n = i - getTarget().(FormattingFunction).getFirstFormatArgumentIndex()
n = i - this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex()
)
}
@@ -251,7 +251,22 @@ class FormattingFunctionCall extends Expr {
int getNumFormatArgument() {
result = count(this.getFormatArgument(_)) and
// format arguments must be known
exists(getTarget().(FormattingFunction).getFirstFormatArgumentIndex())
exists(this.getTarget().(FormattingFunction).getFirstFormatArgumentIndex())
}
/**
* Gets the argument, if any, to which the output is written. If `isStream` is
* `true`, the output argument is a stream (that is, this call behaves like
* `fprintf`). If `isStream` is `false`, the output argument is a buffer (that
* is, this call behaves like `sprintf`)
*/
Expr getOutputArgument(boolean isStream) {
result =
this.(Call)
.getArgument(this.(Call)
.getTarget()
.(FormattingFunction)
.getOutputParameterIndex(isStream))
}
}
@@ -275,7 +290,7 @@ class FormatLiteral extends Literal {
* DEPRECATED: Use getDefaultCharType() instead.
*/
deprecated predicate isWideCharDefault() {
getUse().getTarget().(FormattingFunction).isWideCharDefault()
this.getUse().getTarget().(FormattingFunction).isWideCharDefault()
}
/**
@@ -283,7 +298,7 @@ class FormatLiteral extends Literal {
* `char` or `wchar_t`.
*/
Type getDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getDefaultCharType()
result = this.getUse().getTarget().(FormattingFunction).getDefaultCharType()
}
/**
@@ -292,7 +307,7 @@ class FormatLiteral extends Literal {
* which is correct for a particular function.
*/
Type getNonDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getNonDefaultCharType()
result = this.getUse().getTarget().(FormattingFunction).getNonDefaultCharType()
}
/**
@@ -300,7 +315,9 @@ class FormatLiteral extends Literal {
* snapshots there may be multiple results where we can't tell which is correct for a
* particular function.
*/
Type getWideCharType() { result = getUse().getTarget().(FormattingFunction).getWideCharType() }
Type getWideCharType() {
result = this.getUse().getTarget().(FormattingFunction).getWideCharType()
}
/**
* Holds if this `FormatLiteral` is in a context that supports
@@ -338,7 +355,7 @@ class FormatLiteral extends Literal {
}
private string getFlagRegexp() {
if isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*"
if this.isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*"
}
private string getFieldWidthRegexp() { result = "(?:[1-9][0-9]*|\\*|\\*[0-9]+\\$)?" }
@@ -346,13 +363,13 @@ class FormatLiteral extends Literal {
private string getPrecRegexp() { result = "(?:\\.(?:[0-9]*|\\*|\\*[0-9]+\\$))?" }
private string getLengthRegexp() {
if isMicrosoft()
if this.isMicrosoft()
then result = "(?:hh?|ll?|L|q|j|z|t|w|I32|I64|I)?"
else result = "(?:hh?|ll?|L|q|j|z|Z|t)?"
}
private string getConvCharRegexp() {
if isMicrosoft()
if this.isMicrosoft()
then result = "[aAcCdeEfFgGimnopsSuxXZ@]"
else result = "[aAcCdeEfFgGimnopsSuxX@]"
}
@@ -732,16 +749,16 @@ class FormatLiteral extends Literal {
* Gets the argument type required by the nth conversion specifier.
*/
Type getConversionType(int n) {
result = getConversionType1(n) or
result = getConversionType1b(n) or
result = getConversionType2(n) or
result = getConversionType3(n) or
result = getConversionType4(n) or
result = getConversionType6(n) or
result = getConversionType7(n) or
result = getConversionType8(n) or
result = getConversionType9(n) or
result = getConversionType10(n)
result = this.getConversionType1(n) or
result = this.getConversionType1b(n) or
result = this.getConversionType2(n) or
result = this.getConversionType3(n) or
result = this.getConversionType4(n) or
result = this.getConversionType6(n) or
result = this.getConversionType7(n) or
result = this.getConversionType8(n) or
result = this.getConversionType9(n) or
result = this.getConversionType10(n)
}
private Type getConversionType1(int n) {
@@ -771,15 +788,15 @@ class FormatLiteral extends Literal {
or
conv = ["c", "C"] and
len = ["l", "w"] and
result = getWideCharType()
result = this.getWideCharType()
or
conv = "c" and
(len != "l" and len != "w" and len != "h") and
result = getDefaultCharType()
result = this.getDefaultCharType()
or
conv = "C" and
(len != "l" and len != "w" and len != "h") and
result = getNonDefaultCharType()
result = this.getNonDefaultCharType()
)
)
}
@@ -816,15 +833,15 @@ class FormatLiteral extends Literal {
or
conv = ["s", "S"] and
len = ["l", "w"] and
result.(PointerType).getBaseType() = getWideCharType()
result.(PointerType).getBaseType() = this.getWideCharType()
or
conv = "s" and
(len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getDefaultCharType()
result.(PointerType).getBaseType() = this.getDefaultCharType()
or
conv = "S" and
(len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getNonDefaultCharType()
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
)
)
}
@@ -879,19 +896,19 @@ class FormatLiteral extends Literal {
exists(string len, string conv |
this.parseConvSpec(n, _, _, _, _, _, len, conv) and
(len != "l" and len != "w" and len != "h") and
getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function
this.getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function
(
conv = "c" and
result = getNonDefaultCharType()
result = this.getNonDefaultCharType()
or
conv = "C" and
result = getDefaultCharType()
result = this.getDefaultCharType()
or
conv = "s" and
result.(PointerType).getBaseType() = getNonDefaultCharType()
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
or
conv = "S" and
result.(PointerType).getBaseType() = getDefaultCharType()
result.(PointerType).getBaseType() = this.getDefaultCharType()
)
)
}
@@ -924,9 +941,13 @@ class FormatLiteral extends Literal {
* not account for positional arguments (`$`).
*/
int getFormatArgumentIndexFor(int n, int mode) {
hasFormatArgumentIndexFor(n, mode) and
this.hasFormatArgumentIndexFor(n, mode) and
(3 * n) + mode =
rank[result + 1](int n2, int mode2 | hasFormatArgumentIndexFor(n2, mode2) | (3 * n2) + mode2)
rank[result + 1](int n2, int mode2 |
this.hasFormatArgumentIndexFor(n2, mode2)
|
(3 * n2) + mode2
)
}
/**
@@ -936,7 +957,7 @@ class FormatLiteral extends Literal {
int getNumArgNeeded(int n) {
exists(this.getConvSpecOffset(n)) and
exists(this.getConversionChar(n)) and
result = count(int mode | hasFormatArgumentIndexFor(n, mode))
result = count(int mode | this.hasFormatArgumentIndexFor(n, mode))
}
/**
@@ -948,7 +969,7 @@ class FormatLiteral extends Literal {
// At least one conversion specifier has a parameter field, in which case,
// they all should have.
result = max(string s | this.getParameterField(_) = s + "$" | s.toInt())
else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode))
else result = count(int n, int mode | this.hasFormatArgumentIndexFor(n, mode))
}
/**
@@ -1038,10 +1059,10 @@ class FormatLiteral extends Literal {
exists(int sizeBits |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
bits = this.getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
t.isSigned() and bits = t.getSize() * 8
)
@@ -1056,10 +1077,10 @@ class FormatLiteral extends Literal {
exists(int sizeBits |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
bits = this.getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
t.isUnsigned() and bits = t.getSize() * 8
)
@@ -1074,26 +1095,26 @@ class FormatLiteral extends Literal {
exists(int sizeBytes, int baseLen |
sizeBytes =
min(int bytes |
bytes = getIntegralDisplayType(n).getSize()
bytes = this.getIntegralDisplayType(n).getSize()
or
exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
t.isUnsigned() and bytes = t.getSize()
)
) and
baseLen = sizeBytes * 2 and
(
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
)
)
or
this.getConversionChar(n).toLowerCase() = "p" and
exists(PointerType ptrType, int baseLen |
ptrType = getFullyConverted().getType() and
ptrType = this.getFullyConverted().getType() and
baseLen = max(ptrType.getSize() * 2) and // e.g. "0x1234567812345678"; exact format is platform dependent
(
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
)
)
or
@@ -1102,17 +1123,17 @@ class FormatLiteral extends Literal {
exists(int sizeBits, int baseLen |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
bits = this.getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
t.isUnsigned() and bits = t.getSize() * 8
)
) and
baseLen = (sizeBits / 3.0).ceil() and
(
if hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
if this.hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
)
)
or
@@ -1135,8 +1156,8 @@ class FormatLiteral extends Literal {
*/
int getMaxConvertedLengthLimited(int n) {
if this.getConversionChar(n).toLowerCase() = "f"
then result = getMaxConvertedLength(n).minimum(8)
else result = getMaxConvertedLength(n)
then result = this.getMaxConvertedLength(n).minimum(8)
else result = this.getMaxConvertedLength(n)
}
/**

View File

@@ -24,7 +24,7 @@ abstract class ScanfFunction extends Function {
* Holds if the default meaning of `%s` is a `wchar_t*` string
* (rather than a `char*`).
*/
predicate isWideCharDefault() { exists(getName().indexOf("wscanf")) }
predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) }
}
/**
@@ -34,10 +34,10 @@ class Scanf extends ScanfFunction {
Scanf() {
this instanceof TopLevelFunction and
(
hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
this.hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
)
}
@@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction {
Fscanf() {
this instanceof TopLevelFunction and
(
hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
this.hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
)
}
@@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction {
Sscanf() {
this instanceof TopLevelFunction and
(
hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
this.hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
)
}
@@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction {
Snscanf() {
this instanceof TopLevelFunction and
(
hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
this.hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
this.hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
this.hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
this.hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
// note that the max_amount is not a limit on the output length, it's an input length
// limit used with non null-terminated strings.
)
@@ -120,18 +120,18 @@ class ScanfFunctionCall extends FunctionCall {
/**
* Gets the `scanf`-like function that is called.
*/
ScanfFunction getScanfFunction() { result = getTarget() }
ScanfFunction getScanfFunction() { result = this.getTarget() }
/**
* Gets the position at which the input string or stream parameter occurs,
* if this function call does not read from standard input.
*/
int getInputParameterIndex() { result = getScanfFunction().getInputParameterIndex() }
int getInputParameterIndex() { result = this.getScanfFunction().getInputParameterIndex() }
/**
* Gets the position at which the format parameter occurs.
*/
int getFormatParameterIndex() { result = getScanfFunction().getFormatParameterIndex() }
int getFormatParameterIndex() { result = this.getScanfFunction().getFormatParameterIndex() }
/**
* Gets the format expression used in this call.
@@ -142,7 +142,7 @@ class ScanfFunctionCall extends FunctionCall {
* Holds if the default meaning of `%s` is a `wchar_t*` string
* (rather than a `char*`).
*/
predicate isWideCharDefault() { getScanfFunction().isWideCharDefault() }
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
}
/**
@@ -158,7 +158,7 @@ class ScanfFormatLiteral extends Expr {
ScanfFunctionCall getUse() { result.getFormat() = this }
/** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */
predicate isWideCharDefault() { getUse().getTarget().(ScanfFunction).isWideCharDefault() }
predicate isWideCharDefault() { this.getUse().getTarget().(ScanfFunction).isWideCharDefault() }
/**
* Gets the format string itself, transformed as follows:

View File

@@ -40,8 +40,8 @@ abstract class MutexType extends Type {
* Gets a call that locks or tries to lock any mutex of this type.
*/
FunctionCall getLockAccess() {
result = getMustlockAccess() or
result = getTrylockAccess()
result = this.getMustlockAccess() or
result = this.getTrylockAccess()
}
/**
@@ -63,22 +63,22 @@ abstract class MutexType extends Type {
/**
* DEPRECATED: use mustlockAccess(fc, arg) instead.
*/
deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() }
deprecated Function getMustlockFunction() { result = this.getMustlockAccess().getTarget() }
/**
* DEPRECATED: use trylockAccess(fc, arg) instead.
*/
deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() }
deprecated Function getTrylockFunction() { result = this.getTrylockAccess().getTarget() }
/**
* DEPRECATED: use lockAccess(fc, arg) instead.
*/
deprecated Function getLockFunction() { result = getLockAccess().getTarget() }
deprecated Function getLockFunction() { result = this.getLockAccess().getTarget() }
/**
* DEPRECATED: use unlockAccess(fc, arg) instead.
*/
deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() }
deprecated Function getUnlockFunction() { result = this.getUnlockAccess().getTarget() }
}
/**
@@ -155,17 +155,17 @@ class DefaultMutexType extends MutexType {
override predicate mustlockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = mustlockCandidate() and
lockArgType(fc, arg)
this.lockArgType(fc, arg)
}
override predicate trylockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = trylockCandidate() and
lockArgType(fc, arg)
this.lockArgType(fc, arg)
}
override predicate unlockAccess(FunctionCall fc, Expr arg) {
fc.getTarget() = unlockCandidate() and
lockArgType(fc, arg)
this.lockArgType(fc, arg)
}
}

View File

@@ -194,14 +194,14 @@ class BasicBlock extends ControlFlowNodeBase {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*
* Yields no result if this basic block spans multiple source files.
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn)
this.hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn)
}
pragma[noinline]
@@ -276,7 +276,7 @@ class EntryBasicBlock extends BasicBlock {
*/
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() {
getEnd() instanceof Function or
aborting(getEnd())
this.getEnd() instanceof Function or
aborting(this.getEnd())
}
}

View File

@@ -66,7 +66,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
*/
ControlFlowNode getATrueSuccessor() {
qlCFGTrueSuccessor(this, result) and
result = getASuccessor()
result = this.getASuccessor()
}
/**
@@ -75,7 +75,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
*/
ControlFlowNode getAFalseSuccessor() {
qlCFGFalseSuccessor(this, result) and
result = getASuccessor()
result = this.getASuccessor()
}
/** Gets the `BasicBlock` containing this control-flow node. */

View File

@@ -121,7 +121,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
@@ -135,7 +135,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
exists(boolean testIsTrue |
comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
)
}
}
@@ -147,27 +147,29 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
GuardConditionFromShortCircuitNot() {
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and
exists(IRGuardCondition ir | getOperand() = ir.getAST())
exists(IRGuardCondition ir | this.getOperand() = ir.getAST())
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
}
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
getOperand().(GuardCondition).comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
this.getOperand()
.(GuardCondition)
.comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
}
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
}
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
}
}
@@ -303,9 +305,9 @@ class IRGuardCondition extends Instruction {
cached
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
pred.getASuccessor() = succ and
controls(pred, testIsTrue)
this.controls(pred, testIsTrue)
or
succ = getBranchSuccessor(testIsTrue) and
succ = this.getBranchSuccessor(testIsTrue) and
branch.getCondition() = this and
branch.getBlock() = pred
}

View File

@@ -73,19 +73,19 @@ abstract deprecated class LocalScopeVariableReachability extends string {
*/
exists(BasicBlock bb, int i |
isSource(source, v) and
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
this.isSink(sink, v) and
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
)
or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _)
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
this.bbSuccessorEntryReaches(bb, v, sink, _)
)
}
@@ -97,11 +97,11 @@ abstract deprecated class LocalScopeVariableReachability extends string {
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
bbEntryReachesLocally(succ, v, node) and
this.bbEntryReachesLocally(succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
not this.isBarrier(succ.getNode(_), v) and
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
@@ -110,7 +110,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
) {
exists(int n |
node = bb.getNode(n) and
isSink(node, v)
this.isSink(node, v)
|
not exists(this.firstBarrierIndexIn(bb, v))
or
@@ -119,7 +119,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
}
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | isBarrier(bb.getNode(m), v))
result = min(int m | this.isBarrier(bb.getNode(m), v))
}
}
@@ -271,7 +271,7 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
* accounts for loops where the condition is provably true upon entry.
*/
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
reachesTo(source, v, sink, _)
this.reachesTo(source, v, sink, _)
}
/**
@@ -281,21 +281,21 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
) {
exists(ControlFlowNode def |
actualSourceReaches(source, v, def, v0) and
this.actualSourceReaches(source, v, def, v0) and
LocalScopeVariableReachability.super.reaches(def, v0, sink) and
isSinkActual(sink, v0)
this.isSinkActual(sink, v0)
)
}
private predicate actualSourceReaches(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) {
isSourceActual(source, v) and def = source and v0 = v
this.isSourceActual(source, v) and def = source and v0 = v
or
exists(ControlFlowNode source1, SemanticStackVariable v1 |
actualSourceReaches(source, v, source1, v1)
this.actualSourceReaches(source, v, source1, v1)
|
reassignment(source1, v1, def, v0)
this.reassignment(source1, v1, def, v0)
)
}
@@ -307,14 +307,14 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
}
final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
isSourceActual(node, v)
this.isSourceActual(node, v)
or
// Reassignment generates a new (non-actual) source
reassignment(_, _, node, v)
this.reassignment(_, _, node, v)
}
final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
isSinkActual(node, v)
this.isSinkActual(node, v)
or
// Reassignment generates a new (non-actual) sink
exprDefinition(_, node, v.getAnAccess())
@@ -347,21 +347,21 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
/** See `LocalScopeVariableReachability.reaches`. */
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
exists(BasicBlock bb, int i |
isSource(source, v) and
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
this.isSink(sink, v) and
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
k in [i .. j - 1]
)
)
or
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
bbSuccessorEntryReaches(source, bb, v, sink, _)
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
)
}
@@ -372,22 +372,22 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
bbEntryReachesLocally(source, succ, v, node) and
this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
private predicate bbEntryReachesLocally(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) {
isSource(source, v) and
exists(int n | node = bb.getNode(n) and isSink(node, v) |
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
this.isSource(source, v) and
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
)
}
}

View File

@@ -59,7 +59,7 @@ class SsaDefinition extends ControlFlowNodeBase {
ControlFlowNode getDefinition() { result = this }
/** Gets the `BasicBlock` containing this definition. */
BasicBlock getBasicBlock() { result.contains(getDefinition()) }
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** Holds if this definition is a phi node for variable `v`. */
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) }

View File

@@ -72,19 +72,19 @@ abstract class StackVariableReachability extends string {
*/
exists(BasicBlock bb, int i |
isSource(source, v) and
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
this.isSink(sink, v) and
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
)
or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _)
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
this.bbSuccessorEntryReaches(bb, v, sink, _)
)
}
@@ -96,11 +96,11 @@ abstract class StackVariableReachability extends string {
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
bbEntryReachesLocally(succ, v, node) and
this.bbEntryReachesLocally(succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
not this.isBarrier(succ.getNode(_), v) and
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
@@ -109,7 +109,7 @@ abstract class StackVariableReachability extends string {
) {
exists(int n |
node = bb.getNode(n) and
isSink(node, v)
this.isSink(node, v)
|
not exists(this.firstBarrierIndexIn(bb, v))
or
@@ -118,7 +118,7 @@ abstract class StackVariableReachability extends string {
}
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | isBarrier(bb.getNode(m), v))
result = min(int m | this.isBarrier(bb.getNode(m), v))
}
}
@@ -268,7 +268,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
* accounts for loops where the condition is provably true upon entry.
*/
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
reachesTo(source, v, sink, _)
this.reachesTo(source, v, sink, _)
}
/**
@@ -278,21 +278,21 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
) {
exists(ControlFlowNode def |
actualSourceReaches(source, v, def, v0) and
this.actualSourceReaches(source, v, def, v0) and
StackVariableReachability.super.reaches(def, v0, sink) and
isSinkActual(sink, v0)
this.isSinkActual(sink, v0)
)
}
private predicate actualSourceReaches(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) {
isSourceActual(source, v) and def = source and v0 = v
this.isSourceActual(source, v) and def = source and v0 = v
or
exists(ControlFlowNode source1, SemanticStackVariable v1 |
actualSourceReaches(source, v, source1, v1)
this.actualSourceReaches(source, v, source1, v1)
|
reassignment(source1, v1, def, v0)
this.reassignment(source1, v1, def, v0)
)
}
@@ -304,14 +304,14 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
}
final override predicate isSource(ControlFlowNode node, StackVariable v) {
isSourceActual(node, v)
this.isSourceActual(node, v)
or
// Reassignment generates a new (non-actual) source
reassignment(_, _, node, v)
this.reassignment(_, _, node, v)
}
final override predicate isSink(ControlFlowNode node, StackVariable v) {
isSinkActual(node, v)
this.isSinkActual(node, v)
or
// Reassignment generates a new (non-actual) sink
exprDefinition(_, node, v.getAnAccess())
@@ -342,21 +342,21 @@ abstract class StackVariableReachabilityExt extends string {
/** See `StackVariableReachability.reaches`. */
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
exists(BasicBlock bb, int i |
isSource(source, v) and
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
this.isSink(sink, v) and
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
k in [i .. j - 1]
)
)
or
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
bbSuccessorEntryReaches(source, bb, v, sink, _)
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
)
}
@@ -367,22 +367,22 @@ abstract class StackVariableReachabilityExt extends string {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
bbEntryReachesLocally(source, succ, v, node) and
this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
private predicate bbEntryReachesLocally(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) {
isSource(source, v) and
exists(int n | node = bb.getNode(n) and isSink(node, v) |
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
this.isSource(source, v) and
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
)
}
}

View File

@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
* position.
*/
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 }
deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
pragma[noinline]
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
exists(BasicBlock bb |
exists(int outerIndex |
result = bb.getNode(outerIndex) and
index = outerToInnerIndex(bb, outerIndex)
index = this.outerToInnerIndex(bb, outerIndex)
)
)
}

View File

@@ -344,14 +344,13 @@ private int convertIntToType(int val, IntegralType t) {
then if val = 0 then result = 0 else result = 1
else
if t.isUnsigned()
then if val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 then result = val else none()
then val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 and result = val
else
if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0
then result = val
else
if (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0
then result = val
else none()
else (
(-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 and result = val
)
}
/**
@@ -386,7 +385,7 @@ library class ExprEvaluator extends int {
abstract predicate interesting(Expr e);
/** Gets the value of (interesting) expression `e`, if any. */
int getValue(Expr e) { result = getValueInternal(e, e) }
int getValue(Expr e) { result = this.getValueInternal(e, e) }
/**
* When evaluating a syntactic subexpression of `e`, we may
@@ -426,9 +425,9 @@ library class ExprEvaluator extends int {
* calculates the values bottom-up.
*/
predicate interestingInternal(Expr e, Expr req, boolean sub) {
interesting(e) and req = e and sub = true
this.interesting(e) and req = e and sub = true
or
exists(Expr mid | interestingInternal(e, mid, sub) |
exists(Expr mid | this.interestingInternal(e, mid, sub) |
req = mid.(NotExpr).getOperand() or
req = mid.(BinaryLogicalOperation).getAnOperand() or
req = mid.(RelationalOperation).getAnOperand() or
@@ -443,36 +442,36 @@ library class ExprEvaluator extends int {
)
or
exists(VariableAccess va, Variable v, boolean sub1 |
interestingVariableAccess(e, va, v, sub1) and
this.interestingVariableAccess(e, va, v, sub1) and
req = v.getAnAssignedValue() and
(sub1 = true implies not ignoreVariableAssignment(e, v, req)) and
(sub1 = true implies not this.ignoreVariableAssignment(e, v, req)) and
sub = false
)
or
exists(Function f |
interestingFunction(e, f) and
this.interestingFunction(e, f) and
returnStmt(f, req) and
sub = false
)
}
private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) {
interestingInternal(e, va, sub) and
this.interestingInternal(e, va, sub) and
v = getVariableTarget(va) and
(
v.hasInitializer()
or
sub = true and allowVariableWithoutInitializer(e, v)
sub = true and this.allowVariableWithoutInitializer(e, v)
) and
tractableVariable(v) and
forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) |
sub = true and
ignoreNonAnalyzableVariableDefinition(e, v, def)
this.ignoreNonAnalyzableVariableDefinition(e, v, def)
)
}
private predicate interestingFunction(Expr e, Function f) {
exists(FunctionCall fc | interestingInternal(e, fc, _) |
exists(FunctionCall fc | this.interestingInternal(e, fc, _) |
f = fc.getTarget() and
not obviouslyNonConstant(f) and
not f.getUnspecifiedType() instanceof VoidType
@@ -482,10 +481,10 @@ library class ExprEvaluator extends int {
/** Gets the value of subexpressions `req` for expression `e`, if any. */
private int getValueInternal(Expr e, Expr req) {
(
interestingInternal(e, req, true) and
this.interestingInternal(e, req, true) and
(
result = req.(CompileTimeConstantInt).getIntValue() or
result = getCompoundValue(e, req.(CompileTimeVariableExpr))
result = this.getCompoundValue(e, req.(CompileTimeVariableExpr))
) and
(
req.getUnderlyingType().(IntegralType).isSigned() or
@@ -496,109 +495,126 @@ library class ExprEvaluator extends int {
/** Gets the value of compound subexpressions `val` for expression `e`, if any. */
private int getCompoundValue(Expr e, CompileTimeVariableExpr val) {
interestingInternal(e, val, true) and
this.interestingInternal(e, val, true) and
(
exists(NotExpr req | req = val |
result = 1 and getValueInternal(e, req.getOperand()) = 0
result = 1 and this.getValueInternal(e, req.getOperand()) = 0
or
result = 0 and getValueInternal(e, req.getOperand()) != 0
result = 0 and this.getValueInternal(e, req.getOperand()) != 0
)
or
exists(LogicalAndExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) != 0 and
getValueInternal(e, req.getRightOperand()) != 0
this.getValueInternal(e, req.getLeftOperand()) != 0 and
this.getValueInternal(e, req.getRightOperand()) != 0
or
result = 0 and getValueInternal(e, req.getAnOperand()) = 0
result = 0 and this.getValueInternal(e, req.getAnOperand()) = 0
)
or
exists(LogicalOrExpr req | req = val |
result = 1 and getValueInternal(e, req.getAnOperand()) != 0
result = 1 and this.getValueInternal(e, req.getAnOperand()) != 0
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) = 0 and
getValueInternal(e, req.getRightOperand()) = 0
this.getValueInternal(e, req.getLeftOperand()) = 0 and
this.getValueInternal(e, req.getRightOperand()) = 0
)
or
exists(LTExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) <
this.getValueInternal(e, req.getRightOperand())
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) >=
this.getValueInternal(e, req.getRightOperand())
)
or
exists(GTExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) >
this.getValueInternal(e, req.getRightOperand())
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) <=
this.getValueInternal(e, req.getRightOperand())
)
or
exists(LEExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) <=
this.getValueInternal(e, req.getRightOperand())
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) >
this.getValueInternal(e, req.getRightOperand())
)
or
exists(GEExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) >=
this.getValueInternal(e, req.getRightOperand())
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) <
this.getValueInternal(e, req.getRightOperand())
)
or
exists(EQExpr req | req = val |
result = 1 and
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) =
this.getValueInternal(e, req.getRightOperand())
or
result = 0 and
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) !=
this.getValueInternal(e, req.getRightOperand())
)
or
exists(NEExpr req | req = val |
result = 0 and
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) =
this.getValueInternal(e, req.getRightOperand())
or
result = 1 and
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) !=
this.getValueInternal(e, req.getRightOperand())
)
or
exists(AddExpr req | req = val |
result =
getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) +
this.getValueInternal(e, req.getRightOperand())
)
or
exists(SubExpr req | req = val |
result =
getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) -
this.getValueInternal(e, req.getRightOperand())
)
or
exists(MulExpr req | req = val |
result =
getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) *
this.getValueInternal(e, req.getRightOperand())
)
or
exists(RemExpr req | req = val |
result =
getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) %
this.getValueInternal(e, req.getRightOperand())
)
or
exists(DivExpr req | req = val |
result =
getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand())
this.getValueInternal(e, req.getLeftOperand()) /
this.getValueInternal(e, req.getRightOperand())
)
or
exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue()))
exists(AssignExpr req | req = val | result = this.getValueInternal(e, req.getRValue()))
or
result = getVariableValue(e, val.(VariableAccess))
result = this.getVariableValue(e, val.(VariableAccess))
or
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
result = getFunctionValue(call.getTarget())
result = this.getFunctionValue(call.getTarget())
)
)
}
@@ -606,7 +622,7 @@ library class ExprEvaluator extends int {
language[monotonicAggregates]
private int getVariableValue(Expr e, VariableAccess va) {
exists(Variable v |
interestingVariableAccess(e, va, v, true) and
this.interestingVariableAccess(e, va, v, true) and
// All assignments must have the same int value
result =
unique(Expr value |
@@ -620,14 +636,16 @@ library class ExprEvaluator extends int {
/** Holds if the function `f` is considered by the analysis and may return `ret`. */
pragma[noinline]
private predicate interestingReturnValue(Function f, Expr ret) {
interestingFunction(_, f) and
this.interestingFunction(_, f) and
returnStmt(f, ret)
}
private int getFunctionValue(Function f) {
// All returns must have the same int value
// And it must have at least one return
forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret))
forex(Expr ret | this.interestingReturnValue(f, ret) |
result = this.getValueInternalNonSubExpr(ret)
)
}
/**
@@ -642,10 +660,10 @@ library class ExprEvaluator extends int {
* omitted).
*/
private int getValueInternalNonSubExpr(Expr req) {
interestingInternal(_, req, false) and
this.interestingInternal(_, req, false) and
(
result = req.(CompileTimeConstantInt).getIntValue() or
result = getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr))
result = this.getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr))
) and
(
req.getUnderlyingType().(IntegralType).isSigned() or
@@ -656,131 +674,131 @@ library class ExprEvaluator extends int {
private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) {
(
exists(NotExpr req | req = val |
result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0
result = 1 and this.getValueInternalNonSubExpr(req.getOperand()) = 0
or
result = 0 and getValueInternalNonSubExpr(req.getOperand()) != 0
result = 0 and this.getValueInternalNonSubExpr(req.getOperand()) != 0
)
or
exists(LogicalAndExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and
getValueInternalNonSubExpr(req.getRightOperand()) != 0
this.getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and
this.getValueInternalNonSubExpr(req.getRightOperand()) != 0
or
result = 0 and getValueInternalNonSubExpr(req.getAnOperand()) = 0
result = 0 and this.getValueInternalNonSubExpr(req.getAnOperand()) = 0
)
or
exists(LogicalOrExpr req | req = val |
result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0
result = 1 and this.getValueInternalNonSubExpr(req.getAnOperand()) != 0
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and
getValueInternalNonSubExpr(req.getRightOperand()) = 0
this.getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and
this.getValueInternalNonSubExpr(req.getRightOperand()) = 0
)
or
exists(LTExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) <
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(GTExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) >
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(LEExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) >
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(GEExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) <
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(EQExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) =
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(NEExpr req | req = val |
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) =
this.getValueInternalNonSubExpr(req.getRightOperand())
or
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(AddExpr req | req = val |
result =
getValueInternalNonSubExpr(req.getLeftOperand()) +
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) +
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(SubExpr req | req = val |
result =
getValueInternalNonSubExpr(req.getLeftOperand()) -
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) -
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(MulExpr req | req = val |
result =
getValueInternalNonSubExpr(req.getLeftOperand()) *
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) *
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(RemExpr req | req = val |
result =
getValueInternalNonSubExpr(req.getLeftOperand()) %
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) %
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(DivExpr req | req = val |
result =
getValueInternalNonSubExpr(req.getLeftOperand()) /
getValueInternalNonSubExpr(req.getRightOperand())
this.getValueInternalNonSubExpr(req.getLeftOperand()) /
this.getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(AssignExpr req | req = val | result = getValueInternalNonSubExpr(req.getRValue()))
exists(AssignExpr req | req = val | result = this.getValueInternalNonSubExpr(req.getRValue()))
or
result = getVariableValueNonSubExpr(val.(VariableAccess))
result = this.getVariableValueNonSubExpr(val.(VariableAccess))
or
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
result = getFunctionValue(call.getTarget())
result = this.getFunctionValue(call.getTarget())
)
)
}
private int getVariableValueNonSubExpr(VariableAccess va) {
// All assignments must have the same int value
result = getMinVariableValueNonSubExpr(va) and
result = getMaxVariableValueNonSubExpr(va)
result = this.getMinVariableValueNonSubExpr(va) and
result = this.getMaxVariableValueNonSubExpr(va)
}
/**
@@ -791,8 +809,9 @@ library class ExprEvaluator extends int {
pragma[noopt]
private int getMinVariableValueNonSubExpr(VariableAccess va) {
exists(Variable v |
interestingVariableAccess(_, va, v, false) and
result = min(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value))
this.interestingVariableAccess(_, va, v, false) and
result =
min(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
)
}
@@ -804,8 +823,9 @@ library class ExprEvaluator extends int {
pragma[noopt]
private int getMaxVariableValueNonSubExpr(VariableAccess va) {
exists(Variable v |
interestingVariableAccess(_, va, v, false) and
result = max(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value))
this.interestingVariableAccess(_, va, v, false) and
result =
max(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
)
}
}
@@ -968,9 +988,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
abstract predicate isLoopBody(Expr e, StmtParent s);
private predicate isLoopBodyDescendant(Expr e, StmtParent s) {
isLoopBody(e, s)
this.isLoopBody(e, s)
or
exists(StmtParent mid | isLoopBodyDescendant(e, mid) |
exists(StmtParent mid | this.isLoopBodyDescendant(e, mid) |
s = mid.(Stmt).getAChild() or
s = mid.(Expr).getAChild()
)
@@ -978,13 +998,13 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
// Same as `interestingInternal(e, sub, true)` but avoids negative recursion
private predicate interestingSubExpr(Expr e, Expr sub) {
interesting(e) and e = sub
this.interesting(e) and e = sub
or
exists(Expr mid | interestingSubExpr(e, mid) and sub = mid.getAChild())
exists(Expr mid | this.interestingSubExpr(e, mid) and sub = mid.getAChild())
}
private predicate maybeInterestingVariable(Expr e, Variable v) {
exists(VariableAccess va | interestingSubExpr(e, va) | va.getTarget() = v)
exists(VariableAccess va | this.interestingSubExpr(e, va) | va.getTarget() = v)
}
/**
@@ -996,9 +1016,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* definition of `v`.
*/
private predicate reachesLoopEntryFromLoopBody(Expr e, Variable v, StmtParent valueOrDef) {
maybeInterestingVariable(e, v) and
this.maybeInterestingVariable(e, v) and
(valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and
isLoopBodyDescendant(e, valueOrDef) and
this.isLoopBodyDescendant(e, valueOrDef) and
/*
* Use primitive basic blocks in reachability analysis for better performance.
* This is similar to the pattern used in e.g. `DefinitionsAndUses` and
@@ -1008,16 +1028,16 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef |
// Reaches in same basic block
exists(int pos2 |
loopEntryAt(bb1, pos2, e) and
this.loopEntryAt(bb1, pos2, e) and
pos2 > pos1 and
not exists(int k | assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1])
not exists(int k | this.assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1])
)
or
// Reaches in a successor block
exists(PrimitiveBasicBlock bb2 |
bb2 = bb1.getASuccessor() and
not exists(int pos3 | assignmentAt(bb1, pos3, v) and pos3 > pos1) and
bbReachesLoopEntry(bb2, e, v)
not exists(int pos3 | this.assignmentAt(bb1, pos3, v) and pos3 > pos1) and
this.bbReachesLoopEntry(bb2, e, v)
)
)
}
@@ -1025,12 +1045,12 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
private predicate loopEntryAt(PrimitiveBasicBlock bb, int pos, Expr e) {
exists(Node cfn |
bb.getNode(pos) = cfn and
isLoopEntry(e, cfn)
this.isLoopEntry(e, cfn)
)
}
private predicate assignmentAt(PrimitiveBasicBlock bb, int pos, Variable v) {
maybeInterestingVariable(_, v) and
this.maybeInterestingVariable(_, v) and
bb.getNode(pos) = v.getAnAssignedValue()
}
@@ -1039,19 +1059,19 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* the loop belonging to `e` without crossing an assignment to `v`.
*/
private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) {
bbReachesLoopEntryLocally(bb, e, v)
this.bbReachesLoopEntryLocally(bb, e, v)
or
exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() |
bbReachesLoopEntry(succ, e, v) and
not assignmentAt(bb, _, v)
this.bbReachesLoopEntry(succ, e, v) and
not this.assignmentAt(bb, _, v)
)
}
private predicate bbReachesLoopEntryLocally(PrimitiveBasicBlock bb, Expr e, Variable v) {
exists(int pos |
loopEntryAt(bb, pos, e) and
maybeInterestingVariable(e, v) and
not exists(int pos1 | assignmentAt(bb, pos1, v) | pos1 < pos)
this.loopEntryAt(bb, pos, e) and
this.maybeInterestingVariable(e, v) and
not exists(int pos1 | this.assignmentAt(bb, pos1, v) | pos1 < pos)
)
}
@@ -1085,10 +1105,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* ```
*/
override predicate ignoreNonAnalyzableVariableDefinition(Expr e, Variable v, StmtParent def) {
maybeInterestingVariable(e, v) and
this.maybeInterestingVariable(e, v) and
nonAnalyzableVariableDefinition(v, def) and
isLoopBodyDescendant(e, def) and
not reachesLoopEntryFromLoopBody(e, v, def)
this.isLoopBodyDescendant(e, def) and
not this.reachesLoopEntryFromLoopBody(e, v, def)
}
/**
@@ -1121,10 +1141,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
* ```
*/
override predicate ignoreVariableAssignment(Expr e, Variable v, Expr value) {
maybeInterestingVariable(e, v) and
this.maybeInterestingVariable(e, v) and
value = v.getAnAssignedValue() and
isLoopBodyDescendant(e, value) and
not reachesLoopEntryFromLoopBody(e, v, value)
this.isLoopBodyDescendant(e, value) and
not this.reachesLoopEntryFromLoopBody(e, v, value)
}
}

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -801,6 +801,9 @@ private module Cached {
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) }
cached
newtype TCallContext =
TAnyCallContext() or
@@ -937,7 +940,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
}
override predicate relevantFor(DataFlowCallable callable) {
recordDataFlowCallSite(getCall(), callable)
recordDataFlowCallSite(this.getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
@@ -1236,6 +1239,13 @@ class TypedContent extends MkTypedContent {
/** Gets a textual representation of this content. */
string toString() { result = c.toString() }
/**
* Holds if access paths with this `TypedContent` at their head always should
* be tracked at high precision. This disables adaptive access path precision
* for such access paths.
*/
predicate forceHighPrecision() { forceHighPrecision(c) }
}
/**
@@ -1250,7 +1260,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -175,6 +175,7 @@ module Consistency {
query predicate postWithInFlow(Node n, string msg) {
isPostUpdateNode(n) and
not clearsContent(n, _) and
simpleLocalFlowStep(_, n) and
msg = "PostUpdateNode should not be the target of local flow."
}

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -219,15 +219,13 @@ class DataFlowExpr = Expr;
class DataFlowType = Type;
/** A function call relevant for data flow. */
class DataFlowCall extends Expr {
DataFlowCall() { this instanceof Call }
class DataFlowCall extends Expr instanceof Call {
/**
* Gets the nth argument for this call.
*
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
*/
Expr getArgument(int n) { result = this.(Call).getArgument(n) }
Expr getArgument(int n) { result = super.getArgument(n) }
/** Gets the data flow node corresponding to this call. */
ExprNode getNode() { result.getExpr() = this }
@@ -240,6 +238,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl
int accessPathLimit() { result = 5 }
/**
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { none() }
/** The unit type. */
private newtype TUnit = TMkUnit()
@@ -283,3 +287,12 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { none() }

View File

@@ -101,18 +101,18 @@ class Node extends TNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/**
* Gets an upper bound on the type of this node.
*/
Type getTypeBound() { result = getType() }
Type getTypeBound() { result = this.getType() }
}
/**
@@ -293,11 +293,11 @@ abstract class PostUpdateNode extends Node {
*/
abstract Node getPreUpdateNode();
override Function getFunction() { result = getPreUpdateNode().getFunction() }
override Function getFunction() { result = this.getPreUpdateNode().getFunction() }
override Type getType() { result = getPreUpdateNode().getType() }
override Type getType() { result = this.getPreUpdateNode().getType() }
override Location getLocation() { result = getPreUpdateNode().getLocation() }
override Location getLocation() { result = this.getPreUpdateNode().getLocation() }
}
abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
@@ -309,7 +309,7 @@ abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDef
PartialDefinition getPartialDefinition() { result = pd }
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
override string toString() { result = this.getPreUpdateNode().toString() + " [post update]" }
}
private class VariablePartialDefinitionNode extends PartialDefinitionNode {
@@ -380,13 +380,13 @@ private class ObjectInitializerNode extends PostUpdateNode, TExprNode {
class PreObjectInitializerNode extends Node, TPreObjectInitializerNode {
Expr getExpr() { this = TPreObjectInitializerNode(result) }
override Function getFunction() { result = getExpr().getEnclosingFunction() }
override Function getFunction() { result = this.getExpr().getEnclosingFunction() }
override Type getType() { result = getExpr().getType() }
override Type getType() { result = this.getExpr().getType() }
override Location getLocation() { result = getExpr().getLocation() }
override Location getLocation() { result = this.getExpr().getLocation() }
override string toString() { result = getExpr().toString() + " [pre init]" }
override string toString() { result = this.getExpr().toString() + " [pre init]" }
}
/**
@@ -401,7 +401,7 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
}
override string toString() {
result = getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]"
result = this.getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]"
}
}
@@ -416,15 +416,17 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
class PreConstructorInitThis extends Node, TPreConstructorInitThis {
ConstructorFieldInit getConstructorFieldInit() { this = TPreConstructorInitThis(result) }
override Constructor getFunction() { result = getConstructorFieldInit().getEnclosingFunction() }
override PointerType getType() {
result.getBaseType() = getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
override Constructor getFunction() {
result = this.getConstructorFieldInit().getEnclosingFunction()
}
override Location getLocation() { result = getConstructorFieldInit().getLocation() }
override PointerType getType() {
result.getBaseType() = this.getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
}
override string toString() { result = getConstructorFieldInit().toString() + " [pre-this]" }
override Location getLocation() { result = this.getConstructorFieldInit().getLocation() }
override string toString() { result = this.getConstructorFieldInit().toString() + " [pre-this]" }
}
/**

View File

@@ -354,7 +354,7 @@ module FlowVar_internal {
result = def.getAUse(v)
or
exists(SsaDefinition descendentDef |
getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
this.getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
result = descendentDef.getAUse(v)
)
)
@@ -515,7 +515,7 @@ module FlowVar_internal {
this.bbInLoopCondition(bbInside) and
not this.bbInLoop(bbOutside) and
bbOutside = bbInside.getASuccessor() and
not reachesWithoutAssignment(bbInside, v)
not this.reachesWithoutAssignment(bbInside, v)
}
/**
@@ -546,7 +546,7 @@ module FlowVar_internal {
private predicate bbInLoop(BasicBlock bb) {
bbDominates(this.(Loop).getStmt(), bb)
or
bbInLoopCondition(bb)
this.bbInLoopCondition(bb)
}
/** Holds if `sbb` is inside this loop. */
@@ -563,7 +563,7 @@ module FlowVar_internal {
bb = this.(Loop).getStmt() and
v = this.getARelevantVariable()
or
reachesWithoutAssignment(bb.getAPredecessor(), v) and
this.reachesWithoutAssignment(bb.getAPredecessor(), v) and
this.bbInLoop(bb)
) and
not assignsToVar(bb, v)

View File

@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
* position.
*/
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 }
deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
pragma[noinline]
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
exists(BasicBlock bb |
exists(int outerIndex |
result = bb.getNode(outerIndex) and
index = outerToInnerIndex(bb, outerIndex)
index = this.outerToInnerIndex(bb, outerIndex)
)
)
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { 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() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { 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() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -203,7 +203,7 @@ class PointerFieldAccess extends FieldAccess {
PointerFieldAccess() {
exists(PointerType t |
t = getQualifier().getFullyConverted().getUnspecifiedType() and
t = this.getQualifier().getFullyConverted().getUnspecifiedType() and
t.getBaseType() instanceof Class
)
}
@@ -218,7 +218,9 @@ class PointerFieldAccess extends FieldAccess {
class DotFieldAccess extends FieldAccess {
override string getAPrimaryQlClass() { result = "DotFieldAccess" }
DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) }
DotFieldAccess() {
exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType())
}
}
/**

View File

@@ -148,7 +148,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
override int getPrecedence() { result = 17 }
override string toString() { result = "... " + getOperator() }
override string toString() { result = "... " + this.getOperator() }
}
/**
@@ -166,7 +166,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
override int getPrecedence() { result = 17 }
override string toString() { result = "... " + getOperator() }
override string toString() { result = "... " + this.getOperator() }
}
/**

View File

@@ -35,12 +35,12 @@ class BuiltInVarArgsStart extends VarArgsExpr, @vastartexpr {
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
final Expr getVAList() { result = this.getChild(0) }
/**
* Gets the argument that specifies the last named parameter before the ellipsis.
*/
final VariableAccess getLastNamedParameter() { result = getChild(1) }
final VariableAccess getLastNamedParameter() { result = this.getChild(1) }
}
/**
@@ -60,7 +60,7 @@ class BuiltInVarArgsEnd extends VarArgsExpr, @vaendexpr {
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
final Expr getVAList() { result = this.getChild(0) }
}
/**
@@ -78,7 +78,7 @@ class BuiltInVarArg extends VarArgsExpr, @vaargexpr {
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
final Expr getVAList() { result = this.getChild(0) }
}
/**
@@ -98,12 +98,12 @@ class BuiltInVarArgCopy extends VarArgsExpr, @vacopyexpr {
/**
* Gets the destination `va_list` argument.
*/
final Expr getDestinationVAList() { result = getChild(0) }
final Expr getDestinationVAList() { result = this.getChild(0) }
/**
* Gets the the source `va_list` argument.
*/
final Expr getSourceVAList() { result = getChild(1) }
final Expr getSourceVAList() { result = this.getChild(1) }
}
/**

View File

@@ -71,10 +71,10 @@ class Call extends Expr, NameQualifiableElement, TCall {
* at index 2, respectively.
*/
Expr getAnArgumentSubExpr(int index) {
result = getArgument(index)
result = this.getArgument(index)
or
exists(Expr mid |
mid = getAnArgumentSubExpr(index) and
mid = this.getAnArgumentSubExpr(index) and
not mid instanceof Call and
not mid instanceof SizeofOperator and
result = mid.getAChild()
@@ -167,27 +167,27 @@ class FunctionCall extends Call, @funbindexpr {
override string getAPrimaryQlClass() { result = "FunctionCall" }
/** Gets an explicit template argument for this call. */
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
Locatable getAnExplicitTemplateArgument() { result = this.getExplicitTemplateArgument(_) }
/** Gets an explicit template argument value for this call. */
Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) }
Locatable getAnExplicitTemplateArgumentKind() { result = this.getExplicitTemplateArgumentKind(_) }
/** Gets a template argument for this call. */
Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() }
Locatable getATemplateArgument() { result = this.getTarget().getATemplateArgument() }
/** Gets a template argument value for this call. */
Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() }
Locatable getATemplateArgumentKind() { result = this.getTarget().getATemplateArgumentKind() }
/** Gets the nth explicit template argument for this call. */
Locatable getExplicitTemplateArgument(int n) {
n < getNumberOfExplicitTemplateArguments() and
result = getTemplateArgument(n)
n < this.getNumberOfExplicitTemplateArguments() and
result = this.getTemplateArgument(n)
}
/** Gets the nth explicit template argument value for this call. */
Locatable getExplicitTemplateArgumentKind(int n) {
n < getNumberOfExplicitTemplateArguments() and
result = getTemplateArgumentKind(n)
n < this.getNumberOfExplicitTemplateArguments() and
result = this.getTemplateArgumentKind(n)
}
/** Gets the number of explicit template arguments for this call. */
@@ -198,19 +198,19 @@ class FunctionCall extends Call, @funbindexpr {
}
/** Gets the number of template arguments for this call. */
int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) }
int getNumberOfTemplateArguments() { result = count(int i | exists(this.getTemplateArgument(i))) }
/** Gets the nth template argument for this call (indexed from 0). */
Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) }
Locatable getTemplateArgument(int n) { result = this.getTarget().getTemplateArgument(n) }
/** Gets the nth template argument value for this call (indexed from 0). */
Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) }
Locatable getTemplateArgumentKind(int n) { result = this.getTarget().getTemplateArgumentKind(n) }
/** Holds if any template arguments for this call are implicit / deduced. */
predicate hasImplicitTemplateArguments() {
exists(int i |
exists(getTemplateArgument(i)) and
not exists(getExplicitTemplateArgument(i))
exists(this.getTemplateArgument(i)) and
not exists(this.getExplicitTemplateArgument(i))
)
}
@@ -233,9 +233,9 @@ class FunctionCall extends Call, @funbindexpr {
* visible at the call site.
*/
Type getExpectedReturnType() {
if getTargetType() instanceof RoutineType
then result = getTargetType().(RoutineType).getReturnType()
else result = getTarget().getType()
if this.getTargetType() instanceof RoutineType
then result = this.getTargetType().(RoutineType).getReturnType()
else result = this.getTarget().getType()
}
/**
@@ -247,9 +247,9 @@ class FunctionCall extends Call, @funbindexpr {
* was visible at the call site.
*/
Type getExpectedParameterType(int n) {
if getTargetType() instanceof RoutineType
then result = getTargetType().(RoutineType).getParameterType(n)
else result = getTarget().getParameter(n).getType()
if this.getTargetType() instanceof RoutineType
then result = this.getTargetType().(RoutineType).getParameterType(n)
else result = this.getTarget().getParameter(n).getType()
}
/**
@@ -263,7 +263,7 @@ class FunctionCall extends Call, @funbindexpr {
/**
* Gets the type of this expression, that is, the return type of the function being called.
*/
override Type getType() { result = getExpectedReturnType() }
override Type getType() { result = this.getExpectedReturnType() }
/**
* Holds if this is a call to a virtual function.
@@ -280,7 +280,7 @@ class FunctionCall extends Call, @funbindexpr {
/** Gets a textual representation of this function call. */
override string toString() {
if exists(getTarget())
if exists(this.getTarget())
then result = "call to " + this.getTarget().getName()
else result = "call to unknown function"
}
@@ -288,15 +288,15 @@ class FunctionCall extends Call, @funbindexpr {
override predicate mayBeImpure() {
this.getChild(_).mayBeImpure() or
this.getTarget().mayHaveSideEffects() or
isVirtual() or
getTarget().getAnAttribute().getName() = "weak"
this.isVirtual() or
this.getTarget().getAnAttribute().getName() = "weak"
}
override predicate mayBeGloballyImpure() {
this.getChild(_).mayBeGloballyImpure() or
this.getTarget().mayHaveSideEffects() or
isVirtual() or
getTarget().getAnAttribute().getName() = "weak"
this.isVirtual() or
this.getTarget().getAnAttribute().getName() = "weak"
}
}
@@ -367,7 +367,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
* ```
*/
class OverloadedArrayExpr extends FunctionCall {
OverloadedArrayExpr() { getTarget().hasName("operator[]") }
OverloadedArrayExpr() { this.getTarget().hasName("operator[]") }
override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" }
@@ -585,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
*/
Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "constructor init of field " + getTarget().getName() }
override string toString() { result = "constructor init of field " + this.getTarget().getName() }
override predicate mayBeImpure() { this.getExpr().mayBeImpure() }

View File

@@ -188,8 +188,8 @@ private predicate isPointerToMemberOrNullPointer(Type type) {
class ArithmeticConversion extends Cast {
ArithmeticConversion() {
conversionkinds(underlyingElement(this), 0) and
isArithmeticOrEnum(getUnspecifiedType()) and
isArithmeticOrEnum(getExpr().getUnspecifiedType())
isArithmeticOrEnum(this.getUnspecifiedType()) and
isArithmeticOrEnum(this.getExpr().getUnspecifiedType())
}
override string getSemanticConversionString() { result = "arithmetic conversion" }
@@ -204,8 +204,8 @@ class ArithmeticConversion extends Cast {
*/
class IntegralConversion extends ArithmeticConversion {
IntegralConversion() {
isIntegralOrEnum(getUnspecifiedType()) and
isIntegralOrEnum(getExpr().getUnspecifiedType())
isIntegralOrEnum(this.getUnspecifiedType()) and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
@@ -224,8 +224,8 @@ class IntegralConversion extends ArithmeticConversion {
*/
class FloatingPointConversion extends ArithmeticConversion {
FloatingPointConversion() {
getUnspecifiedType() instanceof FloatingPointType and
getExpr().getUnspecifiedType() instanceof FloatingPointType
this.getUnspecifiedType() instanceof FloatingPointType and
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
@@ -244,8 +244,8 @@ class FloatingPointConversion extends ArithmeticConversion {
*/
class FloatingPointToIntegralConversion extends ArithmeticConversion {
FloatingPointToIntegralConversion() {
isIntegralOrEnum(getUnspecifiedType()) and
getExpr().getUnspecifiedType() instanceof FloatingPointType
isIntegralOrEnum(this.getUnspecifiedType()) and
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
@@ -264,8 +264,8 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
*/
class IntegralToFloatingPointConversion extends ArithmeticConversion {
IntegralToFloatingPointConversion() {
getUnspecifiedType() instanceof FloatingPointType and
isIntegralOrEnum(getExpr().getUnspecifiedType())
this.getUnspecifiedType() instanceof FloatingPointType and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
@@ -290,8 +290,8 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
class PointerConversion extends Cast {
PointerConversion() {
conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(getUnspecifiedType()) and
isPointerOrNullPointer(getExpr().getUnspecifiedType())
isPointerOrNullPointer(this.getUnspecifiedType()) and
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
@@ -315,8 +315,8 @@ class PointerToMemberConversion extends Cast {
PointerToMemberConversion() {
conversionkinds(underlyingElement(this), 0) and
exists(Type fromType, Type toType |
fromType = getExpr().getUnspecifiedType() and
toType = getUnspecifiedType() and
fromType = this.getExpr().getUnspecifiedType() and
toType = this.getUnspecifiedType() and
isPointerToMemberOrNullPointer(fromType) and
isPointerToMemberOrNullPointer(toType) and
// A conversion from nullptr to nullptr is a `PointerConversion`, not a
@@ -345,8 +345,8 @@ class PointerToMemberConversion extends Cast {
class PointerToIntegralConversion extends Cast {
PointerToIntegralConversion() {
conversionkinds(underlyingElement(this), 0) and
isIntegralOrEnum(getUnspecifiedType()) and
isPointerOrNullPointer(getExpr().getUnspecifiedType())
isIntegralOrEnum(this.getUnspecifiedType()) and
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
@@ -366,8 +366,8 @@ class PointerToIntegralConversion extends Cast {
class IntegralToPointerConversion extends Cast {
IntegralToPointerConversion() {
conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(getUnspecifiedType()) and
isIntegralOrEnum(getExpr().getUnspecifiedType())
isPointerOrNullPointer(this.getUnspecifiedType()) and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
@@ -403,7 +403,7 @@ class BoolConversion extends Cast {
class VoidConversion extends Cast {
VoidConversion() {
conversionkinds(underlyingElement(this), 0) and
getUnspecifiedType() instanceof VoidType
this.getUnspecifiedType() instanceof VoidType
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
@@ -434,8 +434,8 @@ class InheritanceConversion extends Cast {
* conversion is to an indirect virtual base class.
*/
final ClassDerivation getDerivation() {
result.getBaseClass() = getBaseClass() and
result.getDerivedClass() = getDerivedClass()
result.getBaseClass() = this.getBaseClass() and
result.getDerivedClass() = this.getDerivedClass()
}
/**
@@ -490,12 +490,12 @@ class BaseClassConversion extends InheritanceConversion {
override Class getBaseClass() { result = getConversionClass(this) }
override Class getDerivedClass() { result = getConversionClass(getExpr()) }
override Class getDerivedClass() { result = getConversionClass(this.getExpr()) }
/**
* Holds if this conversion is to a virtual base class.
*/
predicate isVirtual() { getDerivation().isVirtual() or not exists(getDerivation()) }
predicate isVirtual() { this.getDerivation().isVirtual() or not exists(this.getDerivation()) }
}
/**
@@ -515,7 +515,7 @@ class DerivedClassConversion extends InheritanceConversion {
override string getSemanticConversionString() { result = "derived class conversion" }
override Class getBaseClass() { result = getConversionClass(getExpr()) }
override Class getBaseClass() { result = getConversionClass(this.getExpr()) }
override Class getDerivedClass() { result = getConversionClass(this) }
}
@@ -637,8 +637,8 @@ class DynamicCast extends Cast, @dynamic_cast {
*/
class UuidofOperator extends Expr, @uuidof {
override string toString() {
if exists(getTypeOperand())
then result = "__uuidof(" + getTypeOperand().getName() + ")"
if exists(this.getTypeOperand())
then result = "__uuidof(" + this.getTypeOperand().getName() + ")"
else result = "__uuidof(0)"
}

View File

@@ -26,7 +26,7 @@ class Expr extends StmtParent, @expr {
Function getEnclosingFunction() { result = exprEnclosingElement(this) }
/** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */
BlockStmt getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() }
BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() }
override Stmt getEnclosingStmt() {
result = this.getParent().(Expr).getEnclosingStmt()
@@ -219,13 +219,13 @@ class Expr extends StmtParent, @expr {
* Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an
* _xvalue_.
*/
predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() }
predicate isGLValueCategory() { this.isLValueCategory() or this.isXValueCategory() }
/**
* Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an
* _xvalue_.
*/
predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() }
predicate isRValueCategory() { this.isPRValueCategory() or this.isXValueCategory() }
/**
* Gets a string representation of the value category of the expression.
@@ -240,15 +240,15 @@ class Expr extends StmtParent, @expr {
* `hasLValueToRvalueConversion()` holds.
*/
string getValueCategoryString() {
isLValueCategory() and
this.isLValueCategory() and
result = "lvalue"
or
isXValueCategory() and
this.isXValueCategory() and
result = "xvalue"
or
(
isPRValueCategory() and
if hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue"
this.isPRValueCategory() and
if this.hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue"
)
}
@@ -263,7 +263,7 @@ class Expr extends StmtParent, @expr {
* such as an expression inside a sizeof.
*/
predicate isUnevaluated() {
exists(Element e | e = getParentWithConversions+() |
exists(Element e | e = this.getParentWithConversions+() |
e instanceof SizeofOperator
or
exists(Expr e2 |
@@ -279,7 +279,7 @@ class Expr extends StmtParent, @expr {
e instanceof AlignofOperator
)
or
exists(Decltype d | d.getExpr() = getParentWithConversions*())
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
}
/**
@@ -725,7 +725,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
*
* Gets the expression that is being dereferenced.
*/
deprecated Expr getExpr() { result = getOperand() }
deprecated Expr getExpr() { result = this.getOperand() }
override string getOperator() { result = "*" }
@@ -780,15 +780,15 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
* Gets the alignment argument passed to the allocation function, if any.
*/
Expr getAlignmentArgument() {
hasAlignedAllocation() and
this.hasAlignedAllocation() and
(
// If we have an allocator call, the alignment is the second argument to
// that call.
result = getAllocatorCall().getArgument(1)
result = this.getAllocatorCall().getArgument(1)
or
// Otherwise, the alignment winds up as child number 3 of the `new`
// itself.
result = getChild(3)
result = this.getChild(3)
)
}
@@ -916,7 +916,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
* Gets the element type of the array being allocated.
*/
Type getAllocatedElementType() {
result = getType().getUnderlyingType().(PointerType).getBaseType()
result = this.getType().getUnderlyingType().(PointerType).getBaseType()
}
/**
@@ -946,7 +946,12 @@ class DeleteExpr extends Expr, @delete_expr {
*/
Type getDeletedObjectType() {
result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
this.getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
}
/**
@@ -957,7 +962,7 @@ class DeleteExpr extends Expr, @delete_expr {
/**
* Gets the destructor to be called to destroy the object, if any.
*/
Destructor getDestructor() { result = getDestructorCall().getTarget() }
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
/**
* Gets the `operator delete` that deallocates storage. Does not hold
@@ -1020,7 +1025,12 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
*/
Type getDeletedElementType() {
result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
this.getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
}
/**
@@ -1034,7 +1044,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
/**
* Gets the destructor to be called to destroy each element in the array, if any.
*/
Destructor getDestructor() { result = getDestructorCall().getTarget() }
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
/**
* Gets the `operator delete[]` that deallocates storage.
@@ -1101,7 +1111,7 @@ class StmtExpr extends Expr, @expr_stmt {
* x = ({ dosomething(); a+b; });
* ```
*/
Expr getResultExpr() { result = getStmtResultExpr(getStmt()) }
Expr getResultExpr() { result = getStmtResultExpr(this.getStmt()) }
}
/** Get the result expression of a statement. (Helper function for StmtExpr.) */
@@ -1230,20 +1240,20 @@ class FoldExpr extends Expr, @foldexpr {
predicate isRightFold() { fold(underlyingElement(this), _, false) }
/** Holds if this is a unary fold expression. */
predicate isUnaryFold() { getNumChild() = 1 }
predicate isUnaryFold() { this.getNumChild() = 1 }
/** Holds if this is a binary fold expression. */
predicate isBinaryFold() { getNumChild() = 2 }
predicate isBinaryFold() { this.getNumChild() = 2 }
/**
* Gets the child expression containing the unexpanded parameter pack.
*/
Expr getPackExpr() {
this.isUnaryFold() and
result = getChild(0)
result = this.getChild(0)
or
this.isBinaryFold() and
if this.isRightFold() then result = getChild(0) else result = getChild(1)
if this.isRightFold() then result = this.getChild(0) else result = this.getChild(1)
}
/**
@@ -1251,7 +1261,7 @@ class FoldExpr extends Expr, @foldexpr {
*/
Expr getInitExpr() {
this.isBinaryFold() and
if this.isRightFold() then result = getChild(1) else result = getChild(0)
if this.isRightFold() then result = this.getChild(1) else result = this.getChild(0)
}
}

View File

@@ -24,7 +24,7 @@ class LambdaExpression extends Expr, @lambdaexpr {
/**
* Gets an implicitly or explicitly captured value of this lambda expression.
*/
LambdaCapture getACapture() { result = getCapture(_) }
LambdaCapture getACapture() { result = this.getCapture(_) }
/**
* Gets the nth implicitly or explicitly captured value of this lambda expression.
@@ -58,13 +58,13 @@ class LambdaExpression extends Expr, @lambdaexpr {
* - The return type.
* - The statements comprising the lambda body.
*/
Operator getLambdaFunction() { result = getType().(Closure).getLambdaFunction() }
Operator getLambdaFunction() { result = this.getType().(Closure).getLambdaFunction() }
/**
* Gets the initializer that initializes the captured variables in the closure, if any.
* A lambda that does not capture any variables will not have an initializer.
*/
ClassAggregateLiteral getInitializer() { result = getChild(0) }
ClassAggregateLiteral getInitializer() { result = this.getChild(0) }
}
/**
@@ -103,7 +103,7 @@ class Closure extends Class {
* ```
*/
class LambdaCapture extends Locatable, @lambdacapture {
override string toString() { result = getField().getName() }
override string toString() { result = this.getField().getName() }
override string getAPrimaryQlClass() { result = "LambdaCapture" }

View File

@@ -60,12 +60,12 @@ class TextLiteral extends Literal {
/** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
string getAHexEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset)
result = this.getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset)
}
/** Gets an octal escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
string getAnOctalEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset)
result = this.getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset)
}
/**
@@ -75,27 +75,27 @@ class TextLiteral extends Literal {
string getANonStandardEscapeSequence(int occurrence, int offset) {
// Find all single character escape sequences (ignoring the start of octal escape sequences),
// together with anything starting like a hex escape sequence but not followed by a hex digit.
result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and
result = this.getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and
// From these, exclude all standard escape sequences.
not result = getAStandardEscapeSequence(_, _)
not result = this.getAStandardEscapeSequence(_, _)
}
/** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
string getASimpleEscapeSequence(int occurrence, int offset) {
result = getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset)
result = this.getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset)
}
/** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
string getAStandardEscapeSequence(int occurrence, int offset) {
result = getASimpleEscapeSequence(occurrence, offset) or
result = getAnOctalEscapeSequence(occurrence, offset) or
result = getAHexEscapeSequence(occurrence, offset)
result = this.getASimpleEscapeSequence(occurrence, offset) or
result = this.getAnOctalEscapeSequence(occurrence, offset) or
result = this.getAHexEscapeSequence(occurrence, offset)
}
/**
* Gets the length of the string literal (including null) before escape sequences added by the extractor.
*/
int getOriginalLength() { result = getValue().length() + 1 }
int getOriginalLength() { result = this.getValue().length() + 1 }
}
/**
@@ -216,7 +216,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
(
// If the field has an explicit initializer expression, then the field is
// initialized.
exists(getFieldExpr(field))
exists(this.getFieldExpr(field))
or
// If the type is not a union, all fields without initializers are value
// initialized.
@@ -224,7 +224,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
or
// If the type is a union, and there are no explicit initializers, then
// the first declared field is value initialized.
not exists(getAChild()) and
not exists(this.getAChild()) and
field.getInitializationOrder() = 0
)
}
@@ -239,8 +239,8 @@ class ClassAggregateLiteral extends AggregateLiteral {
*/
pragma[inline]
predicate isValueInitialized(Field field) {
isInitialized(field) and
not exists(getFieldExpr(field))
this.isInitialized(field) and
not exists(this.getFieldExpr(field))
}
}
@@ -285,7 +285,7 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
bindingset[elementIndex]
predicate isInitialized(int elementIndex) {
elementIndex >= 0 and
elementIndex < getArraySize()
elementIndex < this.getArraySize()
}
/**
@@ -298,8 +298,8 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
*/
bindingset[elementIndex]
predicate isValueInitialized(int elementIndex) {
isInitialized(elementIndex) and
not exists(getElementExpr(elementIndex))
this.isInitialized(elementIndex) and
not exists(this.getElementExpr(elementIndex))
}
}

View File

@@ -173,7 +173,7 @@ class LocalVariable extends LocalScopeVariable, @localvariable { }
class VariableDeclarationEntry extends @var_decl {
string toString() { result = "QualifiedName DeclarationEntry" }
Variable getDeclaration() { result = getVariable() }
Variable getDeclaration() { result = this.getVariable() }
/**
* Gets the variable which is being declared or defined.

View File

@@ -4,7 +4,7 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.DataFlow3
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
private import semmle.code.cpp.ir.dataflow.ResolveCall
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.DataFlow
@@ -355,20 +355,6 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
*/
GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() }
/**
* Resolve potential target function(s) for `call`.
*
* If `call` is a call through a function pointer (`ExprCall`) or
* targets a virtual method, simple data flow analysis is performed
* in order to identify target(s).
*/
Function resolveCall(Call call) {
exists(CallInstruction callInstruction |
callInstruction.getAST() = call and
result = Dispatch::viableCallable(callInstruction)
)
}
/**
* Provides definitions for augmenting source/sink pairs with data-flow paths
* between them. From a `@kind path-problem` query, import this module in the
@@ -479,7 +465,7 @@ module TaintedWithPath {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -0,0 +1,23 @@
/**
* Provides a predicate for non-contextual virtual dispatch and function
* pointer resolution.
*/
import cpp
private import semmle.code.cpp.ir.ValueNumbering
private import internal.DataFlowDispatch
private import semmle.code.cpp.ir.IR
/**
* Resolve potential target function(s) for `call`.
*
* If `call` is a call through a function pointer (`ExprCall`) or its target is
* a virtual member function, simple data flow analysis is performed in order
* to identify the possible target(s).
*/
Function resolveCall(Call call) {
exists(CallInstruction callInstruction |
callInstruction.getAST() = call and
result = viableCallable(callInstruction)
)
}

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -110,12 +110,12 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
/**
* Holds if data may flow from some source to `sink` for this configuration.
*/
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
}
int getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
or
p.allowParameterReturnInSelf()
)
)
}
@@ -1394,8 +1400,12 @@ private module Stage2 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2083,8 +2093,12 @@ private module Stage3 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2139,7 +2153,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2842,8 +2857,12 @@ private module Stage4 {
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
p.allowParameterReturnInSelf()
)
)
}
@@ -2916,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
int getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
override string toString() { result = p + ": " + ap }
predicate hasLocationInfo(
@@ -2973,12 +2994,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**
@@ -3166,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
}
override string toString() {
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
or
result = "[" + this.toStringImpl(false)
}
@@ -3248,7 +3272,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3305,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
}
override string toString() { result = this.getNodeEx().toString() + ppAp() }
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
override string toStringWithContext() {
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3375,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override PathNodeImpl getASuccessorImpl() {
// an intermediate step to another intermediate node
result = getSuccMid()
result = this.getSuccMid()
or
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
exists(PathNodeMid mid, PathNodeSink sink |
mid = getSuccMid() and
mid = this.getSuccMid() and
mid.getNodeEx() = sink.getNodeEx() and
mid.getAp() instanceof AccessPathNil and
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3456,7 +3482,7 @@ private predicate pathStep(
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
or
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
@@ -3533,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(ArgNode arg |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
ap = mid.getAp() and
apa = ap.getApprox()
apa = ap.getApprox() and
config = mid.getConfiguration()
)
}
@@ -3557,12 +3585,14 @@ private predicate parameterCand(
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap
AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, i, outercc, call, ap, apa) and
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3571,12 +3601,13 @@ private predicate pathIntoCallable0(
* before and after entering the callable are `outercc` and `innercc`,
* respectively.
*/
pragma[nomagic]
private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
(
sc = TSummaryCtxSome(p, ap)
@@ -3606,18 +3637,23 @@ private predicate paramFlowsThrough(
ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
not kind.(ParamUpdateReturnKind).getPosition() = pos
// we don't expect a parameter to return stored in itself, unless explicitly allowed
(
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
sc.getParamNode().allowParameterReturnInSelf()
)
)
}
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
AccessPathApprox apa
AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
)
}
@@ -3627,9 +3663,9 @@ private predicate pathThroughCallable0(
*/
pragma[noinline]
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3643,10 +3679,11 @@ private module Subpaths {
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
NodeEx out, AccessPath apout
) {
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
unbindConf(arg.getConfiguration()))
exists(Configuration config |
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
)
}
/**
@@ -4033,7 +4070,7 @@ private module FlowExploration {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -801,6 +801,9 @@ private module Cached {
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) }
cached
newtype TCallContext =
TAnyCallContext() or
@@ -937,7 +940,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
}
override predicate relevantFor(DataFlowCallable callable) {
recordDataFlowCallSite(getCall(), callable)
recordDataFlowCallSite(this.getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
@@ -1236,6 +1239,13 @@ class TypedContent extends MkTypedContent {
/** Gets a textual representation of this content. */
string toString() { result = c.toString() }
/**
* Holds if access paths with this `TypedContent` at their head always should
* be tracked at high precision. This disables adaptive access path precision
* for such access paths.
*/
predicate forceHighPrecision() { forceHighPrecision(c) }
}
/**
@@ -1250,7 +1260,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -175,6 +175,7 @@ module Consistency {
query predicate postWithInFlow(Node n, string msg) {
isPostUpdateNode(n) and
not clearsContent(n, _) and
simpleLocalFlowStep(_, n) and
msg = "PostUpdateNode should not be the target of local flow."
}

View File

@@ -466,6 +466,12 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl
int accessPathLimit() { result = 5 }
/**
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { none() }
/** The unit type. */
private newtype TUnit = TMkUnit()
@@ -501,3 +507,12 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { none() }

View File

@@ -110,7 +110,7 @@ class Node extends TIRDataFlowNode {
/**
* Gets an upper bound on the type of this node.
*/
IRType getTypeBound() { result = getType() }
IRType getTypeBound() { result = this.getType() }
/** Gets the location of this element. */
Location getLocation() { none() } // overridden by subclasses
@@ -120,7 +120,7 @@ class Node extends TIRDataFlowNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -831,7 +831,7 @@ class FieldContent extends Content, TFieldContent {
FieldContent() { this = TFieldContent(c, startBit, endBit) }
// Ensure that there's just 1 result for `toString`.
override string toString() { result = min(Field f | f = getAField() | f.toString()) }
override string toString() { result = min(Field f | f = this.getAField() | f.toString()) }
predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit }

View File

@@ -38,5 +38,8 @@ Instruction callOutput(CallInstruction call, FunctionOutput output) {
effect.getPrimaryInstruction() = call and
output.isParameterDerefOrQualifierObject(effect.getIndex())
)
// TODO: return value dereference
or
// TODO: modify this when we get return value dereferences
result = call and
output.isReturnValueDeref()
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { 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() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { 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() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { 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() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
final string toString() { result = getFirstInstruction(this).toString() }
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
* Get the `Phi` instructions that appear at the start of this block.
*/
final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
}
/**
* Gets an instruction in this block. This includes `Phi` instructions.
*/
final Instruction getAnInstruction() {
result = getInstruction(_) or
result = getAPhiInstruction()
result = this.getInstruction(_) or
result = this.getAPhiInstruction()
}
/**
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
/**
* Gets the last instruction in this block.
*/
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
final Instruction getLastInstruction() {
result = this.getInstruction(this.getInstructionCount() - 1)
}
/**
* Gets the number of non-`Phi` instructions in this block.
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
* block `B` must pass through block `A`. A block always dominates itself.
*/
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
/**
* Gets a block on the dominance frontier of this block.
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
*/
pragma[noinline]
final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
this.dominates(result.getAPredecessor()) and
not this.strictlyDominates(result)
}
/**
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
* function must pass through block `A`. A block always post-dominates itself.
*/
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block }
final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
/**
* Gets a block on the post-dominance frontier of this block.
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
*/
pragma[noinline]
final IRBlock postPominanceFrontier() {
postDominates(result.getASuccessor()) and
not strictlyPostDominates(result)
this.postDominates(result.getASuccessor()) and
not this.strictlyPostDominates(result)
}
/**
* Holds if this block is reachable from the entry block of its function.
*/
final predicate isReachableFromFunctionEntry() {
this = getEnclosingIRFunction().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry()
this = this.getEnclosingIRFunction().getEntryBlock() or
this.getAPredecessor().isReachableFromFunctionEntry()
}
}

View File

@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
*/
final Language::Location getLocation() { result = getUse().getLocation() }
final Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
*/
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
/**
* Gets the `Instruction` that consumes this operand.
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
*/
final Instruction getDef() {
result = this.getAnyDef() and
getDefinitionOverlap() instanceof MustExactlyOverlap
this.getDefinitionOverlap() instanceof MustExactlyOverlap
}
/**
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated final Instruction getUseInstruction() { result = getUse() }
deprecated final Instruction getUseInstruction() { result = this.getUse() }
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
*
* Gets the `Instruction` whose result is the value of the operand.
*/
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
/**
* Gets the overlap relationship between the operand's definition and its use.
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
/**
* Holds if the result of the definition instruction does not exactly overlap this use.
*/
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
final predicate isDefinitionInexact() {
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
}
/**
* Gets a prefix to use when dumping the operand in an operand list.
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
* For example: `this:r3_5`
*/
final string getDumpString() {
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId()
result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
}
/**
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
* definition is not modeled in SSA.
*/
private string getDefinitionId() {
result = getAnyDef().getResultId()
result = this.getAnyDef().getResultId()
or
not exists(getAnyDef()) and result = "m?"
not exists(this.getAnyDef()) and result = "m?"
}
/**
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
* the empty string.
*/
private string getInexactSpecifier() {
if isDefinitionInexact() then result = "~" else result = ""
if this.isDefinitionInexact() then result = "~" else result = ""
}
/**
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
/**
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
* from the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
final IRType getIRType() { result = getLanguageType().getIRType() }
final IRType getIRType() { result = this.getLanguageType().getIRType() }
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
final Language::Type getType() { getLanguageType().hasType(result, _) }
final Language::Type getType() { this.getLanguageType().hasType(result, _) }
/**
* Holds if the value consumed by this operand is a glvalue. If this
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getType()`.
*/
final predicate isGLValue() { getLanguageType().hasType(_, true) }
final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
final int getSize() { result = getLanguageType().getByteSize() }
final int getSize() { result = this.getLanguageType().getByteSize() }
}
/**
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() }
MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
/**
* Holds if the memory access performed by this operand will not always read from every bit in the
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call).
*/
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() }
predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
* is `r1`.
*/
final AddressOperand getAddressOperand() {
getMemoryAccess().usesAddressOperand() and
result.getUse() = getUse()
this.getMemoryAccess().usesAddressOperand() and
result.getUse() = this.getUse()
}
}
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
final override Overlap getDefinitionOverlap() { result = overlap }
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
final override int getDumpSortOrder() {
result = 11 + this.getPredecessorBlock().getDisplayIndex()
}
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() }
final override string getDumpLabel() {
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
}
final override string getDumpId() {
result = this.getPredecessorBlock().getDisplayIndex().toString()
}
/**
* Gets the predecessor block from which this value comes.

Some files were not shown because too many files have changed in this diff Show More