Merge branch 'main' into rdmarsh2/dataflow-global-vars

This commit is contained in:
Robert Marsh
2022-08-01 14:56:24 -04:00
974 changed files with 30411 additions and 10888 deletions

View File

@@ -3,22 +3,12 @@ description: Fetches the latest version of CodeQL
runs: runs:
using: composite using: composite
steps: steps:
- name: Select platform - Linux
if: runner.os == 'Linux'
shell: bash
run: echo "GA_CODEQL_CLI_PLATFORM=linux64" >> $GITHUB_ENV
- name: Select platform - MacOS
if: runner.os == 'MacOS'
shell: bash
run: echo "GA_CODEQL_CLI_PLATFORM=osx64" >> $GITHUB_ENV
- name: Fetch CodeQL - name: Fetch CodeQL
shell: bash shell: bash
run: | 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 extension install github/gh-codeql
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-$GA_CODEQL_CLI_PLATFORM.zip "$LATEST" gh codeql set-channel release
unzip -q -d "${RUNNER_TEMP}" codeql-$GA_CODEQL_CLI_PLATFORM.zip gh codeql version
echo "${RUNNER_TEMP}/codeql" >> "${GITHUB_PATH}" gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}

View File

@@ -10,6 +10,7 @@ on:
- "*/ql/lib/**/*.qll" - "*/ql/lib/**/*.qll"
- "!**/experimental/**" - "!**/experimental/**"
- "!ql/**" - "!ql/**"
- "!swift/**"
- ".github/workflows/check-change-note.yml" - ".github/workflows/check-change-note.yml"
jobs: jobs:

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "*/ql/lib/**" - "*/ql/lib/**"
- .github/workflows/check-qldoc.yml - .github/workflows/check-qldoc.yml
- .github/actions/fetch-codeql
branches: branches:
- main - main
- "rc/*" - "rc/*"
@@ -14,18 +15,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install CodeQL
run: |
gh extension install github/gh-codeql
gh codeql set-channel nightly
gh codeql version
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 2 fetch-depth: 2
- name: Install CodeQL
uses: ./.github/actions/fetch-codeql
- name: Check QLdoc coverage - name: Check QLdoc coverage
shell: bash shell: bash
run: | run: |
@@ -34,7 +30,7 @@ jobs:
changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -Po '^(?!swift)[a-z]*/ql/lib' || true; } | sort -u)" changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -Po '^(?!swift)[a-z]*/ql/lib' || true; } | sort -u)"
for pack_dir in ${changed_lib_packs}; do for pack_dir in ${changed_lib_packs}; do
lang="${pack_dir%/ql/lib}" lang="${pack_dir%/ql/lib}"
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-current.txt" --dir="${pack_dir}" codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-current.txt" --dir="${pack_dir}"
done done
git checkout HEAD^ git checkout HEAD^
for pack_dir in ${changed_lib_packs}; do for pack_dir in ${changed_lib_packs}; do
@@ -42,7 +38,7 @@ jobs:
# In this case the right thing to do is to skip the check. # In this case the right thing to do is to skip the check.
[[ ! -d "${pack_dir}" ]] && continue [[ ! -d "${pack_dir}" ]] && continue
lang="${pack_dir%/ql/lib}" lang="${pack_dir%/ql/lib}"
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-baseline.txt" --dir="${pack_dir}" codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-baseline.txt" --dir="${pack_dir}"
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-current.txt" | sort -u > "${RUNNER_TEMP}/current-undocumented.txt" awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-current.txt" | sort -u > "${RUNNER_TEMP}/current-undocumented.txt"
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-baseline.txt" | sort -u > "${RUNNER_TEMP}/baseline-undocumented.txt" awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-baseline.txt" | sort -u > "${RUNNER_TEMP}/baseline-undocumented.txt"
UNDOCUMENTED="$(grep -f <(comm -13 "${RUNNER_TEMP}/baseline-undocumented.txt" "${RUNNER_TEMP}/current-undocumented.txt") "${RUNNER_TEMP}/${lang}-current.txt" || true)" UNDOCUMENTED="$(grep -f <(comm -13 "${RUNNER_TEMP}/baseline-undocumented.txt" "${RUNNER_TEMP}/current-undocumented.txt") "${RUNNER_TEMP}/${lang}-current.txt" || true)"

View File

@@ -12,6 +12,7 @@ on:
- main - main
paths: paths:
- ".github/workflows/csv-coverage-metrics.yml" - ".github/workflows/csv-coverage-metrics.yml"
- ".github/actions/fetch-codeql"
jobs: jobs:
publish-java: publish-java:

View File

