Compare commits

..

1 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
ee314a4dad remove javascript 2021-09-29 11:19:08 +02:00
11448 changed files with 115357 additions and 1068029 deletions

View File

@@ -1,27 +1,8 @@
{ { "provide": [ "*/ql/src/qlpack.yml",
"provide": [ "*/ql/lib/qlpack.yml",
"*/ql/src/qlpack.yml", "*/ql/test/qlpack.yml",
"*/ql/lib/qlpack.yml", "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"*/ql/test/qlpack.yml", "*/ql/examples/qlpack.yml",
"*/ql/examples/qlpack.yml", "*/upgrades/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml", "misc/legacy-support/*/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml", "misc/suite-helpers/qlpack.yml" ] }
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/lib/qlpack.yml",
"csharp/ql/campaigns/Solorigate/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/test/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",
"ruby/extractor-pack/codeql-extractor.yml",
"ruby/ql/consistency-queries/qlpack.yml",
"ql/ql/consistency-queries/qlpack.yml",
"ql/extractor-pack/codeql-extractor.yml"
],
"versionPolicies": {
"default": {
"requireChangeNotes": true,
"committedPrereleaseSuffix": "dev",
"committedVersion": "nextPatchRelease"
}
}
}

View File

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

View File

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

View File

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

7
.github/labeler.yml vendored
View File

@@ -18,14 +18,7 @@ Python:
- python/**/* - python/**/*
- change-notes/**/*python* - change-notes/**/*python*
Ruby:
- ruby/**/*
- change-notes/**/*ruby*
documentation: documentation:
- "**/*.qhelp" - "**/*.qhelp"
- "**/*.md" - "**/*.md"
- docs/**/* - docs/**/*
"QL-for-QL":
- ql/**/*

View File

@@ -7,7 +7,6 @@ on:
- "*/ql/src/**/*.ql" - "*/ql/src/**/*.ql"
- "*/ql/src/**/*.qll" - "*/ql/src/**/*.qll"
- "!**/experimental/**" - "!**/experimental/**"
- "!ql/**"
jobs: jobs:
check-change-note: check-change-note:

View File

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

View File

@@ -1,31 +0,0 @@
name: Post pull-request comment
on:
workflow_run:
workflows: ["Query help preview"]
types:
- completed
permissions:
pull-requests: write
jobs:
post_comment:
runs-on: ubuntu-latest
steps:
- name: Download artifact
run: gh run download "${WORKFLOW_RUN_ID}" --repo "${GITHUB_REPOSITORY}" --name "comment"
env:
GITHUB_TOKEN: ${{ github.token }}
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
- run: |
PR="$(grep -o '^[0-9]\+$' pr.txt)"
PR_HEAD_SHA="$(gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR}" --jq .head.sha)"
# Check that the pull-request head SHA matches the head SHA of the workflow run
if [ "${WORKFLOW_RUN_HEAD_SHA}" != "${PR_HEAD_SHA}" ]; then
echo "PR head SHA ${PR_HEAD_SHA} does not match workflow_run event SHA ${WORKFLOW_RUN_HEAD_SHA}. Stopping." 1>&2
exit 1
fi
gh pr comment "${PR}" --repo "${GITHUB_REPOSITORY}" -F comment.txt
env:
GITHUB_TOKEN: ${{ github.token }}
WORKFLOW_RUN_HEAD_SHA: ${{ github.event.workflow_run.head_commit.id }}

View File

@@ -1,63 +0,0 @@
name: Query help preview
permissions:
contents: read
on:
pull_request:
branches:
- main
- "rc/*"
paths:
- "ruby/**/*.qhelp"
jobs:
qhelp:
runs-on: ubuntu-latest
steps:
- run: echo "${{ github.event.number }}" > pr.txt
- uses: actions/upload-artifact@v2
with:
name: comment
path: pr.txt
retention-days: 1
- uses: actions/checkout@v2
with:
fetch-depth: 2
persist-credentials: false
- uses: ./.github/actions/fetch-codeql
- name: Determine changed files
id: changes
run: |
(git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.qhelp$' | grep -z -v '.inc.qhelp';
git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename | xargs --null -rn1 git grep -z -l) |
grep -z '.qhelp$' | grep -z -v '^-' | sort -z -u > "${RUNNER_TEMP}/paths.txt"
- name: QHelp preview
run: |
EXIT_CODE=0
echo "QHelp previews:" > comment.txt
while read -r -d $'\0' path; do
if [ ! -f "${path}" ]; then
exit 1
fi
echo "<details> <summary>${path}</summary>"
echo
codeql generate query-help --format=markdown -- "./${path}" 2> errors.txt || EXIT_CODE="$?"
if [ -s errors.txt ]; then
echo "# errors/warnings:"
echo '```'
cat errors.txt
cat errors.txt 1>&2
echo '```'
fi
echo "</details>"
done < "${RUNNER_TEMP}/paths.txt" >> comment.txt
exit "${EXIT_CODE}"
- if: always()
uses: actions/upload-artifact@v2
with:
name: comment
path: comment.txt
retention-days: 1