@@ -3,18 +3,20 @@ name: Check framework coverage changes
on: on:
pull_request: pull_request:
paths: paths:
- '.github/workflows/csv-coverage-pr-comment.yml' - ".github/workflows/csv-coverage-pr-comment.yml"
- '*/ql/src/**/*.ql' - ".github/workflows/csv-coverage-pr-artifacts.yml"
- '*/ql/src/**/*.qll' - ".github/actions/fetch-codeql"
- '*/ql/lib/**/*.ql' - "*/ql/src/**/*.ql"
- '*/ql/lib/**/*.qll' - "*/ql/src/**/*.qll"
- 'misc/scripts/library-coverage/*.py' - "*/ql/lib/**/*.ql"
- "*/ql/lib/**/*.qll"
- "misc/scripts/library-coverage/*.py"
# input data files # input data files
- '*/documentation/library-coverage/cwe-sink.csv' - "*/documentation/library-coverage/cwe-sink.csv"
- '*/documentation/library-coverage/frameworks.csv' - "*/documentation/library-coverage/frameworks.csv"
branches: branches:
- main - main
- 'rc/*' - "rc/*"
jobs: jobs:
generate: generate:
@@ -23,77 +25,72 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Dump GitHub context - name: Dump GitHub context
env: env:
GITHUB_CONTEXT: ${{ toJSON(github.event) }} GITHUB_CONTEXT: ${{ toJSON(github.event) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- name: Clone self (github/codeql) - MERGE - name: Clone self (github/codeql) - MERGE
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: merge path: merge
- name: Clone self (github/codeql) - BASE - name: Clone self (github/codeql) - BASE
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
fetch-depth: 2 fetch-depth: 2
path: base path: base
- run: | - run: |
git checkout HEAD^1 git checkout HEAD^1
git log -1 --format='%H' git log -1 --format='%H'
working-directory: base working-directory: base
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: 3.8
- name: Download CodeQL CLI - name: Download CodeQL CLI
env: uses: ./merge/.github/actions/fetch-codeql
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Generate CSV files on merge commit of the PR
run: | run: |
gh release download --repo "github/codeql-cli-binaries" --pattern "codeql-linux64.zip" echo "Running generator on merge"
- name: Unzip CodeQL CLI PATH="$PATH:codeql-cli/codeql" python merge/misc/scripts/library-coverage/generate-report.py ci merge merge
run: unzip -d codeql-cli codeql-linux64.zip mkdir out_merge
- name: Generate CSV files on merge commit of the PR cp framework-coverage-*.csv out_merge/
run: | cp framework-coverage-*.rst out_merge/
echo "Running generator on merge" - name: Generate CSV files on base commit of the PR
PATH="$PATH:codeql-cli/codeql" python merge/misc/scripts/library-coverage/generate-report.py ci merge merge run: |
mkdir out_merge echo "Running generator on base"
cp framework-coverage-*.csv out_merge/ PATH="$PATH:codeql-cli/codeql" python base/misc/scripts/library-coverage/generate-report.py ci base base
cp framework-coverage-*.rst out_merge/ mkdir out_base
- name: Generate CSV files on base commit of the PR cp framework-coverage-*.csv out_base/
run: | cp framework-coverage-*.rst out_base/
echo "Running generator on base" - name: Generate diff of coverage reports
PATH="$PATH:codeql-cli/codeql" python base/misc/scripts/library-coverage/generate-report.py ci base base run: |
mkdir out_base python base/misc/scripts/library-coverage/compare-folders.py out_base out_merge comparison.md
cp framework-coverage-*.csv out_base/ - name: Upload CSV package list
cp framework-coverage-*.rst out_base/ uses: actions/upload-artifact@v3
- name: Generate diff of coverage reports with:
run: | name: csv-framework-coverage-merge
python base/misc/scripts/library-coverage/compare-folders.py out_base out_merge comparison.md path: |
- name: Upload CSV package list out_merge/framework-coverage-*.csv
uses: actions/upload-artifact@v3 out_merge/framework-coverage-*.rst
with: - name: Upload CSV package list
name: csv-framework-coverage-merge uses: actions/upload-artifact@v3
path: | with:
out_merge/framework-coverage-*.csv name: csv-framework-coverage-base
out_merge/framework-coverage-*.rst path: |
- name: Upload CSV package list out_base/framework-coverage-*.csv
uses: actions/upload-artifact@v3 out_base/framework-coverage-*.rst
with: - name: Upload comparison results
name: csv-framework-coverage-base uses: actions/upload-artifact@v3
path: | with:
out_base/framework-coverage-*.csv name: comparison
out_base/framework-coverage-*.rst path: |
- name: Upload comparison results comparison.md
uses: actions/upload-artifact@v3 - name: Save PR number
with: run: |
name: comparison mkdir -p pr
path: | echo ${{ github.event.pull_request.number }} > pr/NR
comparison.md - name: Upload PR number
- name: Save PR number uses: actions/upload-artifact@v3
run: | with:
mkdir -p pr name: pr
echo ${{ github.event.pull_request.number }} > pr/NR path: pr/
- name: Upload PR number
uses: actions/upload-artifact@v3
with:
name: pr
path: pr/

View File

@@ -5,38 +5,31 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone self (github/codeql) - name: Clone self (github/codeql)
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: script path: script
- name: Clone self (github/codeql) for analysis - name: Clone self (github/codeql) for analysis
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: codeqlModels path: codeqlModels
fetch-depth: 0 fetch-depth: 0
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: 3.8
- name: Download CodeQL CLI - name: Download CodeQL CLI
env: uses: ./.github/actions/fetch-codeql
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build modeled package list
run: | run: |
gh release download --repo "github/codeql-cli-binaries" --pattern "codeql-linux64.zip" CLI=$(realpath "codeql-cli/codeql")
- name: Unzip CodeQL CLI echo $CLI
run: unzip -d codeql-cli codeql-linux64.zip PATH="$PATH:$CLI" python script/misc/scripts/library-coverage/generate-timeseries.py codeqlModels
- name: Build modeled package list - name: Upload timeseries CSV
run: | uses: actions/upload-artifact@v3
CLI=$(realpath "codeql-cli/codeql") with:
echo $CLI name: framework-coverage-timeseries
PATH="$PATH:$CLI" python script/misc/scripts/library-coverage/generate-timeseries.py codeqlModels path: framework-coverage-timeseries-*.csv
- name: Upload timeseries CSV
uses: actions/upload-artifact@v3
with:
name: framework-coverage-timeseries
path: framework-coverage-timeseries-*.csv

View File

@@ -12,33 +12,27 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Dump GitHub context - name: Dump GitHub context
env: env:
GITHUB_CONTEXT: ${{ toJSON(github.event) }} GITHUB_CONTEXT: ${{ toJSON(github.event) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- name: Clone self (github/codeql) - name: Clone self (github/codeql)
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: ql path: ql
fetch-depth: 0 fetch-depth: 0
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: 3.8
- name: Download CodeQL CLI - name: Download CodeQL CLI
env: uses: ./.github/actions/fetch-codeql
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Generate coverage files
run: | run: |
gh release download --repo "github/codeql-cli-binaries" --pattern "codeql-linux64.zip" PATH="$PATH:codeql-cli/codeql" python ql/misc/scripts/library-coverage/generate-report.py ci ql ql
- name: Unzip CodeQL CLI
run: unzip -d codeql-cli codeql-linux64.zip
- name: Generate coverage files - name: Create pull request with changes
run: | env:
PATH="$PATH:codeql-cli/codeql" python ql/misc/scripts/library-coverage/generate-report.py ci ql ql GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- name: Create pull request with changes python ql/misc/scripts/library-coverage/create-pr.py ql "$GITHUB_REPOSITORY"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python ql/misc/scripts/library-coverage/create-pr.py ql "$GITHUB_REPOSITORY"

View File

@@ -4,46 +4,39 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
qlModelShaOverride: qlModelShaOverride:
description: 'github/codeql repo SHA used for looking up the CSV models' description: "github/codeql repo SHA used for looking up the CSV models"
required: false required: false
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone self (github/codeql) - name: Clone self (github/codeql)
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: script path: script
- name: Clone self (github/codeql) for analysis - name: Clone self (github/codeql) for analysis
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
path: codeqlModels path: codeqlModels
ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }} ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }}
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: 3.8
- name: Download CodeQL CLI - name: Download CodeQL CLI
env: uses: ./.github/actions/fetch-codeql
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build modeled package list
run: | run: |
gh release download --repo "github/codeql-cli-binaries" --pattern "codeql-linux64.zip" PATH="$PATH:codeql-cli/codeql" python script/misc/scripts/library-coverage/generate-report.py ci codeqlModels script
- name: Unzip CodeQL CLI - name: Upload CSV package list
run: unzip -d codeql-cli codeql-linux64.zip uses: actions/upload-artifact@v3
- name: Build modeled package list with:
run: | name: framework-coverage-csv
PATH="$PATH:codeql-cli/codeql" python script/misc/scripts/library-coverage/generate-report.py ci codeqlModels script path: framework-coverage-*.csv
- name: Upload CSV package list - name: Upload RST package list
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: framework-coverage-csv name: framework-coverage-rst
path: framework-coverage-*.csv path: framework-coverage-*.rst
- name: Upload RST package list
uses: actions/upload-artifact@v3
with:
name: framework-coverage-rst
path: framework-coverage-*.rst

View File