View File

@@ -1,192 +0,0 @@
name: Run QL for QL
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
jobs:
queries:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
with:
languages: javascript # does not matter
- name: Get CodeQL version
id: get-codeql-version
run: |
echo "::set-output name=version::$("${CODEQL}" --version | head -n 1 | rev | cut -d " " -f 1 | rev)"
shell: bash
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Cache queries
id: cache-queries
uses: actions/cache@v2
with:
path: ${{ runner.temp }}/query-pack.zip
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}
- name: Build query pack
if: steps.cache-queries.outputs.cache-hit != 'true'
run: |
cd ql/ql/src
"${CODEQL}" pack create
cd .codeql/pack/codeql/ql-all/0.0.0
zip "${PACKZIP}" -r .
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
PACKZIP: ${{ runner.temp }}/query-pack.zip
- name: Upload query pack
uses: actions/upload-artifact@v2
with:
name: query-pack-zip
path: ${{ runner.temp }}/query-pack.zip
extractors:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache entire extractor
id: cache-extractor
uses: actions/cache@v2
with:
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true'
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo fmt --all -- --check
- name: Build
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --verbose
- name: Run tests
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo test --verbose
- name: Release build
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --release
- name: Generate dbscheme
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v2
with:
name: extractor-ubuntu-latest
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
retention-days: 1
package:
runs-on: ubuntu-latest
needs:
- extractors
- queries
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: query-pack-zip
path: query-pack-zip
- uses: actions/download-artifact@v2
with:
name: extractor-ubuntu-latest
path: linux64
- run: |
unzip query-pack-zip/*.zip -d pack
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
mkdir -p pack/tools/linux64
if [[ -f linux64/ql-autobuilder ]]; then
cp linux64/ql-autobuilder pack/tools/linux64/autobuilder
chmod +x pack/tools/linux64/autobuilder
fi
if [[ -f linux64/ql-extractor ]]; then
cp linux64/ql-extractor pack/tools/linux64/extractor
chmod +x pack/tools/linux64/extractor
fi
cd pack
zip -rq ../codeql-ql.zip .
- uses: actions/upload-artifact@v2
with:
name: codeql-ql-pack
path: codeql-ql.zip
retention-days: 1
analyze:
runs-on: ubuntu-latest
strategy:
matrix:
folder: [cpp, csharp, java, javascript, python, ql, ruby]
needs:
- package
steps:
- name: Download pack
uses: actions/download-artifact@v2
with:
name: codeql-ql-pack
path: ${{ runner.temp }}/codeql-ql-pack-artifact
- name: Prepare pack
run: |
unzip "${PACK_ARTIFACT}/*.zip" -d "${PACK}"
env:
PACK_ARTIFACT: ${{ runner.temp }}/codeql-ql-pack-artifact
PACK: ${{ runner.temp }}/pack
- name: Hack codeql-action options
run: |
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
env:
PACK: ${{ runner.temp }}/pack
- name: Checkout repository
uses: actions/checkout@v2
- name: Create CodeQL config file
run: |
echo "paths:" > ${CONF}
echo " - ${FOLDER}" >> ${CONF}
echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF}
echo "Config file: "
cat ${CONF}
env:
CONF: ./ql-for-ql-config.yml
FOLDER: ${{ matrix.folder }}
- name: Initialize CodeQL
uses: github/codeql-action/init@erik-krogh/ql
with:
languages: ql
db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@erik-krogh/ql
with:
category: "ql-for-ql-${{ matrix.folder }}"

View File

@@ -1,84 +0,0 @@
name: Collect database stats for QL for QL
on:
push:
branches: [main]
paths:
- ql/ql/src/ql.dbscheme
pull_request:
branches: [main]
paths:
- ql/ql/src/ql.dbscheme
workflow_dispatch:
jobs:
measure:
env:
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
strategy:
matrix:
repo:
- github/codeql
- github/codeql-go
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
with:
languages: javascript # does not matter
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Checkout ${{ matrix.repo }}
uses: actions/checkout@v2
with:
repository: ${{ matrix.repo }}
path: ${{ github.workspace }}/repo
- name: Create database
run: |
"${CODEQL}" database create \
--search-path "ql/extractor-pack" \
--threads 4 \
--language ql --source-root "${{ github.workspace }}/repo" \
"${{ runner.temp }}/database"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Measure database
run: |
mkdir -p "stats/${{ matrix.repo }}"
"${CODEQL}" dataset measure --threads 4 --output "stats/${{ matrix.repo }}/stats.xml" "${{ runner.temp }}/database/db-ql"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- uses: actions/upload-artifact@v2
with:
name: measurements
path: stats
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: measure
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: measurements
path: stats
- run: |
python -m pip install --user lxml
find stats -name 'stats.xml' -print0 | sort -z | xargs -0 python ql/scripts/merge_stats.py --output ql/ql/src/ql.dbscheme.stats --normalise ql_tokeninfo
- uses: actions/upload-artifact@v2
with:
name: ql.dbscheme.stats
path: ql/ql/src/ql.dbscheme.stats

View File

@@ -1,52 +0,0 @@
name: Run QL for QL Tests
on:
push:
branches: [main]
paths:
- "ql/**"
pull_request:
branches: [main]
paths:
- "ql/**"
env:
CARGO_TERM_COLOR: always
jobs:
qltest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
with:
languages: javascript # does not matter
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build extractor
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh
- name: Run QL tests
run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL formatting
run: |
find ql/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL compilation
run: |
"${CODEQL}" query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ql/extractor-pack" "ql/ql/src" "ql/ql/examples"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}

View File

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

View File

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

View File

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

View File

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

6
.gitignore vendored
View File

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

View File

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

View File

@@ -4,9 +4,6 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
## Change notes
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
## Submitting a new experimental query ## Submitting a new experimental query
@@ -14,14 +11,13 @@ If you have an idea for a query that you would like to share with other CodeQL u
1. **Directory structure** 1. **Directory structure**
There are six language-specific query directories in this repository: There are five language-specific query directories in this repository:
* C/C++: `cpp/ql/src` * C/C++: `cpp/ql/src`
* C#: `csharp/ql/src` * C#: `csharp/ql/src`
* Java: `java/ql/src` * Java: `java/ql/src`
* JavaScript: `javascript/ql/src` * JavaScript: `javascript/ql/src`
* Python: `python/ql/src` * Python: `python/ql/src`
* Ruby: `ruby/ql/src`
Each language-specific directory contains further subdirectories that group queries based on their `@tags` or purpose. Each language-specific directory contains further subdirectories that group queries based on their `@tags` or purpose.
- Experimental queries and libraries are stored in the `experimental` subdirectory within each language-specific directory in the [CodeQL repository](https://github.com/github/codeql). For example, experimental Java queries and libraries are stored in `java/ql/src/experimental` and any corresponding tests in `java/ql/test/experimental`. - Experimental queries and libraries are stored in the `experimental` subdirectory within each language-specific directory in the [CodeQL repository](https://github.com/github/codeql). For example, experimental Java queries and libraries are stored in `java/ql/src/experimental` and any corresponding tests in `java/ql/test/experimental`.

View File

@@ -1,11 +1,11 @@
# CodeQL # CodeQL
This open source repository contains the standard CodeQL libraries and queries that power [GitHub Advanced Security](https://github.com/features/security/code) and the other application security products that [GitHub](https://github.com/features/security/) makes available to its customers worldwide. For the queries, libraries, and extractor that power Go analysis, visit the [CodeQL for Go repository](https://github.com/github/codeql-go). This open source repository contains the standard CodeQL libraries and queries that power [LGTM](https://lgtm.com) and the other CodeQL products that [GitHub](https://github.com) makes available to its customers worldwide. For the queries, libraries, and extractor that power Go analysis, visit the [CodeQL for Go repository](https://github.com/github/codeql-go).
## How do I learn CodeQL and run queries? ## How do I learn CodeQL and run queries?
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL. There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL.
You can use the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension or the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com (Semmle Legacy product) to try out your queries on any open source project that's currently being analyzed. You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension to try out your queries on any open source project that's currently being analyzed.
## Contributing ## Contributing
@@ -13,7 +13,7 @@ We welcome contributions to our standard library and standard checks. Do you hav
## License ## License
The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com). The use of CodeQL on open source code is licensed under specific [Terms & Conditions](https://securitylab.github.com/tools/codeql/license/) UNLESS you have a commercial license in place. If you'd like to use CodeQL with a commercial codebase, please [contact us](https://github.com/enterprise/contact) for further help. The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com).
## Visual Studio Code integration ## Visual Studio Code integration

View File

@@ -7,7 +7,6 @@
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll",
@@ -25,17 +24,14 @@
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll"
], ],
"DataFlow Java/C++/C#/Python Common": [ "DataFlow Java/C++/C#/Python Common": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll"
], ],
"TaintTracking::Configuration Java/C++/C#/Python": [ "TaintTracking::Configuration Java/C++/C#/Python": [
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
@@ -53,21 +49,18 @@
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
], ],
"DataFlow Java/C++/C#/Python Consistency checks": [ "DataFlow Java/C++/C#/Python Consistency checks": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll"
], ],
"DataFlow Java/C# Flow Summaries": [ "DataFlow Java/C# Flow Summaries": [
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll", "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll"
], ],
"SsaReadPosition Java/C#": [ "SsaReadPosition Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
@@ -374,10 +367,8 @@
], ],
"Inline Test Expectations": [ "Inline Test Expectations": [
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll", "cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"java/ql/test/TestUtilities/InlineExpectationsTest.qll", "java/ql/test/TestUtilities/InlineExpectationsTest.qll",
"python/ql/test/TestUtilities/InlineExpectationsTest.qll", "python/ql/test/TestUtilities/InlineExpectationsTest.qll"
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll"
], ],
"C++ ExternalAPIs": [ "C++ ExternalAPIs": [
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll", "cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
@@ -449,28 +440,19 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll", "csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll"
], ],
"CryptoAlgorithms Python/JS/Ruby": [ "CryptoAlgorithms Python/JS": [
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll", "javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll", "python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll"
"ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll"
],
"CryptoAlgorithmNames Python/JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll",
"python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll",
"ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll"
], ],
"SensitiveDataHeuristics Python/JS": [ "SensitiveDataHeuristics Python/JS": [
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll", "javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll" "python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll"
], ],
"ReDoS Util Python/JS/Ruby": [ "ReDoS Util Python/JS": [
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll", "javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll", "python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll"
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll"
], ],
"ReDoS Exponential Python/JS": [ "ReDoS Exponential Python/JS": [
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll", "javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",
@@ -478,28 +460,6 @@
], ],
"ReDoS Polynomial Python/JS": [ "ReDoS Polynomial Python/JS": [
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll", "javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll", "python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll"
"ruby/ql/lib/codeql/ruby/security/performance/SuperlinearBackTracking.qll"
],
"BadTagFilterQuery Python/JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/BadTagFilterQuery.qll",
"python/ql/lib/semmle/python/security/BadTagFilterQuery.qll",
"ruby/ql/lib/codeql/ruby/security/BadTagFilterQuery.qll"
],
"CFG": [
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll"
],
"TypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
],
"CodeQL Tutorial": [
"cpp/ql/lib/tutorial.qll",
"csharp/ql/lib/tutorial.qll",
"java/ql/lib/tutorial.qll",
"javascript/ql/lib/tutorial.qll",
"python/ql/lib/tutorial.qll",
"ruby/ql/lib/tutorial.qll"
] ]
} }

View File

@@ -17,7 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Build" Version="16.11.0" /> <PackageReference Include="Microsoft.Build" Version="16.9.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -5,11 +5,9 @@
@name Badly bounded write (CWE-120) @name Badly bounded write (CWE-120)
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120
@name Potentially overrunning write (CWE-120) @name Potentially overrunning write (CWE-120)
+ semmlecode-cpp-queries/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql: /CWE/CWE-120
@name Likely overrunning write
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWriteFloat.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWriteFloat.ql: /CWE/CWE-120
@name Potentially overrunning write with float to string conversion (CWE-120) @name Potentially overrunning write with float to string conversion (CWE-120)
+ semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120
@name Array offset used before range check (CWE-120) @name Array offset used before range check (CWE-120)
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120
@name Potentially unsafe use of strcat (CWE-120) @name Potentially unsafe use of strcat (CWE-120)

View File

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

View File

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

View File

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

View File

@@ -1,2 +0,0 @@
lgtm,codescanning
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved, reducing the number of false positive results when encryption is present.

View File

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

View File

@@ -1,24 +0,0 @@
## 0.0.8
### Deprecated APIs
* The `codeql/cpp-upgrades` CodeQL pack has been removed. All upgrades scripts have been merged into the `codeql/cpp-all` CodeQL pack.
### Minor Analysis Improvements
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
more accurate length for integers formatted with `%x`
## 0.0.7
## 0.0.6
## 0.0.5
## 0.0.4
### New Features
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
`isFromSystemMacroDefinition` for identifying code that originates from a
macro outside the project being analyzed.

View File

@@ -73,7 +73,7 @@ class Options extends string {
* __assume(0); * __assume(0);
* ``` * ```
* (note that in this case if the hint is wrong and the expression is reached at * (note that in this case if the hint is wrong and the expression is reached at
* runtime, the program's behavior is undefined) * runtime, the program's behaviour is undefined)
*/ */
predicate exprExits(Expr e) { predicate exprExits(Expr e) {
e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or

View File

@@ -50,7 +50,7 @@ class CustomOptions extends Options {
* __assume(0); * __assume(0);
* ``` * ```
* (note that in this case if the hint is wrong and the expression is reached at * (note that in this case if the hint is wrong and the expression is reached at
* runtime, the program's behavior is undefined) * runtime, the program's behaviour is undefined)
*/ */
override predicate exprExits(Expr e) { Options.super.exprExits(e) } override predicate exprExits(Expr e) { Options.super.exprExits(e) }

View File

@@ -1,7 +0,0 @@
## 0.0.4
### New Features
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
`isFromSystemMacroDefinition` for identifying code that originates from a
macro outside the project being analyzed.

View File

@@ -1 +0,0 @@
## 0.0.5

View File

@@ -1 +0,0 @@
## 0.0.6

View File

@@ -1 +0,0 @@
## 0.0.7

View File

@@ -1,10 +0,0 @@
## 0.0.8
### Deprecated APIs
* The `codeql/cpp-upgrades` CodeQL pack has been removed. All upgrades scripts have been merged into the `codeql/cpp-all` CodeQL pack.
### Minor Analysis Improvements
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
more accurate length for integers formatted with `%x`

View File

@@ -1,2 +0,0 @@
---
lastReleaseVersion: 0.0.8

View File

@@ -37,7 +37,7 @@ abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition {
* dependencies. Without this information, range analysis might work for * dependencies. Without this information, range analysis might work for
* simple cases but will go into infinite loops on complex code. * simple cases but will go into infinite loops on complex code.
* *
* For example, when modeling the definition by reference in a call to an * For example, when modelling the definition by reference in a call to an
* overloaded `operator=`, written as `v = e`, the definition of `(this, v)` * overloaded `operator=`, written as `v = e`, the definition of `(this, v)`
* depends on `e`. * depends on `e`.
*/ */

View File

@@ -5,7 +5,7 @@
* `Instruction` level), and then using the array length analysis and the range * `Instruction` level), and then using the array length analysis and the range
* analysis together to prove that some of these pointer dereferences are safe. * analysis together to prove that some of these pointer dereferences are safe.
* *
* The analysis is soundy, i.e. it is sound if no undefined behavior is present * The analysis is soundy, i.e. it is sound if no undefined behaviour is present
* in the program. * in the program.
* Furthermore, it crucially depends on the soundiness of the range analysis and * Furthermore, it crucially depends on the soundiness of the range analysis and
* the array length analysis. * the array length analysis.

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.0.8 version: 0.0.2
groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp
library: true library: true
upgrades: upgrades dependencies:
codeql/cpp-upgrades: 0.0.2

View File

@@ -206,7 +206,9 @@ class Class extends UserType {
* it is callable by a particular caller. For C++11, there's also a question * it is callable by a particular caller. For C++11, there's also a question
* of whether to include members that are defaulted or deleted. * of whether to include members that are defaulted or deleted.
*/ */
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor } deprecated predicate hasCopyConstructor() {
exists(CopyConstructor cc | cc = this.getAMemberFunction())
}
/** /**
* Holds if this class has a copy assignment operator that is either * Holds if this class has a copy assignment operator that is either
@@ -222,7 +224,7 @@ class Class extends UserType {
* or deleted. * or deleted.
*/ */
deprecated predicate hasCopyAssignmentOperator() { deprecated predicate hasCopyAssignmentOperator() {
this.getAMemberFunction() instanceof CopyAssignmentOperator exists(CopyAssignmentOperator coa | coa = this.getAMemberFunction())
} }
/** /**
@@ -235,7 +237,7 @@ class Class extends UserType {
exists(ClassDerivation cd | cd.getBaseClass() = base | exists(ClassDerivation cd | cd.getBaseClass() = base |
result = result =
this.accessOfBaseMemberMulti(cd.getDerivedClass(), this.accessOfBaseMemberMulti(cd.getDerivedClass(),
fieldInBase.accessInDirectDerived(cd.getASpecifier())) fieldInBase.accessInDirectDerived(cd.getASpecifier().(AccessSpecifier)))
) )
} }
@@ -259,20 +261,21 @@ class Class extends UserType {
* includes the case of `base` = `this`. * includes the case of `base` = `this`.
*/ */
AccessSpecifier accessOfBaseMember(Declaration member) { AccessSpecifier accessOfBaseMember(Declaration member) {
result = this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier()) result =
this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier))
} }
/** /**
* DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that * DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that
* `= default` members are no longer included. * `= default` members are no longer included.
*/ */
deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() } deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() }
/** /**
* DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to * DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to
* reflect that `= default` members are no longer included. * reflect that `= default` members are no longer included.
*/ */
deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() } deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() }
/** /**
* Holds if this class, struct or union has an implicitly-declared copy * Holds if this class, struct or union has an implicitly-declared copy
@@ -316,7 +319,7 @@ class Class extends UserType {
exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() | exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() |
// Note: Overload resolution is not implemented -- all copy // Note: Overload resolution is not implemented -- all copy
// constructors are considered equal. // constructors are considered equal.
this.cannotAccessCopyConstructorOnAny(t) this.cannotAccessCopyConstructorOnAny(t.(Class))
) )
or or
// - T has direct or virtual base class that cannot be copied (has deleted, // - T has direct or virtual base class that cannot be copied (has deleted,
@@ -389,7 +392,7 @@ class Class extends UserType {
exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() | exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() |
// Note: Overload resolution is not implemented -- all copy assignment // Note: Overload resolution is not implemented -- all copy assignment
// operators are considered equal. // operators are considered equal.
this.cannotAccessCopyAssignmentOperatorOnAny(t) this.cannotAccessCopyAssignmentOperatorOnAny(t.(Class))
) )
or or
exists(Class c | c = this.getADirectOrVirtualBase() | exists(Class c | c = this.getADirectOrVirtualBase() |
@@ -484,7 +487,7 @@ class Class extends UserType {
exists(ClassDerivation cd | exists(ClassDerivation cd |
// Add the offset of the direct base class and the offset of `baseClass` // Add the offset of the direct base class and the offset of `baseClass`
// within that direct base class. // within that direct base class.
cd = this.getADerivation() and cd = getADerivation() and
result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset() result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset()
) )
} }
@@ -499,12 +502,12 @@ class Class extends UserType {
*/ */
int getABaseClassByteOffset(Class baseClass) { int getABaseClassByteOffset(Class baseClass) {
// Handle the non-virtual case. // Handle the non-virtual case.
result = this.getANonVirtualBaseClassByteOffset(baseClass) result = getANonVirtualBaseClassByteOffset(baseClass)
or or
exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase | exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase |
// Look for the base class as a non-virtual base of a direct or indirect // Look for the base class as a non-virtual base of a direct or indirect
// virtual base, adding the two offsets. // virtual base, adding the two offsets.
this.getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and
result = virtualBaseOffset + offsetFromVirtualBase result = virtualBaseOffset + offsetFromVirtualBase
) )
@@ -620,11 +623,11 @@ class Class extends UserType {
* inherits one). * inherits one).
*/ */
predicate isPolymorphic() { predicate isPolymorphic() {
exists(MemberFunction f | f.getDeclaringType() = this.getABaseClass*() and f.isVirtual()) exists(MemberFunction f | f.getDeclaringType() = getABaseClass*() and f.isVirtual())
} }
override predicate involvesTemplateParameter() { override predicate involvesTemplateParameter() {
this.getATemplateArgument().(Type).involvesTemplateParameter() getATemplateArgument().(Type).involvesTemplateParameter()
} }
/** Holds if this class, struct or union was declared 'final'. */ /** Holds if this class, struct or union was declared 'final'. */
@@ -762,7 +765,7 @@ class ClassDerivation extends Locatable, @derivation {
* }; * };
* ``` * ```
*/ */
Class getBaseClass() { result = this.getBaseType().getUnderlyingType() } Class getBaseClass() { result = getBaseType().getUnderlyingType() }
override string getAPrimaryQlClass() { result = "ClassDerivation" } override string getAPrimaryQlClass() { result = "ClassDerivation" }
@@ -815,7 +818,7 @@ class ClassDerivation extends Locatable, @derivation {
predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) } predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) }
/** Holds if the derivation is for a virtual base class. */ /** Holds if the derivation is for a virtual base class. */
predicate isVirtual() { this.hasSpecifier("virtual") } predicate isVirtual() { hasSpecifier("virtual") }
/** Gets the location of the derivation. */ /** Gets the location of the derivation. */
override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) } override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) }
@@ -843,7 +846,7 @@ class ClassDerivation extends Locatable, @derivation {
* ``` * ```
*/ */
class LocalClass extends Class { class LocalClass extends Class {
LocalClass() { this.isLocal() } LocalClass() { isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" } override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
@@ -885,7 +888,7 @@ class NestedClass extends Class {
* pure virtual function. * pure virtual function.
*/ */
class AbstractClass extends Class { class AbstractClass extends Class {
AbstractClass() { this.getAMemberFunction() instanceof PureVirtualFunction } AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) }
override string getAPrimaryQlClass() { result = "AbstractClass" } override string getAPrimaryQlClass() { result = "AbstractClass" }
} }
@@ -986,9 +989,9 @@ class ClassTemplateSpecialization extends Class {
TemplateClass getPrimaryTemplate() { TemplateClass getPrimaryTemplate() {
// Ignoring template arguments, the primary template has the same name // Ignoring template arguments, the primary template has the same name
// as each of its specializations. // as each of its specializations.
result.getSimpleName() = this.getSimpleName() and result.getSimpleName() = getSimpleName() and
// It is in the same namespace as its specializations. // It is in the same namespace as its specializations.
result.getNamespace() = this.getNamespace() and result.getNamespace() = getNamespace() and
// It is distinguished by the fact that each of its template arguments // It is distinguished by the fact that each of its template arguments
// is a distinct template parameter. // is a distinct template parameter.
count(TemplateParameter tp | tp = result.getATemplateArgument()) = count(TemplateParameter tp | tp = result.getATemplateArgument()) =
@@ -1105,7 +1108,7 @@ deprecated class Interface extends Class {
* ``` * ```
*/ */
class VirtualClassDerivation extends ClassDerivation { class VirtualClassDerivation extends ClassDerivation {
VirtualClassDerivation() { this.hasSpecifier("virtual") } VirtualClassDerivation() { hasSpecifier("virtual") }
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" } override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
} }
@@ -1133,7 +1136,7 @@ class VirtualBaseClass extends Class {
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this } VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
/** A class/struct that is derived from this one using virtual inheritance. */ /** A class/struct that is derived from this one using virtual inheritance. */
Class getAVirtuallyDerivedClass() { result = this.getAVirtualDerivation().getDerivedClass() } Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() }
} }
/** /**
@@ -1152,7 +1155,7 @@ class ProxyClass extends UserType {
override string getAPrimaryQlClass() { result = "ProxyClass" } override string getAPrimaryQlClass() { result = "ProxyClass" }
/** Gets the location of the proxy class. */ /** Gets the location of the proxy class. */
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() } override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }
/** Gets the template parameter for which this is the proxy class. */ /** Gets the template parameter for which this is the proxy class. */
TemplateParameter getTemplateParameter() { TemplateParameter getTemplateParameter() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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