@@ -4,159 +4,111 @@ on:
paths: paths:
- "go/**" - "go/**"
- .github/workflows/go-tests.yml - .github/workflows/go-tests.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
jobs: jobs:
test-linux: test-linux:
name: Test Linux (Ubuntu) name: Test Linux (Ubuntu)
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Go 1.18.1
uses: actions/setup-go@v3
with:
go-version: 1.18.1
id: go
- name: Set up Go 1.18.1 - name: Check out code
uses: actions/setup-go@v3 uses: actions/checkout@v2
with:
go-version: 1.18.1
id: go
- name: Set up CodeQL CLI - name: Set up CodeQL CLI
run: | uses: ./.github/actions/fetch-codeql
echo "Removing old CodeQL Directory..."
rm -rf $HOME/codeql
echo "Done"
cd $HOME
echo "Downloading CodeQL CLI..."
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
unzip -q codeql-linux64.zip
rm -f codeql-linux64.zip
echo "Done"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check out code - name: Enable problem matchers in repository
uses: actions/checkout@v2 shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Enable problem matchers in repository - name: Build
shell: bash run: |
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;' cd go
env make
- name: Build - name: Check that all QL and Go code is autoformatted
run: | run: |
cd go cd go
env PATH=$PATH:$HOME/codeql make env make check-formatting
- name: Check that all QL and Go code is autoformatted - name: Compile qhelp files to markdown
run: | run: |
cd go cd go
env PATH=$PATH:$HOME/codeql make check-formatting env QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown
- name: Compile qhelp files to markdown - name: Upload qhelp markdown
run: | uses: actions/upload-artifact@v2
cd go with:
env PATH=$PATH:$HOME/codeql QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown name: qhelp-markdown
path: go/qhelp-out/**/*.md
- name: Upload qhelp markdown - name: Test
uses: actions/upload-artifact@v2 run: |
with: cd go
name: qhelp-markdown env make test
path: go/qhelp-out/**/*.md
- name: Test
run: |
cd go
env PATH=$PATH:$HOME/codeql make test
test-mac: test-mac:
name: Test MacOS name: Test MacOS
runs-on: macOS-latest runs-on: macos-latest
steps: steps:
- name: Set up Go 1.18.1 - name: Set up Go 1.18.1
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18.1 go-version: 1.18.1
id: go id: go
- name: Set up CodeQL CLI - name: Check out code
run: | uses: actions/checkout@v2
echo "Removing old CodeQL Directory..."
rm -rf $HOME/codeql
echo "Done"
cd $HOME
echo "Downloading CodeQL CLI..."
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-osx64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
unzip -q codeql-osx64.zip
rm -f codeql-osx64.zip
echo "Done"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check out code - name: Set up CodeQL CLI
uses: actions/checkout@v2 uses: ./.github/actions/fetch-codeql
- name: Enable problem matchers in repository - name: Enable problem matchers in repository
shell: bash shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;' run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Build - name: Build
run: | run: |
cd go cd go
env PATH=$PATH:$HOME/codeql make make
- name: Test - name: Test
run: | run: |
cd go cd go
env PATH=$PATH:$HOME/codeql make test make test
test-win: test-win:
name: Test Windows name: Test Windows
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- name: Set up Go 1.18.1 - name: Set up Go 1.18.1
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18.1 go-version: 1.18.1
id: go id: go
- name: Set up CodeQL CLI - name: Check out code
run: | uses: actions/checkout@v2
echo "Removing old CodeQL Directory..."
rm -rf $HOME/codeql
echo "Done"
cd "$HOME"
echo "Downloading CodeQL CLI..."
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-win64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
unzip -q -o codeql-win64.zip
unzip -q -o codeql-win64.zip codeql/codeql.exe
rm -f codeql-win64.zip
echo "Done"
env:
GITHUB_TOKEN: ${{ github.token }}
shell:
bash
- name: Check out code - name: Set up CodeQL CLI
uses: actions/checkout@v2 uses: ./.github/actions/fetch-codeql
- name: Enable problem matchers in repository - name: Enable problem matchers in repository
shell: bash shell: bash
run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;' run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
- name: Build - name: Build
run: | run: |
$Env:Path += ";$HOME\codeql" cd go
cd go make
make
- name: Test - name: Test
run: | run: |
$Env:Path += ";$HOME\codeql" cd go
cd go make test
make test

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**" - "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml - .github/workflows/js-ml-tests.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main
@@ -13,6 +14,7 @@ on:
paths: paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**" - "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml - .github/workflows/js-ml-tests.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
workflow_dispatch: workflow_dispatch:

View File

@@ -9,6 +9,7 @@ on:
- main - main
paths: paths:
- ".github/workflows/mad_regenerate-models.yml" - ".github/workflows/mad_regenerate-models.yml"
- ".github/actions/fetch-codeql"
jobs: jobs:
regenerate-models: regenerate-models:

View File

@@ -10,16 +10,16 @@ env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
jobs: jobs:
queries: analyze:
runs-on: ubuntu-latest runs-on: ubuntu-latest-xl
steps: steps:
### Build the queries ###
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Find codeql - name: Find codeql
id: find-codeql id: find-codeql
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980 uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with: with:
languages: javascript # does not matter languages: javascript # does not matter
tools: latest
- name: Get CodeQL version - name: Get CodeQL version
id: get-codeql-version id: get-codeql-version
run: | run: |
@@ -49,14 +49,7 @@ jobs:
name: query-pack-zip name: query-pack-zip
path: ${{ runner.temp }}/query-pack.zip path: ${{ runner.temp }}/query-pack.zip
extractors: ### Build the extractor ###
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache entire extractor - name: Cache entire extractor
id: cache-extractor id: cache-extractor
uses: actions/cache@v3 uses: actions/cache@v3
@@ -100,15 +93,8 @@ jobs:
ql/target/release/ql-extractor ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe ql/target/release/ql-extractor.exe
retention-days: 1 retention-days: 1
package:
runs-on: ubuntu-latest
needs: ### Package the queries and extractor ###
- extractors
- queries
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
with: with:
name: query-pack-zip name: query-pack-zip
@@ -136,16 +122,8 @@ jobs:
name: codeql-ql-pack name: codeql-ql-pack
path: codeql-ql.zip path: codeql-ql.zip
retention-days: 1 retention-days: 1
analyze:
runs-on: ubuntu-latest
strategy:
matrix:
folder: [cpp, csharp, java, javascript, python, ql, ruby, swift, go]
needs: ### Run the analysis ###
- package
steps:
- name: Download pack - name: Download pack
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
with: with:
@@ -165,14 +143,11 @@ jobs:
env: env:
PACK: ${{ runner.temp }}/pack PACK: ${{ runner.temp }}/pack
- name: Checkout repository
uses: actions/checkout@v3
- name: Create CodeQL config file - name: Create CodeQL config file
run: | run: |
echo "paths:" > ${CONF}
echo " - ${FOLDER}" >> ${CONF}
echo "paths-ignore:" >> ${CONF} echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF} echo " - ql/ql/test" >> ${CONF}
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
echo "disable-default-queries: true" >> ${CONF} echo "disable-default-queries: true" >> ${CONF}
echo "packs:" >> ${CONF} echo "packs:" >> ${CONF}
echo " - codeql/ql" >> ${CONF} echo " - codeql/ql" >> ${CONF}
@@ -180,24 +155,34 @@ jobs:
cat ${CONF} cat ${CONF}
env: env:
CONF: ./ql-for-ql-config.yml CONF: ./ql-for-ql-config.yml
FOLDER: ${{ matrix.folder }}
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980 uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with: with:
languages: ql languages: ql
db-location: ${{ runner.temp }}/db db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml config-file: ./ql-for-ql-config.yml
tools: latest
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980 uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with: with:
category: "ql-for-ql-${{ matrix.folder }}" category: "ql-for-ql"
- name: Copy sarif file to CWD - name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./${{ matrix.folder }}.sarif run: cp ../results/ql.sarif ./ql-for-ql.sarif
- name: Fixup the $scema in sarif # Until https://github.com/microsoft/sarif-vscode-extension/pull/436/ is part in a stable release
run: |
sed -i 's/\$schema.*/\$schema": "https:\/\/raw.githubusercontent.com\/oasis-tcs\/sarif-spec\/master\/Schemata\/sarif-schema-2.1.0",/' ql-for-ql.sarif
- name: Sarif as artifact - name: Sarif as artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ${{ matrix.folder }}.sarif name: ql-for-ql.sarif
path: ${{ matrix.folder }}.sarif path: ql-for-ql.sarif
- name: Split out the sarif file into langs
run: |
mkdir split-sarif
node ./ql/scripts/split-sarif.js ql-for-ql.sarif split-sarif
- name: Upload langs as artifacts
uses: actions/upload-artifact@v3
with:
name: ql-for-ql-langs
path: split-sarif
retention-days: 1

View File

@@ -36,7 +36,7 @@ jobs:
ql/target ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }} key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Build Extractor - name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./scripts/create-extractor-pack.sh
env: env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }} CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Checkout ${{ matrix.repo }} - name: Checkout ${{ matrix.repo }}

View File

@@ -36,7 +36,7 @@ jobs:
run: | run: |
cd ql; cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }}); codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh env "PATH=$PATH:$codeqlpath" ./scripts/create-extractor-pack.sh
- name: Run QL tests - name: Run QL tests
run: | run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test "${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test

View File

@@ -10,6 +10,7 @@ on:
pull_request: pull_request:
paths: paths:
- '.github/workflows/query-list.yml' - '.github/workflows/query-list.yml'
- '.github/actions/fetch-codeql'
- 'misc/scripts/generate-code-scanning-query-list.py' - 'misc/scripts/generate-code-scanning-query-list.py'
jobs: jobs:
@@ -29,8 +30,6 @@ jobs:
- name: Download CodeQL CLI - name: Download CodeQL CLI
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo # Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
uses: ./codeql/.github/actions/fetch-codeql uses: ./codeql/.github/actions/fetch-codeql
- name: Unzip CodeQL CLI
run: unzip -d codeql-cli codeql-linux64.zip
- name: Build code scanning query list - name: Build code scanning query list
run: | run: |
python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "ruby/**" - "ruby/**"
- .github/workflows/ruby-build.yml - .github/workflows/ruby-build.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main
@@ -13,6 +14,7 @@ on:
paths: paths:
- "ruby/**" - "ruby/**"
- .github/workflows/ruby-build.yml - .github/workflows/ruby-build.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main
@@ -90,19 +92,14 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Fetch CodeQL - name: Fetch CodeQL
run: | uses: ./.github/actions/fetch-codeql
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 - name: Build Query Pack
run: | run: |
codeql/codeql pack create ql/lib --output target/packs codeql pack create ql/lib --output target/packs
codeql/codeql pack install ql/src codeql pack install ql/src
codeql/codeql pack create ql/src --output target/packs codeql pack create ql/src --output target/packs
PACK_FOLDER=$(readlink -f target/packs/codeql/ruby-queries/*) 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 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}/{}" \;) (cd ql/src; find queries \( -name '*.qhelp' -o -name '*.rb' -o -name '*.erb' \) -exec bash -c 'mkdir -p "'"${PACK_FOLDER}"'/$(dirname "{}")"' \; -exec cp "{}" "${PACK_FOLDER}/{}" \;)
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
@@ -179,19 +176,15 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: [package] needs: [package]
steps: steps:
- uses: actions/checkout@v3
- name: Fetch CodeQL
uses: ./.github/actions/fetch-codeql
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
repository: Shopify/example-ruby-app repository: Shopify/example-ruby-app
ref: 67a0decc5eb550f3a9228eda53925c3afd40dfe9 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 - name: Download Ruby bundle
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
with: with:
@@ -215,12 +208,12 @@ jobs:
- name: Run QL test - name: Run QL test
shell: bash shell: bash
run: | run: |
"${{ runner.temp }}/codeql/codeql" test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" . codeql test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" .
- name: Create database - name: Create database
shell: bash shell: bash
run: | run: |
"${{ runner.temp }}/codeql/codeql" database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root . ../database codeql database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root . ../database
- name: Analyze database - name: Analyze database
shell: bash shell: bash
run: | 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 codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "ruby/**" - "ruby/**"
- .github/workflows/ruby-qltest.yml - .github/workflows/ruby-qltest.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main
@@ -13,6 +14,7 @@ on:
paths: paths:
- "ruby/**" - "ruby/**"
- .github/workflows/ruby-qltest.yml - .github/workflows/ruby-qltest.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "swift/**" - "swift/**"
- .github/workflows/swift-codegen.yml - .github/workflows/swift-codegen.yml
- .github/actions/fetch-codeql
branches: branches:
- main - main

View File

@@ -0,0 +1,35 @@
name: "Swift: Run Integration Tests"
on:
pull_request:
paths:
- "swift/**"
- .github/workflows/swift-integration-tests.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml
branches:
- main
defaults:
run:
working-directory: swift
jobs:
integration-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
# - macos-latest TODO
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v3
- name: Build Swift extractor
run: |
bazel run //swift:create-extractor-pack
- name: Run integration tests
run: |
python integration-tests/runner.py

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "swift/**" - "swift/**"
- .github/workflows/swift-qltest.yml - .github/workflows/swift-qltest.yml
- .github/actions/fetch-codeql
- codeql-workspace.yml - codeql-workspace.yml
branches: branches:
- main - main

View File

@@ -5,6 +5,7 @@ on:
paths: paths:
- "*/ql/*/change-notes/**/*" - "*/ql/*/change-notes/**/*"
- ".github/workflows/validate-change-notes.yml" - ".github/workflows/validate-change-notes.yml"
- ".github/actions/fetch-codeql"
branches: branches:
- main - main
- "rc/*" - "rc/*"
@@ -12,6 +13,7 @@ on:
paths: paths:
- "*/ql/*/change-notes/**/*" - "*/ql/*/change-notes/**/*"
- ".github/workflows/validate-change-notes.yml" - ".github/workflows/validate-change-notes.yml"
- ".github/actions/fetch-codeql"
jobs: jobs:
check-change-note: check-change-note:

View File

@@ -42,3 +42,4 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers /.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers /.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
/.github/workflows/ruby-* @github/codeql-ruby /.github/workflows/ruby-* @github/codeql-ruby
/.github/workflows/swift-* @github/codeql-c

View File

@@ -453,11 +453,11 @@
"python/ql/src/Lexical/CommentedOutCodeReferences.inc.qhelp" "python/ql/src/Lexical/CommentedOutCodeReferences.inc.qhelp"
], ],
"IDE Contextual Queries": [ "IDE Contextual Queries": [
"cpp/ql/src/IDEContextual.qll", "cpp/ql/lib/IDEContextual.qll",
"csharp/ql/src/IDEContextual.qll", "csharp/ql/lib/IDEContextual.qll",
"java/ql/src/IDEContextual.qll", "java/ql/lib/IDEContextual.qll",
"javascript/ql/src/IDEContextual.qll", "javascript/ql/lib/IDEContextual.qll",
"python/ql/src/analysis/IDEContextual.qll" "python/ql/lib/analysis/IDEContextual.qll"
], ],
"SSA C#": [ "SSA C#": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",

View File

@@ -0,0 +1,17 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 330 <= kind and kind <= 334)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 0 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add new builtin operations
compatibility: partial
exprs.rel: run exprs.qlo

View File

@@ -1,3 +1,19 @@
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.
## 0.3.0
### Deprecated APIs
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
### Bug Fixes
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
## 0.2.3 ## 0.2.3
### New Features ### New Features

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.

View File

@@ -0,0 +1,9 @@
## 0.3.0
### Deprecated APIs
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
### Bug Fixes
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.

View File

@@ -0,0 +1,5 @@
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.2.3 lastReleaseVersion: 0.3.1

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.3.0-dev version: 0.3.2-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -6,6 +6,7 @@
import semmle.code.cpp.Location import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/** /**
* Get the `Element` that represents this `@element`. * Get the `Element` that represents this `@element`.
@@ -28,9 +29,12 @@ Element mkElement(@element e) { unresolveElement(result) = e }
pragma[inline] pragma[inline]
@element unresolveElement(Element e) { @element unresolveElement(Element e) {
not result instanceof @usertype and not result instanceof @usertype and
not result instanceof @variable and
result = e result = e
or or
e = resolveClass(result) e = resolveClass(result)
or
e = resolveGlobalVariable(result)
} }
/** /**

View File

@@ -6,6 +6,7 @@ import semmle.code.cpp.Element
import semmle.code.cpp.exprs.Access import semmle.code.cpp.exprs.Access
import semmle.code.cpp.Initializer import semmle.code.cpp.Initializer
private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/** /**
* A C/C++ variable. For example, in the following code there are four * A C/C++ variable. For example, in the following code there are four
@@ -32,6 +33,8 @@ private import semmle.code.cpp.internal.ResolveClass
* can have multiple declarations. * can have multiple declarations.
*/ */
class Variable extends Declaration, @variable { class Variable extends Declaration, @variable {
Variable() { isVariable(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "Variable" } override string getAPrimaryQlClass() { result = "Variable" }
/** Gets the initializer of this variable, if any. */ /** Gets the initializer of this variable, if any. */

View File

@@ -46,7 +46,7 @@ predicate nullCheckExpr(Expr checkExpr, Variable var) {
or or
exists(LogicalAndExpr op, AnalysedExpr child | exists(LogicalAndExpr op, AnalysedExpr child |
expr = op and expr = op and
op.getRightOperand() = child and op.getAnOperand() = child and
nullCheckExpr(child, v) nullCheckExpr(child, v)
) )
or or
@@ -99,7 +99,7 @@ predicate validCheckExpr(Expr checkExpr, Variable var) {
or or
exists(LogicalAndExpr op, AnalysedExpr child | exists(LogicalAndExpr op, AnalysedExpr child |
expr = op and expr = op and
op.getRightOperand() = child and op.getAnOperand() = child and
validCheckExpr(child, v) validCheckExpr(child, v)
) )
or or
@@ -169,7 +169,10 @@ class AnalysedExpr extends Expr {
*/ */
predicate isDef(LocalScopeVariable v) { predicate isDef(LocalScopeVariable v) {
this.inCondition() and this.inCondition() and
this.(Assignment).getLValue() = v.getAnAccess() (
this.(Assignment).getLValue() = v.getAnAccess() or
this.(ConditionDeclExpr).getVariableAccess() = v.getAnAccess()
)
} }
/** /**

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -1,5 +1,5 @@
/** /**
* Provides classes for modeling built-in operations. Built-in operations are * Provides classes for modeling built-in operations. Built-in operations are
* typically compiler specific and are used by libraries and generated code. * typically compiler specific and are used by libraries and generated code.
*/ */
@@ -120,8 +120,8 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
/** /**
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations * A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence * of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a GNU/Clang extension. * of an overloaded `operator &`). This is a gcc/clang extension.
* ``` * ```
* struct S { * struct S {
* int a, b; * int a, b;
@@ -137,8 +137,8 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
/** /**
* A C/C++ `__INTADDR__` built-in operation (used by some implementations * A C/C++ `__INTADDR__` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence * of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension. * of an overloaded `operator &`). This is an EDG extension.
* ``` * ```
* struct S { * struct S {
* int a, b; * int a, b;
@@ -173,7 +173,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
* *
* Returns `true` if the type has a copy constructor. * Returns `true` if the type has a copy constructor.
* ``` * ```
* std::integral_constant< bool, __has_copy(_Tp)> hc; * std::integral_constant<bool, __has_copy(_Tp)> hc;
* ``` * ```
*/ */
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr { class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
@@ -189,7 +189,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
* Returns `true` if a copy assignment operator has an empty exception * Returns `true` if a copy assignment operator has an empty exception
* specification. * specification.
* ``` * ```
* std::integral_constant< bool, __has_nothrow_assign(_Tp)> hnta; * std::integral_constant<bool, __has_nothrow_assign(_Tp)> hnta;
* ``` * ```
*/ */
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign { class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
@@ -220,7 +220,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
* *
* Returns `true` if the copy constructor has an empty exception specification. * Returns `true` if the copy constructor has an empty exception specification.
* ``` * ```
* std::integral_constant< bool, __has_nothrow_copy(MyType) >; * std::integral_constant<bool, __has_nothrow_copy(MyType) >;
* ``` * ```
*/ */
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy { class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
@@ -266,7 +266,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
* *
* Returns true if the type has a trivial copy constructor. * Returns true if the type has a trivial copy constructor.
* ``` * ```
* std::integral_constant< bool, __has_trivial_copy(MyType) > htc; * std::integral_constant<bool, __has_trivial_copy(MyType)> htc;
* ``` * ```
*/ */
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy { class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
@@ -468,7 +468,7 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
* ``` * ```
* template<typename _Tp1, typename _Tp2> * template<typename _Tp1, typename _Tp2>
* struct types_compatible * struct types_compatible
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2) > * : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2)>
* { }; * { };
* ``` * ```
*/ */
@@ -479,8 +479,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
/** /**
* A clang `__builtin_shufflevector` expression. * A clang `__builtin_shufflevector` expression.
* *
* It outputs a permutation of elements from one or two input vectors. * It outputs a permutation of elements from one or two input vectors. See
* Please see
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector * https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
* for more information. * for more information.
* ``` * ```
@@ -494,11 +493,29 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" } override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
} }
/**
* A gcc `__builtin_shuffle` expression.
*
* It outputs a permutation of elements from one or two input vectors.
* See https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
* for more information.
* ```
* // Concatenate every other element of 4-element vectors V1 and V2.
* M = {0, 2, 4, 6};
* V3 = __builtin_shuffle(V1, V2, M);
* ```
*/
class BuiltInOperationBuiltInShuffle extends BuiltInOperation, @builtinshuffle {
override string toString() { result = "__builtin_shuffle" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffle" }
}
/** /**
* A clang `__builtin_convertvector` expression. * A clang `__builtin_convertvector` expression.
* *
* Allows for conversion of vectors of equal element count and compatible * Allows for conversion of vectors of equal element count and compatible
* element types. Please see * element types. See
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector * https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
* for more information. * for more information.
* ``` * ```
@@ -547,7 +564,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
* ``` * ```
* template<typename T, typename... Args> * template<typename T, typename... Args>
* struct is_trivially_constructible * struct is_trivially_constructible
* : public integral_constant<bool, __is_trivially_constructible(T, Args...) > * : public integral_constant<bool, __is_trivially_constructible(T, Args...)>
* { }; * { };
* ``` * ```
*/ */
@@ -612,13 +629,10 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
* The `__is_trivially_assignable` built-in operation (used by some * The `__is_trivially_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header). * implementations of the `<type_traits>` header).
* *
* Returns `true` if the assignment operator `C::operator =(const C& c)` is * Returns `true` if the assignment operator `C::operator =(const D& d)` is
* trivial. * trivial (i.e., it will not call any operation that is non-trivial).
* ``` * ```
* template<typename T> * bool v = __is_trivially_assignable(MyType1, MyType2);
* struct is_trivially_assignable
* : public integral_constant<bool, __is_trivially_assignable(T) >
* { };
* ``` * ```
*/ */
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr { class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
@@ -631,10 +645,10 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
* The `__is_nothrow_assignable` built-in operation (used by some * The `__is_nothrow_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header). * implementations of the `<type_traits>` header).
* *
* Returns true if there exists a `C::operator =(const C& c) nothrow` * Returns true if there exists a `C::operator =(const D& d) nothrow`
* assignment operator (i.e, with an empty exception specification). * assignment operator (i.e, with an empty exception specification).
* ``` * ```
* bool v = __is_nothrow_assignable(MyType); * bool v = __is_nothrow_assignable(MyType1, MyType2);
* ``` * ```
*/ */
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr { class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
@@ -643,15 +657,30 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
} }
/**
* The `__is_assignable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d)` assignment
* operator.
* ```
* bool v = __is_assignable(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
override string toString() { result = "__is_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
}
/** /**
* The `__is_standard_layout` built-in operation (used by some implementations * The `__is_standard_layout` built-in operation (used by some implementations
* of the `<type_traits>` header). * of the `<type_traits>` header).
* *
* Returns `true` if the type is a primitive type, or a `class`, `struct` or * Returns `true` if the type is a primitive type, or a `class`, `struct` or
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member * `union` without (1) virtual functions or base classes, (2) reference member
* variable or (3) multiple occurrences of base `class` objects, among other * variable, or (3) multiple occurrences of base `class` objects, among other
* restrictions. Please see * restrictions. See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* for more information. * for more information.
* ``` * ```
* bool v = __is_standard_layout(MyType); * bool v = __is_standard_layout(MyType);
@@ -668,7 +697,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
* implementations of the `<type_traits>` header). * implementations of the `<type_traits>` header).
* *
* Returns `true` if instances of this type can be copied by trivial * Returns `true` if instances of this type can be copied by trivial
* means. The copying is done in a manner similar to the `memcpy` * means. The copying is done in a manner similar to the `memcpy`
* function. * function.
*/ */
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr { class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
@@ -682,13 +711,13 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
* the `<type_traits>` header). * the `<type_traits>` header).
* *
* Returns `true` if the type is a scalar type, a reference type or an array of * Returns `true` if the type is a scalar type, a reference type or an array of
* literal types, among others. Please see * literal types, among others. See
* https://en.cppreference.com/w/cpp/named_req/LiteralType * https://en.cppreference.com/w/cpp/named_req/LiteralType
* for more information. * for more information.
* *
* ``` * ```
* template <typename _Tp> * template <typename _Tp>
* std::integral_constant< bool, __is_literal_type(_Tp)> ilt; * std::integral_constant<bool, __is_literal_type(_Tp)> ilt;
* ``` * ```
*/ */
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr { class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
@@ -705,7 +734,7 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
* compiler, with semantics of the `memcpy` operation. * compiler, with semantics of the `memcpy` operation.
* ``` * ```
* template <typename _Tp> * template <typename _Tp>
* std::integral_constant< bool, __has_trivial_move_constructor(_Tp)> htmc; * std::integral_constant<bool, __has_trivial_move_constructor(_Tp)> htmc;
* ``` * ```
*/ */
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation, class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@@ -723,7 +752,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
* ``` * ```
* template<typename T> * template<typename T>
* struct has_trivial_move_assign * struct has_trivial_move_assign
* : public integral_constant<bool, __has_trivial_move_assign(T) > * : public integral_constant<bool, __has_trivial_move_assign(T)>
* { }; * { };
* ``` * ```
*/ */
@@ -758,7 +787,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
* ``` * ```
* template<typename T, typename... Args> * template<typename T, typename... Args>
* struct is_constructible * struct is_constructible
* : public integral_constant<bool, __is_constructible(T, Args...) > * : public integral_constant<bool, __is_constructible(T, Args...)>
* { }; * { };
* ``` * ```
*/ */
@@ -785,7 +814,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
} }
/** /**
* The `__has_finalizer` built-in operation. This is a Microsoft extension. * The `__has_finalizer` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called * Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called
* from either the regular destructor or the garbage collector. * from either the regular destructor or the garbage collector.
@@ -800,10 +829,10 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
} }
/** /**
* The `__is_delegate` built-in operation. This is a Microsoft extension. * The `__is_delegate` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if the function has been declared as a `delegate`, used in * Returns `true` if the function has been declared as a `delegate`, used in
* message forwarding. Please see * message forwarding. See
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions * https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
* for more information. * for more information.
*/ */
@@ -814,9 +843,9 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
} }
/** /**
* The `__is_interface_class` built-in operation. This is a Microsoft extension. * The `__is_interface_class` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if the type has been declared as an `interface`. Please see * Returns `true` if the type has been declared as an `interface`. See
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions * https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
* for more information. * for more information.
*/ */
@@ -827,9 +856,9 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
} }
/** /**
* The `__is_ref_array` built-in operation. This is a Microsoft extension. * The `__is_ref_array` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if the object passed in is a _platform array_. Please see * Returns `true` if the object passed in is a _platform array_. See
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions * https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
* for more information. * for more information.
* ``` * ```
@@ -844,9 +873,9 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
} }
/** /**
* The `__is_ref_class` built-in operation. This is a Microsoft extension. * The `__is_ref_class` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if the type is a _reference class_. Please see * Returns `true` if the type is a _reference class_. See
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions * https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* for more information. * for more information.
* ``` * ```
@@ -861,10 +890,10 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
} }
/** /**
* The `__is_sealed` built-in operation. This is a Microsoft extension. * The `__is_sealed` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if a given class or virtual function is marked as `sealed`, * Returns `true` if a given class or virtual function is marked as `sealed`,
* meaning that it cannot be extended or overridden. The `sealed` keyword * meaning that it cannot be extended or overridden. The `sealed` keyword
* is similar to the C++11 `final` keyword. * is similar to the C++11 `final` keyword.
* ``` * ```
* ref class X sealed { * ref class X sealed {
@@ -879,7 +908,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
} }
/** /**
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension. * The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if passed a value type that contains no references to the * Returns `true` if passed a value type that contains no references to the
* garbage-collected heap. * garbage-collected heap.
@@ -898,9 +927,9 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
} }
/** /**
* The `__is_value_class` built-in operation. This is a Microsoft extension. * The `__is_value_class` built-in operation. This is a Microsoft extension.
* *
* Returns `true` if passed a value type. Please see * Returns `true` if passed a value type. See
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions * https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* For more information. * For more information.
* ``` * ```
@@ -922,7 +951,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
* ``` * ```
* template<typename T> * template<typename T>
* struct is_final * struct is_final
* : public integral_constant<bool, __is_final(T) > * : public integral_constant<bool, __is_final(T)>
* { }; * { };
* ``` * ```
*/ */
@@ -933,7 +962,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
} }
/** /**
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension. * The `__builtin_choose_expr` expression. This is a gcc/clang extension.
* *
* The expression functions similarly to the ternary `?:` operator, except * The expression functions similarly to the ternary `?:` operator, except
* that it is evaluated at compile-time. * that it is evaluated at compile-time.
@@ -978,3 +1007,50 @@ class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
/** Gets the operand corresponding to the imaginary part of the complex number. */ /** Gets the operand corresponding to the imaginary part of the complex number. */
Expr getImaginaryOperand() { this.hasChild(result, 1) } Expr getImaginaryOperand() { this.hasChild(result, 1) }
} }
/**
* A C++ `__is_aggregate` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type has is an aggregate type.
* ```
* std::integral_constant<bool, __is_aggregate(_Tp)> ia;
* ```
*/
class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
override string toString() { result = "__is_aggregate" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAggregate" }
}
/**
* A C++ `__has_unique_object_representations` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is trivially copyable and if the object representation
* is unique for two objects with the same value.
* ```
* bool v = __has_unique_object_representations(MyType);
* ```
*/
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
@hasuniqueobjectrepresentations {
override string toString() { result = "__has_unique_object_representations" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
}
/**
* A C/C++ `__builtin_bit_cast` built-in operation (used by some implementations
* of `std::bit_cast`).
*
* Performs a bit cast from a value to a type.
* ```
* __builtin_bit_cast(Type, value);
* ```
*/
class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
override string toString() { result = "__builtin_bit_cast" }
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
}

View File

@@ -255,8 +255,10 @@ class FunctionCall extends Call, @funbindexpr {
/** /**
* Gets the function called by this call. * Gets the function called by this call.
* *
* In the case of virtual function calls, the result is the most-specific function in the override tree (as * In the case of virtual function calls, the result is the most-specific function in the override tree
* determined by the compiler) such that the target at runtime will be one of `result.getAnOverridingFunction*()`. * such that the target at runtime will be one of `result.getAnOverridingFunction*()`. The most-specific
* function is determined by the compiler based on the compile time type of the object the function is a
* member of.
*/ */
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) } override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }

View File

@@ -596,9 +596,12 @@ class ParenthesisExpr extends Conversion, @parexpr {
} }
/** /**
* A C/C++ expression that has not been resolved. * A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
* *
* It is assigned `ErroneousType` as its type. * If the expression could not be resolved, it has type `ErroneousType`. In the
* case of a database upgrade or downgrade, the original type from before the
* upgrade or downgrade is kept if that type can be represented.
*/ */
class ErrorExpr extends Expr, @errorexpr { class ErrorExpr extends Expr, @errorexpr {
override string toString() { result = "<error expr>" } override string toString() { result = "<error expr>" }

View File

@@ -0,0 +1,57 @@
private predicate hasDefinition(@globalvariable g) {
exists(@var_decl vd | var_decls(vd, g, _, _, _) | var_def(vd))
}
private predicate onlyOneCompleteGlobalVariableExistsWithMangledName(@mangledname name) {
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name)) = 1
}
/** Holds if `g` is a unique global variable with a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithDefinition(@mangledname name, @globalvariable g) {
hasDefinition(g) and
mangled_name(g, name) and
onlyOneCompleteGlobalVariableExistsWithMangledName(name)
}
/** Holds if `g` is a global variable without a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithoutDefinition(@mangledname name, @globalvariable g) {
not hasDefinition(g) and
mangled_name(g, name)
}
/**
* Holds if `incomplete` is a global variable without a definition, and there exists
* a unique global variable `complete` with the same name that does have a definition.
*/
private predicate hasTwinWithDefinition(@globalvariable incomplete, @globalvariable complete) {
exists(@mangledname name |
not variable_instantiation(incomplete, complete) and
isGlobalWithMangledNameAndWithoutDefinition(name, incomplete) and
isGlobalWithMangledNameAndWithDefinition(name, complete)
)
}
import Cached
cached
private module Cached {
/**
* If `v` is a global variable without a definition, and there exists a unique
* global variable with the same name that does have a definition, then the
* result is that unique global variable. Otherwise, the result is `v`.
*/
cached
@variable resolveGlobalVariable(@variable v) {
hasTwinWithDefinition(v, result)
or
not hasTwinWithDefinition(v, _) and
result = v
}
cached
predicate isVariable(@variable v) {
not v instanceof @globalvariable
or
v = resolveGlobalVariable(_)
}
}

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
or or
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
) )
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
jumpStepCached(n1, n2) and jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
) )
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 | exists(Node n1, Node n2 |
node1.asNode() = n1 and node1.asNode() = n1 and
node2.asNode() = n2 and node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic] pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(node1.asNode(), c, node2.asNode()) and readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
or or
exists(Node n | exists(Node n |
@@ -562,7 +562,8 @@ pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) { ) {
store(node1.asNode(), tc, node2.asNode(), contentType) and store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
read(_, tc.getContent(), _, config) and read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config) stepFilter(node1, node2, config)
} }

View File

@@ -1650,6 +1650,11 @@ case @expr.kind of
| 327 = @co_await | 327 = @co_await
| 328 = @co_yield | 328 = @co_yield
| 329 = @temp_init | 329 = @temp_init
| 330 = @isassignable
| 331 = @isaggregate
| 332 = @hasuniqueobjectrepresentations
| 333 = @builtinbitcast
| 334 = @builtinshuffle
; ;
@var_args_expr = @vastartexpr @var_args_expr = @vastartexpr
@@ -1711,6 +1716,11 @@ case @expr.kind of
| @isfinalexpr | @isfinalexpr
| @builtinchooseexpr | @builtinchooseexpr
| @builtincomplex | @builtincomplex
| @isassignable
| @isaggregate
| @hasuniqueobjectrepresentations
| @builtinbitcast
| @builtinshuffle
; ;
new_allocated_type( new_allocated_type(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add new builtin operations
compatibility: backwards

View File

@@ -1,3 +1,11 @@
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.
## 0.2.0
## 0.1.4 ## 0.1.4
## 0.1.3 ## 0.1.3

View File

@@ -44,7 +44,7 @@ predicate whiteListWrapped(FunctionCall fc) {
from FunctionCall c, FloatingPointType t1, IntegralType t2 from FunctionCall c, FloatingPointType t1, IntegralType t2
where where
t1 = c.getTarget().getType().getUnderlyingType() and pragma[only_bind_into](t1) = c.getTarget().getType().getUnderlyingType() and
t2 = c.getActualType() and t2 = c.getActualType() and
c.hasImplicitConversion() and c.hasImplicitConversion() and
not whiteListWrapped(c) not whiteListWrapped(c)

View File

@@ -10,7 +10,6 @@
* @precision medium * @precision medium
* @tags security * @tags security
* external/cwe/cwe-480 * external/cwe/cwe-480
* external/microsoft/c6317
*/ */
import cpp import cpp

View File

@@ -7,8 +7,7 @@
* @problem.severity error * @problem.severity error
* @precision high * @precision high
* @id cpp/string-copy-return-value-as-boolean * @id cpp/string-copy-return-value-as-boolean
* @tags external/microsoft/C6324 * @tags correctness
* correctness
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @id cpp/inconsistent-loop-direction * @id cpp/inconsistent-loop-direction
* @tags correctness * @tags correctness
* external/cwe/cwe-835 * external/cwe/cwe-835
* external/microsoft/6293
* @msrc.severity important * @msrc.severity important
*/ */

View File

@@ -18,7 +18,7 @@ import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.MustFlow import semmle.code.cpp.ir.dataflow.MustFlow
import PathGraph import PathGraph
/** Holds if `f` has a name that we intrepret as evidence of intentionally returning the value of the stack pointer. */ /** Holds if `f` has a name that we interpret as evidence of intentionally returning the value of the stack pointer. */
predicate intentionallyReturnsStackPointer(Function f) { predicate intentionallyReturnsStackPointer(Function f) {
f.getName().toLowerCase().matches(["%stack%", "%sp%"]) f.getName().toLowerCase().matches(["%stack%", "%sp%"])
} }
@@ -74,13 +74,12 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
from from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var, MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
ReturnStackAllocatedMemoryConfig conf, Function f ReturnStackAllocatedMemoryConfig conf
where where
conf.hasFlowPath(source, sink) and conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
source.getNode().asInstruction() = var and source.getNode().asInstruction() = var and
// Only raise an alert if we're returning from the _same_ callable as the on that // Only raise an alert if we're returning from the _same_ callable as the on that
// declared the stack variable. // declared the stack variable.
var.getEnclosingFunction() = pragma[only_bind_into](f) and var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
sink.getNode().getEnclosingCallable() = pragma[only_bind_into](f)
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(), select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
var.getAst().toString() var.getAst().toString()

View File

@@ -133,7 +133,9 @@ TGlobalAddress globalAddress(Instruction instr) {
) )
or or
exists(FieldAddressInstruction fai | instr = fai | exists(FieldAddressInstruction fai | instr = fai |
result = TFieldAddress(globalAddress(fai.getObjectAddress()), fai.getField()) result =
TFieldAddress(globalAddress(pragma[only_bind_into](fai.getObjectAddress())),
pragma[only_bind_out](fai.getField()))
) )
or or
result = globalAddress(instr.(PointerOffsetInstruction).getLeft()) result = globalAddress(instr.(PointerOffsetInstruction).getLeft())

View File

@@ -15,6 +15,7 @@ class VariableAccessInInitializer extends VariableAccess {
Variable var; Variable var;
Initializer init; Initializer init;
pragma[nomagic]
VariableAccessInInitializer() { VariableAccessInInitializer() {
init.getDeclaration() = var and init.getDeclaration() = var and
init.getExpr().getAChild*() = this init.getExpr().getAChild*() = this

View File

@@ -77,7 +77,7 @@ class ExecState extends DataFlow::FlowState {
ExecState() { ExecState() {
this = this =
"ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and "ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and
interestingConcatenation(fst, snd) interestingConcatenation(pragma[only_bind_into](fst), pragma[only_bind_into](snd))
} }
DataFlow::Node getFstNode() { result = fst } DataFlow::Node getFstNode() { result = fst }

View File

@@ -8,11 +8,6 @@
* @precision high * @precision high
* @tags security * @tags security
* external/cwe/cwe-253 * external/cwe/cwe-253
* external/microsoft/C6214
* external/microsoft/C6215
* external/microsoft/C6216
* external/microsoft/C6217
* external/microsoft/C6230
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @msrc.severity important * @msrc.severity important
* @tags security * @tags security
* external/cwe/cwe-428 * external/cwe/cwe-428
* external/microsoft/C6277
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @precision high * @precision high
* @tags security * @tags security
* external/cwe/cwe-704 * external/cwe/cwe-704
* external/microsoft/c/c6276
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* @precision high * @precision high
* @tags security * @tags security
* external/cwe/cwe-732 * external/cwe/cwe-732
* external/microsoft/C6248
*/ */
import cpp import cpp

View File

@@ -0,0 +1 @@
## 0.2.0

View File

@@ -0,0 +1,5 @@
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.1.4 lastReleaseVersion: 0.3.0

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.2.0-dev version: 0.3.1-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --clang
struct mystruct { struct mystruct {
int f1; int f1;
int f2; int f2;
@@ -13,3 +13,6 @@ void f(void) {
int i2 = edg_offsetof(struct mystruct,f2); int i2 = edg_offsetof(struct mystruct,f2);
} }
void g(void) {
double f = __builtin_bit_cast(double,42l);
}

View File

@@ -13,3 +13,6 @@
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 | | edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 | | edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
| edg.c:13:43:13:44 | f2 | 0 | 0 | | edg.c:13:43:13:44 | f2 | 0 | 0 |
| edg.c:17:16:17:45 | __builtin_bit_cast | 1 | 1 |
| edg.c:17:16:17:45 | double | 0 | 0 |
| edg.c:17:42:17:44 | 42 | 1 | 1 |

View File

@@ -296,3 +296,20 @@
| ms.cpp:255:24:255:43 | a_struct | | <none> | | ms.cpp:255:24:255:43 | a_struct | | <none> |
| ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 | | ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 |
| ms.cpp:256:24:256:49 | a_final_struct | | <none> | | ms.cpp:256:24:256:49 | a_final_struct | | <none> |
| ms.cpp:258:29:258:62 | __is_assignable | a_struct,a_struct | 1 |
| ms.cpp:258:29:258:62 | a_struct | | <none> |
| ms.cpp:258:29:258:62 | a_struct | | <none> |
| ms.cpp:259:29:259:59 | __is_assignable | a_struct,empty | 0 |
| ms.cpp:259:29:259:59 | a_struct | | <none> |
| ms.cpp:259:29:259:59 | empty | | <none> |
| ms.cpp:260:29:260:57 | __is_assignable | a_struct,int | 0 |
| ms.cpp:260:29:260:57 | a_struct | | <none> |
| ms.cpp:260:29:260:57 | int | | <none> |
| ms.cpp:262:28:262:51 | __is_aggregate | a_struct | 1 |
| ms.cpp:262:28:262:51 | a_struct | | <none> |
| ms.cpp:263:28:263:46 | __is_aggregate | int | 0 |
| ms.cpp:263:28:263:46 | int | | <none> |
| ms.cpp:265:49:265:88 | __has_unique_object_representations | int | 1 |
| ms.cpp:265:49:265:88 | int | | <none> |
| ms.cpp:266:49:266:90 | __has_unique_object_representations | float | 0 |
| ms.cpp:266:49:266:90 | float | | <none> |

View File

@@ -254,5 +254,14 @@ void f(void) {
bool b_is_final1 = __is_final(a_struct); bool b_is_final1 = __is_final(a_struct);
bool b_is_final2 = __is_final(a_final_struct); bool b_is_final2 = __is_final(a_final_struct);
}
bool b_is_assignable1 = __is_assignable(a_struct,a_struct);
bool b_is_assignable2 = __is_assignable(a_struct,empty);
bool b_is_assignable3 = __is_assignable(a_struct,int);
bool b_is_aggregate1 = __is_aggregate(a_struct);
bool b_is_aggregate2 = __is_aggregate(int);
bool b_has_unique_object_representations1 = __has_unique_object_representations(int);
bool b_has_unique_object_representations2 = __has_unique_object_representations(float);
}

View File

@@ -0,0 +1,20 @@
| test.cpp:9:9:9:9 | v | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:10:9:10:10 | ! ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:11:9:11:14 | ... == ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:12:9:12:17 | ... == ... | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:13:9:13:14 | ... != ... | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:14:9:14:17 | ... != ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:15:8:15:23 | call to __builtin_expect | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:16:8:16:23 | call to __builtin_expect | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:17:9:17:17 | ... && ... | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:18:9:18:17 | ... && ... | test.cpp:5:13:5:13 | v | is not null | is valid |
| test.cpp:19:9:19:18 | ... && ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:20:9:20:18 | ... && ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:21:9:21:14 | ... = ... | test.cpp:5:13:5:13 | v | is null | is not valid |
| test.cpp:21:9:21:14 | ... = ... | test.cpp:7:10:7:10 | b | is not null | is valid |
| test.cpp:22:9:22:14 | ... = ... | test.cpp:5:13:5:13 | v | is not null | is not valid |
| test.cpp:22:9:22:14 | ... = ... | test.cpp:7:13:7:13 | c | is not null | is not valid |
| test.cpp:22:17:22:17 | c | test.cpp:7:13:7:13 | c | is not null | is valid |
| test.cpp:23:21:23:21 | x | test.cpp:23:14:23:14 | x | is not null | is valid |
| test.cpp:24:9:24:18 | (condition decl) | test.cpp:5:13:5:13 | v | is not null | is not valid |
| test.cpp:24:9:24:18 | (condition decl) | test.cpp:24:14:24:14 | y | is not null | is valid |

View File

@@ -0,0 +1,8 @@
import cpp
from AnalysedExpr a, LocalScopeVariable v, string isNullCheck, string isValidCheck
where
v.getAnAccess().getEnclosingStmt() = a.getParent() and
(if a.isNullCheck(v) then isNullCheck = "is null" else isNullCheck = "is not null") and
(if a.isValidCheck(v) then isValidCheck = "is valid" else isValidCheck = "is not valid")
select a, v, isNullCheck, isValidCheck

View File

@@ -0,0 +1,25 @@
// semmle-extractor-options: -std=c++17
long __builtin_expect(long);
void f(int *v) {
int *w;
bool b, c;
if (v) {}
if (!v) {}
if (v == 0) {}
if ((!v) == 0) {}
if (v != 0) {}
if ((!v) != 0) {}
if(__builtin_expect((long)v)) {}
if(__builtin_expect((long)!v)) {}
if (true && v) {}
if (v && true) {}
if (true && !v) {}
if (!v && true) {}
if (b = !v) {}
if (c = !v; c) {}
if (int *x = v; x) {}
if (int *y = v) {}
}

View File

@@ -4,11 +4,7 @@
| c.c:6:5:6:6 | ls | array of 4 {int} | 1 | | c.c:6:5:6:6 | ls | array of 4 {int} | 1 |
| c.c:8:5:8:7 | iss | array of 4 {array of 2 {int}} | 1 | | c.c:8:5:8:7 | iss | array of 4 {array of 2 {int}} | 1 |
| c.c:12:11:12:11 | i | typedef {int} as "int_alias" | 1 | | c.c:12:11:12:11 | i | typedef {int} as "int_alias" | 1 |
| c.h:4:12:4:13 | ks | array of {int} | 1 |
| c.h:8:12:8:14 | iss | array of {array of 2 {int}} | 1 |
| c.h:10:12:10:12 | i | int | 1 |
| d.cpp:3:7:3:8 | xs | array of {int} | 1 | | d.cpp:3:7:3:8 | xs | array of {int} | 1 |
| d.h:3:14:3:15 | xs | array of 2 {int} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | reference to {const {struct __va_list_tag}} | 1 | | file://:0:0:0:0 | (unnamed parameter 0) | reference to {const {struct __va_list_tag}} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | rvalue reference to {struct __va_list_tag} | 1 | | file://:0:0:0:0 | (unnamed parameter 0) | rvalue reference to {struct __va_list_tag} | 1 |
| file://:0:0:0:0 | fp_offset | unsigned int | 1 | | file://:0:0:0:0 | fp_offset | unsigned int | 1 |

View File

@@ -1,2 +1,4 @@
| vector_types2.cpp:10:15:10:42 | __builtin_shuffle |
| vector_types2.cpp:11:15:11:45 | __builtin_shuffle |
| vector_types.cpp:31:13:31:49 | __builtin_shufflevector | | vector_types.cpp:31:13:31:49 | __builtin_shufflevector |
| vector_types.cpp:58:10:58:52 | __builtin_convertvector | | vector_types.cpp:58:10:58:52 | __builtin_convertvector |

View File

@@ -13,6 +13,12 @@
| file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 | | file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 |
| file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 | | file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 |
| file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 | | file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 |
| vector_types2.cpp:5:7:5:7 | a | a | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:6:7:6:7 | b | b | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:7:7:7:12 | mask_1 | mask_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:8:7:8:12 | mask_2 | mask_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:10:7:10:11 | res_1 | res_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:11:7:11:11 | res_2 | res_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 | | vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 |
| vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 | | vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
| vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 | | vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 |

View File

@@ -0,0 +1,12 @@
// semmle-extractor-options: --gnu --gnu_version 80000
typedef int v4i __attribute__((vector_size (16)));
void f() {
v4i a = {1,2,3,4};
v4i b = {5,6,7,8};
v4i mask_1 = {3,0,1,2};
v4i mask_2 = {3,5,4,2};
v4i res_1 = __builtin_shuffle(a, mask_1);
v4i res_2 = __builtin_shuffle(a, b, mask_2);
}

View File

@@ -1,3 +1,7 @@
## 1.2.1
## 1.2.0
## 1.1.4 ## 1.1.4
## 1.1.3 ## 1.1.3

View File

@@ -0,0 +1 @@
## 1.2.0

View File

@@ -0,0 +1 @@
## 1.2.1

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.1.4 lastReleaseVersion: 1.2.1

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all name: codeql/csharp-solorigate-all
version: 1.2.0-dev version: 1.2.2-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,3 +1,7 @@
## 1.2.1
## 1.2.0
## 1.1.4 ## 1.1.4
## 1.1.3 ## 1.1.3

View File

@@ -0,0 +1 @@
## 1.2.0

View File

@@ -0,0 +1 @@
## 1.2.1

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