mirror of
https://github.com/github/codeql.git
synced 2026-05-17 20:57:07 +02:00
Compare commits
1 Commits
codeql-cli
...
post-relea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ec2601976 |
8
.bazelrc
8
.bazelrc
@@ -1,12 +1,4 @@
|
||||
common --enable_platform_specific_config
|
||||
common --enable_bzlmod
|
||||
# because we use --override_module with `%workspace%`, the lock file is not stable
|
||||
common --lockfile_mode=off
|
||||
|
||||
# when building from this repository in isolation, the internal repository will not be found at ..
|
||||
# where `MODULE.bazel` looks for it. The following will get us past the module loading phase, so
|
||||
# that we can build things that do not rely on that
|
||||
common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
|
||||
|
||||
build --repo_env=CC=clang --repo_env=CXX=clang++
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
7.0.2
|
||||
6.3.1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
DisableFormat: true
|
||||
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -71,10 +71,3 @@ go/extractor/opencsv/CSVReader.java -text
|
||||
# `javascript/ql/experimental/adaptivethreatmodeling/test/update_endpoint_test_files.py`.
|
||||
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.js linguist-generated=true -merge
|
||||
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.ts linguist-generated=true -merge
|
||||
|
||||
# Auto-generated modeling for Python
|
||||
python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
||||
|
||||
# auto-generated bazel lock file
|
||||
ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
||||
ruby/extractor/cargo-bazel-lock.json -merge
|
||||
|
||||
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -20,7 +20,7 @@ JS:
|
||||
|
||||
Kotlin:
|
||||
- java/kotlin-extractor/**/*
|
||||
- java/ql/test-kotlin*/**/*
|
||||
- java/ql/test/kotlin/**/*
|
||||
|
||||
Python:
|
||||
- python/**/*
|
||||
|
||||
3
.github/workflows/check-change-note.yml
vendored
3
.github/workflows/check-change-note.yml
vendored
@@ -1,8 +1,5 @@
|
||||
name: Check change note
|
||||
|
||||
permissions:
|
||||
pull-requests: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
3
.github/workflows/check-implicit-this.yml
vendored
3
.github/workflows/check-implicit-this.yml
vendored
@@ -9,9 +9,6 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/check-qldoc.yml
vendored
3
.github/workflows/check-qldoc.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qldoc:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/check-query-ids.yml
vendored
3
.github/workflows/check-query-ids.yml
vendored
@@ -11,9 +11,6 @@ on:
|
||||
- "rc/*"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check query IDs
|
||||
|
||||
5
.github/workflows/close-stale.yml
vendored
5
.github/workflows/close-stale.yml
vendored
@@ -5,9 +5,6 @@ on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository == 'github/codeql'
|
||||
@@ -15,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Comment or remove the `Stale` label in order to avoid having this issue closed in 7 days.'
|
||||
|
||||
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@@ -28,9 +28,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 8.0.101
|
||||
dotnet-version: 7.0.102
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
6
.github/workflows/compile-queries.yml
vendored
6
.github/workflows/compile-queries.yml
vendored
@@ -8,12 +8,8 @@ on:
|
||||
- "codeql-cli-*"
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
compile-queries:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
|
||||
steps:
|
||||
@@ -28,7 +24,7 @@ jobs:
|
||||
with:
|
||||
key: all-queries
|
||||
- name: check formatting
|
||||
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
- name: compile queries - check-only
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
16
.github/workflows/csharp-qltest.yml
vendored
16
.github/workflows/csharp-qltest.yml
vendored
@@ -25,9 +25,6 @@ defaults:
|
||||
run:
|
||||
working-directory: csharp
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -49,7 +46,6 @@ jobs:
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/semmlecode.csharp.dbscheme downgrades/initial/semmlecode.csharp.dbscheme
|
||||
qltest:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -76,15 +72,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 8.0.101
|
||||
dotnet-version: 7.0.102
|
||||
- name: Extractor unit tests
|
||||
run: |
|
||||
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Util.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Extraction.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=8.0.1 autobuilder/Semmle.Autobuild.CSharp.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=8.0.1 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
|
||||
dotnet test -p:RuntimeFrameworkVersion=7.0.2 extractor/Semmle.Util.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=7.0.2 extractor/Semmle.Extraction.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=7.0.2 autobuilder/Semmle.Autobuild.CSharp.Tests
|
||||
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
|
||||
shell: bash
|
||||
stubgentest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/csv-coverage-metrics.yml
vendored
4
.github/workflows/csv-coverage-metrics.yml
vendored
@@ -14,10 +14,6 @@ on:
|
||||
- ".github/workflows/csv-coverage-metrics.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
publish-java:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -19,10 +19,6 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate framework coverage artifacts
|
||||
|
||||
@@ -6,10 +6,6 @@ on:
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check framework coverage differences and comment
|
||||
|
||||
@@ -3,9 +3,6 @@ name: Build framework coverage timeseries reports
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/csv-coverage-update.yml
vendored
4
.github/workflows/csv-coverage-update.yml
vendored
@@ -5,10 +5,6 @@ on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Update framework coverage report
|
||||
|
||||
3
.github/workflows/csv-coverage.yml
vendored
3
.github/workflows/csv-coverage.yml
vendored
@@ -7,9 +7,6 @@ on:
|
||||
description: "github/codeql repo SHA used for looking up the CSV models"
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/fast-forward.yml
vendored
5
.github/workflows/fast-forward.yml
vendored
@@ -7,14 +7,13 @@ name: Fast-forward tracking branch for selected CodeQL version
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
fast-forward:
|
||||
name: Fast-forward tracking branch for selected CodeQL version
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'github/codeql'
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
BRANCH_NAME: 'lgtm.com'
|
||||
steps:
|
||||
|
||||
13
.github/workflows/go-tests-other-os.yml
vendored
13
.github/workflows/go-tests-other-os.yml
vendored
@@ -8,21 +8,16 @@ on:
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
env:
|
||||
GO_VERSION: '~1.22.0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
GO_VERSION: '~1.21.0'
|
||||
jobs:
|
||||
test-mac:
|
||||
name: Test MacOS
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
@@ -51,15 +46,13 @@ jobs:
|
||||
make test cache="${{ steps.query-cache.outputs.cache-dir }}"
|
||||
|
||||
test-win:
|
||||
if: github.repository_owner == 'github'
|
||||
name: Test Windows
|
||||
runs-on: windows-latest-xl
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
11
.github/workflows/go-tests.yml
vendored
11
.github/workflows/go-tests.yml
vendored
@@ -15,24 +15,17 @@ on:
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
|
||||
env:
|
||||
GO_VERSION: '~1.22.0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
GO_VERSION: '~1.21.0'
|
||||
jobs:
|
||||
test-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
name: Test Linux (Ubuntu)
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
7
.github/workflows/labeler.yml
vendored
7
.github/workflows/labeler.yml
vendored
@@ -2,12 +2,11 @@ name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
|
||||
12
.github/workflows/mad_modelDiff.yml
vendored
12
.github/workflows/mad_modelDiff.yml
vendored
@@ -12,7 +12,6 @@ on:
|
||||
- main
|
||||
paths:
|
||||
- "java/ql/src/utils/modelgenerator/**/*.*"
|
||||
- "misc/scripts/models-as-data/*.*"
|
||||
- ".github/workflows/mad_modelDiff.yml"
|
||||
|
||||
permissions:
|
||||
@@ -62,9 +61,8 @@ jobs:
|
||||
DATABASE=$2
|
||||
cd codeql-$QL_VARIANT
|
||||
SHORTNAME=`basename $DATABASE`
|
||||
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
|
||||
mkdir -p $MODELS/$SHORTNAME
|
||||
mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME
|
||||
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE ${SHORTNAME}.temp.model.yml
|
||||
mv java/ql/lib/ext/generated/${SHORTNAME}.temp.model.yml $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.model.yml
|
||||
cd ..
|
||||
}
|
||||
|
||||
@@ -87,16 +85,16 @@ jobs:
|
||||
set -x
|
||||
MODELS=`pwd`/tmp-models
|
||||
ls -1 tmp-models/
|
||||
for m in $MODELS/*/main/*.model.yml ; do
|
||||
for m in $MODELS/*_main.model.yml ; do
|
||||
t="${m/main/"pr"}"
|
||||
basename=`basename $m`
|
||||
name="diff_${basename/.model.yml/""}"
|
||||
name="diff_${basename/_main.model.yml/""}"
|
||||
(diff -w -u $m $t | diff2html -i stdin -F $MODELS/$name.html) || true
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: models
|
||||
path: tmp-models/**/**/*.model.yml
|
||||
path: tmp-models/*.model.yml
|
||||
retention-days: 20
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
3
.github/workflows/mad_regenerate-models.yml
vendored
3
.github/workflows/mad_regenerate-models.yml
vendored
@@ -11,9 +11,6 @@ on:
|
||||
- ".github/workflows/mad_regenerate-models.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
regenerate-models:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
2
.github/workflows/qhelp-pr-preview.yml
vendored
2
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -77,7 +77,7 @@ jobs:
|
||||
done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt
|
||||
exit "${EXIT_CODE}"
|
||||
|
||||
- if: ${{ !cancelled() }}
|
||||
- if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: comment
|
||||
|
||||
9
.github/workflows/ql-for-ql-build.yml
vendored
9
.github/workflows/ql-for-ql-build.yml
vendored
@@ -9,13 +9,8 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
### Build the queries ###
|
||||
@@ -24,7 +19,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@main
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
@@ -70,7 +65,7 @@ jobs:
|
||||
exclude:*/ql/lib/upgrades/
|
||||
exclude:java/ql/integration-tests
|
||||
- name: Upload sarif to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@main
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: ql-for-ql.sarif
|
||||
category: ql-for-ql
|
||||
|
||||
@@ -11,10 +11,6 @@ on:
|
||||
- ql/ql/src/ql.dbscheme
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: read
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
@@ -29,7 +25,7 @@ jobs:
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@main
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
|
||||
7
.github/workflows/ql-for-ql-tests.yml
vendored
7
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -17,9 +17,6 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -27,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@main
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
@@ -72,7 +69,7 @@ jobs:
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@main
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
|
||||
3
.github/workflows/query-list.yml
vendored
3
.github/workflows/query-list.yml
vendored
@@ -13,9 +13,6 @@ on:
|
||||
- '.github/actions/fetch-codeql/action.yml'
|
||||
- 'misc/scripts/generate-code-scanning-query-list.py'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
|
||||
77
.github/workflows/ruby-build.yml
vendored
77
.github/workflows/ruby-build.yml
vendored
@@ -32,9 +32,6 @@ defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
@@ -51,11 +48,9 @@ jobs:
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Prepare Windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: powershell
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
- name: Install cargo-cross
|
||||
if: runner.os == 'Linux'
|
||||
run: cargo install cross --version 0.2.5
|
||||
- uses: ./.github/actions/os-version
|
||||
id: os_version
|
||||
- name: Cache entire extractor
|
||||
@@ -84,8 +79,16 @@ jobs:
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo test --verbose
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
# On linux, build the extractor via cross in a centos7 container.
|
||||
# This ensures we don't depend on glibc > 2.17.
|
||||
- name: Release build (linux)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||
run: |
|
||||
cd extractor
|
||||
cross build --release
|
||||
mv target/x86_64-unknown-linux-gnu/release/codeql-extractor-ruby target/release/
|
||||
- name: Release build (windows and macos)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os != 'Linux'
|
||||
run: cd extractor && cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
@@ -108,7 +111,6 @@ jobs:
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
retention-days: 1
|
||||
compile-queries:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -117,7 +119,7 @@ jobs:
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
with:
|
||||
key: ruby-build
|
||||
- name: Build Query Pack
|
||||
run: |
|
||||
@@ -229,3 +231,54 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
# This is a copy of the 'test' job that runs in a centos7 container.
|
||||
# This tests that the extractor works correctly on systems with an old glibc.
|
||||
test-centos7:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: centos:centos7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- name: Install gh cli
|
||||
run: |
|
||||
yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
|
||||
# fetch-codeql requires unzip and jq
|
||||
# jq is available in epel-release (https://docs.fedoraproject.org/en-US/epel/)
|
||||
yum install -y gh unzip epel-release
|
||||
yum install -y jq
|
||||
- uses: actions/checkout@v3
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
# Due to a bug in Actions, we can't use runner.temp in the run blocks here.
|
||||
# https://github.com/actions/runner/issues/2185
|
||||
|
||||
- name: Download Ruby bundle
|
||||
uses: actions/download-artifact@v3
|
||||
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: Run QL test
|
||||
shell: bash
|
||||
run: |
|
||||
codeql test run --search-path "$RUNNER_TEMP"/ruby-bundle --additional-packs "$RUNNER_TEMP"/ruby-bundle ruby/ql/test/library-tests/ast/constants/
|
||||
- name: Create database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database create --search-path "$RUNNER_TEMP"/ruby-bundle --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database
|
||||
- name: Analyze database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "$RUNNER_TEMP"/ruby-bundle --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
3
.github/workflows/ruby-dataset-measure.yml
vendored
3
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -17,9 +17,6 @@ on:
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
|
||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -29,9 +29,6 @@ defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -53,7 +50,6 @@ jobs:
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme
|
||||
qltest:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
24
.github/workflows/swift.yml
vendored
24
.github/workflows/swift.yml
vendored
@@ -33,62 +33,46 @@ on:
|
||||
- rc/*
|
||||
- codeql-cli-*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks
|
||||
# without waiting for the macOS build
|
||||
build-and-test-macos:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
build-and-test-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
qltests-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
qltests-macos:
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
integration-tests-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
integration-tests-macos:
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
clang-format:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
|
||||
name: Check that python code is properly formatted
|
||||
with:
|
||||
extra_args: clang-format --all-files
|
||||
codegen:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
@@ -98,12 +82,12 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
name: Check that python code is properly formatted
|
||||
with:
|
||||
extra_args: autopep8 --all-files
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
name: Check that QL generated code was checked in
|
||||
with:
|
||||
extra_args: swift-codegen --all-files
|
||||
|
||||
3
.github/workflows/sync-files.yml
vendored
3
.github/workflows/sync-files.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
- main
|
||||
- 'rc/*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -23,9 +23,6 @@ defaults:
|
||||
run:
|
||||
working-directory: shared/tree-sitter-extractor
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/validate-change-notes.yml
vendored
3
.github/workflows/validate-change-notes.yml
vendored
@@ -15,9 +15,6 @@ on:
|
||||
- ".github/workflows/validate-change-notes.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-change-note:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,9 +39,6 @@
|
||||
# local bazel options
|
||||
/local.bazelrc
|
||||
|
||||
# generated cmake directory
|
||||
/.bazel-cmake
|
||||
|
||||
# CLion project files
|
||||
/.clwb
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ repos:
|
||||
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v17.0.6
|
||||
rev: v13.0.1
|
||||
hooks:
|
||||
- id: clang-format
|
||||
files: ^swift/.*\.(h|c|cpp)$
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-autopep8
|
||||
rev: v1.6.0
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
# Bazel (excluding BUILD.bazel files)
|
||||
WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
MODULE.bazel @github/codeql-ci-reviewers
|
||||
.bazelversion @github/codeql-ci-reviewers
|
||||
.bazelrc @github/codeql-ci-reviewers
|
||||
**/*.bzl @github/codeql-ci-reviewers
|
||||
@@ -45,4 +44,3 @@ MODULE.bazel @github/codeql-ci-reviewers
|
||||
|
||||
# Misc
|
||||
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||
/misc/scripts/generate-code-scanning-query-list.py @RasmusWL
|
||||
|
||||
53
MODULE.bazel
53
MODULE.bazel
@@ -1,53 +0,0 @@
|
||||
module(
|
||||
name = "codeql",
|
||||
version = "0.0",
|
||||
)
|
||||
|
||||
# this points to our internal repository when `codeql` is checked out as a submodule thereof
|
||||
# when building things from `codeql` independently this is stubbed out in `.bazelrc`
|
||||
bazel_dep(name = "semmle_code", version = "0.0")
|
||||
local_path_override(
|
||||
module_name = "semmle_code",
|
||||
path = "..",
|
||||
)
|
||||
|
||||
# see https://registry.bazel.build/ for a list of available packages
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.8")
|
||||
bazel_dep(name = "rules_pkg", version = "0.9.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.0.3")
|
||||
bazel_dep(name = "rules_python", version = "0.31.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip.parse(
|
||||
hub_name = "codegen_deps",
|
||||
python_version = "3.11",
|
||||
requirements_lock = "//misc/codegen:requirements_lock.txt",
|
||||
)
|
||||
use_repo(pip, "codegen_deps")
|
||||
|
||||
swift_deps = use_extension("//swift/third_party:load.bzl", "swift_deps")
|
||||
use_repo(
|
||||
swift_deps,
|
||||
"binlog",
|
||||
"picosha2",
|
||||
"swift_prebuilt_darwin_x86_64",
|
||||
"swift_prebuilt_linux",
|
||||
"swift_toolchain_linux",
|
||||
"swift_toolchain_macos",
|
||||
)
|
||||
|
||||
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
|
||||
node.toolchain(
|
||||
name = "nodejs",
|
||||
node_version = "18.15.0",
|
||||
)
|
||||
use_repo(node, "nodejs", "nodejs_toolchains")
|
||||
|
||||
register_toolchains(
|
||||
"@nodejs_toolchains//:all",
|
||||
)
|
||||
@@ -1,2 +1,12 @@
|
||||
# please use MODULE.bazel to add dependencies
|
||||
# this empty file is required by internal repositories, don't remove it
|
||||
# Please notice that any bazel targets and definitions in this repository are currently experimental
|
||||
# and for internal use only.
|
||||
|
||||
workspace(name = "codeql")
|
||||
|
||||
load("//misc/bazel:workspace.bzl", "codeql_workspace")
|
||||
|
||||
codeql_workspace()
|
||||
|
||||
load("//misc/bazel:workspace_deps.bzl", "codeql_workspace_deps")
|
||||
|
||||
codeql_workspace_deps()
|
||||
|
||||
@@ -53,6 +53,14 @@
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C#/Go/Ruby/Python/Swift Flow Summaries": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
|
||||
],
|
||||
"SsaReadPosition Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
|
||||
@@ -431,6 +439,13 @@
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp",
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp"
|
||||
],
|
||||
"IDE Contextual Queries": [
|
||||
"cpp/ql/lib/IDEContextual.qll",
|
||||
"csharp/ql/lib/IDEContextual.qll",
|
||||
"java/ql/lib/IDEContextual.qll",
|
||||
"javascript/ql/lib/IDEContextual.qll",
|
||||
"python/ql/lib/analysis/IDEContextual.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
|
||||
@@ -447,6 +462,23 @@
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
|
||||
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"TypeTracker": [
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
|
||||
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
|
||||
],
|
||||
"SummaryTypeTracker": [
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll",
|
||||
"ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll"
|
||||
],
|
||||
"AccessPathSyntax": [
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/AccessPathSyntax.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
|
||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
|
||||
],
|
||||
"IncompleteUrlSubstringSanitization": [
|
||||
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
|
||||
"ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll"
|
||||
@@ -466,6 +498,10 @@
|
||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll",
|
||||
"python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll"
|
||||
],
|
||||
"Typo database": [
|
||||
"javascript/ql/src/Expressions/TypoDatabase.qll",
|
||||
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
|
||||
],
|
||||
"Swift declarations test file": [
|
||||
"swift/ql/test/extractor-tests/declarations/declarations.swift",
|
||||
"swift/ql/test/library-tests/ast/declarations.swift"
|
||||
@@ -498,4 +534,4 @@
|
||||
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
|
||||
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
public void TestCppAutobuilderSuccess()
|
||||
{
|
||||
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
|
||||
Actions.RunProcess[@"cmd.exe /C scratch\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program^ Files^ ^(x86^)\Microsoft^ Visual^ Studio^ 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
|
||||
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
|
||||
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
|
||||
@@ -337,11 +337,10 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"] = true;
|
||||
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"] = true;
|
||||
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = true;
|
||||
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CPP_SCRATCH_DIR"] = "scratch";
|
||||
Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.slx";
|
||||
Actions.EnumerateDirectories[@"C:\Project"] = "";
|
||||
Actions.CreateDirectories.Add(@"scratch\.nuget");
|
||||
Actions.DownloadFiles.Add(("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", @"scratch\.nuget\nuget.exe"));
|
||||
Actions.CreateDirectories.Add(@"C:\Project\.nuget");
|
||||
Actions.DownloadFiles.Add(("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", @"C:\Project\.nuget\nuget.exe"));
|
||||
|
||||
var autobuilder = CreateAutoBuilder(true);
|
||||
var solution = new TestSolution(@"C:\Project\test.sln");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -11,12 +11,12 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.Cpp
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
|
||||
<ApplicationIcon />
|
||||
@@ -17,7 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="17.8.3" />
|
||||
<PackageReference Include="Microsoft.Build" Version="17.3.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
|
||||
|
||||
from Expr child, int index, int index_new, Element parent
|
||||
where
|
||||
exprparents(child, index, parent) and
|
||||
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
|
||||
select child, index_new, parent
|
||||
@@ -1,9 +0,0 @@
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Stmt f, Stmt i
|
||||
where
|
||||
for_initialization(f, i) and
|
||||
f instanceof @stmt_for
|
||||
select f, i
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
|
||||
|
||||
from Stmt child, int index, int index_new, Element parent
|
||||
where
|
||||
stmtparents(child, index, parent) and
|
||||
(
|
||||
not isStmtWithInitializer(parent)
|
||||
or
|
||||
index > 0
|
||||
) and
|
||||
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
|
||||
select child, index_new, parent
|
||||
@@ -1,5 +0,0 @@
|
||||
description: Support C++20 range-based for initializers
|
||||
compatibility: partial
|
||||
exprparents.rel: run exprparents.qlo
|
||||
stmtparents.rel: run stmtparents.qlo
|
||||
for_initialization.rel: run for_initialization.qlo
|
||||
@@ -1,11 +0,0 @@
|
||||
class Declaration extends @declaration {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class MangledName extends @mangledname {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Declaration d, MangledName n
|
||||
where mangled_name(d, n, _)
|
||||
select d, n
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Add completness information to mangled name table
|
||||
compatibility: full
|
||||
mangled_name.rel: run mangled_name.qlo
|
||||
@@ -1,9 +0,0 @@
|
||||
class Function extends @function {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Function fun, string name, int kind, int kind_new
|
||||
where
|
||||
functions(fun, name, kind) and
|
||||
if kind = 7 or kind = 8 then kind_new = 0 else kind_new = kind
|
||||
select fun, name, kind_new
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Support more function types
|
||||
compatibility: full
|
||||
functions.rel: run functions.qlo
|
||||
@@ -1,6 +1,5 @@
|
||||
description: Support C++17 if and switch initializers
|
||||
compatibility: partial
|
||||
constexpr_if_initialization.rel: delete
|
||||
if_initialization.rel: delete
|
||||
switch_initialization.rel: delete
|
||||
exprparents.rel: run exprparents.qlo
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
class AttributeArg extends @attribute_arg {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Attribute extends @attribute {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_default {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from AttributeArg arg, int kind, int kind_new, Attribute attr, int index, Location location
|
||||
where
|
||||
attribute_args(arg, kind, attr, index, location) and
|
||||
if arg instanceof @attribute_arg_expr then kind_new = 0 else kind_new = kind
|
||||
select arg, kind_new, attr, index, location
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
description: Support expression attribute arguments
|
||||
compatibility: partial
|
||||
attribute_arg_expr.rel: delete
|
||||
attribute_args.rel: run attribute_args.qlo
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Revert removal of uniqueness constraint on link_targets/2
|
||||
compatibility: backwards
|
||||
@@ -1,58 +1,3 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.
|
||||
|
||||
## 0.12.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added the `PreprocBlock.qll` library to this repository. This library offers a view of `#if`, `#elif`, `#else` and similar directives as a tree with navigable parent-child relationships.
|
||||
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.
|
||||
|
||||
## 0.12.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted many deprecated predicates and classes with uppercase `XML`, `SSA`, `SAL`, `SQL`, etc. in their names. Use the PascalCased versions instead.
|
||||
* Deleted the deprecated `StrcatFunction` class, use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
|
||||
|
||||
## 0.12.3
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `isUserInput`, `userInputArgument`, and `userInputReturned` predicates from `SecurityOptions` have been deprecated. Use `FlowSource` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* `UserDefineLiteral` and `DeductionGuide` classes have been added, representing C++11 user defined literals and C++17 deduction guides.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Changed the output of `Node.toString` to better reflect how many indirections a given dataflow node has.
|
||||
* Added a new predicate `Node.asDefinition` on `DataFlow::Node`s for selecting the dataflow node corresponding to a particular definition.
|
||||
* The deprecated `DefaultTaintTracking` library has been removed.
|
||||
* The `Guards` library has been replaced with the API-compatible `IRGuards` implementation, which has better precision in some cases.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Under certain circumstances a function declaration that is not also a definition could be associated with a `Function` that did not have the definition as a `FunctionDeclarationEntry`. This is now fixed when only one definition exists, and a unique `Function` will exist that has both the declaration and the definition as a `FunctionDeclarationEntry`.
|
||||
|
||||
## 0.12.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.12.1
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -52,18 +52,17 @@ class Options extends string {
|
||||
/**
|
||||
* Holds if a call to this function will never return.
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `_Exit`, `abort`,
|
||||
* `__assert_fail`, `longjmp`, `__builtin_unreachable` and any
|
||||
* function with a `noreturn` or `__noreturn__` attribute or
|
||||
* `noreturn` specifier.
|
||||
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
|
||||
* `longjmp`, `__builtin_unreachable` and any function with a
|
||||
* `noreturn` attribute or specifier.
|
||||
*/
|
||||
predicate exits(Function f) {
|
||||
f.getAnAttribute().hasName(["noreturn", "__noreturn__"])
|
||||
f.getAnAttribute().hasName("noreturn")
|
||||
or
|
||||
f.getASpecifier().hasName("noreturn")
|
||||
or
|
||||
f.hasGlobalOrStdName([
|
||||
"exit", "_exit", "_Exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
|
||||
"exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
|
||||
])
|
||||
or
|
||||
CustomOptions::exits(f) // old Options.qll
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
/**
|
||||
* Returns the `File` matching the given source file name as encoded by the VS
|
||||
@@ -11,5 +10,13 @@ private import codeql.util.FileSystem
|
||||
*/
|
||||
cached
|
||||
File getFileBySourceArchiveName(string name) {
|
||||
result = IdeContextual<File>::getFileBySourceArchiveName(name)
|
||||
// The name provided for a file in the source archive by the VS Code extension
|
||||
// has some differences from the absolute path in the database:
|
||||
// 1. colons are replaced by underscores
|
||||
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
|
||||
// "/C_/foo/bar"
|
||||
// 3. double slashes in UNC prefixes are replaced with a single slash
|
||||
// We can handle 2 and 3 together by unconditionally adding a leading slash
|
||||
// before replacing double slashes.
|
||||
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.12.2
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,20 +0,0 @@
|
||||
## 0.12.3
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `isUserInput`, `userInputArgument`, and `userInputReturned` predicates from `SecurityOptions` have been deprecated. Use `FlowSource` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* `UserDefineLiteral` and `DeductionGuide` classes have been added, representing C++11 user defined literals and C++17 deduction guides.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Changed the output of `Node.toString` to better reflect how many indirections a given dataflow node has.
|
||||
* Added a new predicate `Node.asDefinition` on `DataFlow::Node`s for selecting the dataflow node corresponding to a particular definition.
|
||||
* The deprecated `DefaultTaintTracking` library has been removed.
|
||||
* The `Guards` library has been replaced with the API-compatible `IRGuards` implementation, which has better precision in some cases.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Under certain circumstances a function declaration that is not also a definition could be associated with a `Function` that did not have the definition as a `FunctionDeclarationEntry`. This is now fixed when only one definition exists, and a unique `Function` will exist that has both the declaration and the definition as a `FunctionDeclarationEntry`.
|
||||
@@ -1,6 +0,0 @@
|
||||
## 0.12.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted many deprecated predicates and classes with uppercase `XML`, `SSA`, `SAL`, `SQL`, etc. in their names. Use the PascalCased versions instead.
|
||||
* Deleted the deprecated `StrcatFunction` class, use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
|
||||
@@ -1,6 +0,0 @@
|
||||
## 0.12.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added the `PreprocBlock.qll` library to this repository. This library offers a view of `#if`, `#elif`, `#else` and similar directives as a tree with navigable parent-child relationships.
|
||||
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.
|
||||
@@ -1,5 +0,0 @@
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.
|
||||
@@ -1,5 +0,0 @@
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.12.8
|
||||
lastReleaseVersion: 0.12.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.12.8
|
||||
version: 0.12.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -380,6 +380,9 @@ class Class extends UserType {
|
||||
*/
|
||||
predicate isPod() { is_pod_class(underlyingElement(this)) }
|
||||
|
||||
/** DEPRECATED: Alias for isPod */
|
||||
deprecated predicate isPOD() { this.isPod() }
|
||||
|
||||
/**
|
||||
* Holds if this class, struct or union is a standard-layout class
|
||||
* [N4140 9(7)]. Also holds for structs in C programs.
|
||||
|
||||
@@ -7,7 +7,6 @@ import semmle.code.cpp.Location
|
||||
private import semmle.code.cpp.Enclosing
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
private import semmle.code.cpp.internal.ResolveGlobalVariable
|
||||
private import semmle.code.cpp.internal.ResolveFunction
|
||||
|
||||
/**
|
||||
* Get the `Element` that represents this `@element`.
|
||||
@@ -31,14 +30,11 @@ pragma[inline]
|
||||
@element unresolveElement(Element e) {
|
||||
not result instanceof @usertype and
|
||||
not result instanceof @variable and
|
||||
not result instanceof @function and
|
||||
result = e
|
||||
or
|
||||
e = resolveClass(result)
|
||||
or
|
||||
e = resolveGlobalVariable(result)
|
||||
or
|
||||
e = resolveFunction(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,6 +60,4 @@ Element exprEnclosingElement(Expr e) {
|
||||
)
|
||||
else result = de.getDeclaration()
|
||||
)
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = e
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import semmle.code.cpp.exprs.Call
|
||||
import semmle.code.cpp.metrics.MetricFunction
|
||||
import semmle.code.cpp.Linkage
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
private import semmle.code.cpp.internal.ResolveFunction
|
||||
|
||||
/**
|
||||
* A C/C++ function [N4140 8.3.5]. Both member functions and non-member
|
||||
@@ -26,8 +25,6 @@ private import semmle.code.cpp.internal.ResolveFunction
|
||||
* in more detail in `Declaration.qll`.
|
||||
*/
|
||||
class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
Function() { isFunction(underlyingElement(this)) }
|
||||
|
||||
override string getName() { functions(underlyingElement(this), result, _) }
|
||||
|
||||
/**
|
||||
@@ -331,7 +328,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
MetricFunction getMetrics() { result = this }
|
||||
|
||||
/** Holds if this function calls the function `f`. */
|
||||
pragma[nomagic]
|
||||
predicate calls(Function f) { this.calls(f, _) }
|
||||
|
||||
/**
|
||||
@@ -342,6 +338,10 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
exists(FunctionCall call |
|
||||
call.getEnclosingFunction() = this and call.getTarget() = f and call = l
|
||||
)
|
||||
or
|
||||
exists(DestructorCall call |
|
||||
call.getEnclosingFunction() = this and call.getTarget() = f and call = l
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this function accesses a function or variable or enumerator `a`. */
|
||||
@@ -885,17 +885,3 @@ class BuiltInFunction extends Function {
|
||||
}
|
||||
|
||||
private predicate suppressUnusedThis(Function f) { any() }
|
||||
|
||||
/**
|
||||
* A C++ user-defined literal [N4140 13.5.8].
|
||||
*/
|
||||
class UserDefinedLiteral extends Function {
|
||||
UserDefinedLiteral() { functions(underlyingElement(this), _, 7) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ deduction guide [N4659 17.9].
|
||||
*/
|
||||
class DeductionGuide extends Function {
|
||||
DeductionGuide() { functions(underlyingElement(this), _, 8) }
|
||||
}
|
||||
|
||||
@@ -104,6 +104,9 @@ predicate isPodClass03(Class c) {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for isPodClass03 */
|
||||
deprecated predicate isPODClass03 = isPodClass03/1;
|
||||
|
||||
/**
|
||||
* Holds if `t` is a POD type, according to the rules specified in
|
||||
* C++03 3.9(10):
|
||||
@@ -123,3 +126,6 @@ predicate isPodType03(Type t) {
|
||||
isPodType03(ut.(SpecifiedType).getUnspecifiedType())
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for isPodType03 */
|
||||
deprecated predicate isPODType03 = isPodType03/1;
|
||||
|
||||
@@ -306,14 +306,7 @@ class ExprNode extends AstNode {
|
||||
|
||||
ExprNode() { expr = ast }
|
||||
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = expr.getChild(childIndex)
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
|
||||
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
|
||||
)
|
||||
}
|
||||
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
|
||||
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
@@ -446,11 +439,6 @@ class StmtNode extends AstNode {
|
||||
result.getAst() = child.(Stmt)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(destructorIndex) and
|
||||
childIndex = destructorIndex + max(int index | exists(stmt.getChild(index)) or index = 0) + 1
|
||||
)
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -674,10 +662,6 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
|
||||
or
|
||||
not namedStmtChildPredicates(s, child, _) and
|
||||
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
|
||||
or
|
||||
exists(int n |
|
||||
s.getImplicitDestructorCall(n) = child and result = "getImplicitDestructorCall(" + n + ")"
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Expr expr | expr = parent |
|
||||
@@ -685,11 +669,6 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
|
||||
or
|
||||
not namedExprChildPredicates(expr, child, _) and
|
||||
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
|
||||
or
|
||||
exists(int n |
|
||||
expr.getImplicitDestructorCall(n) = child and
|
||||
result = "getImplicitDestructorCall(" + n + ")"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -735,9 +714,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
or
|
||||
s.(ForStmt).getStmt() = e and pred = "getStmt()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getInitialization() = e and pred = "getInitialization()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getChild(1) = e and pred = "getChild(1)"
|
||||
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)"
|
||||
or
|
||||
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
|
||||
or
|
||||
@@ -745,7 +722,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
or
|
||||
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getChild(5) = e and pred = "getChild(5)"
|
||||
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)"
|
||||
or
|
||||
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
|
||||
or
|
||||
@@ -837,11 +814,7 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
|
||||
or
|
||||
// OverloadedPointerDereferenceExpr::getExpr/0 also considers qualifiers, which are already handled above for all Call classes.
|
||||
not expr.(OverloadedPointerDereferenceExpr).getQualifier() =
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() and
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and
|
||||
pred = "getExpr()"
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()"
|
||||
or
|
||||
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
|
||||
or
|
||||
|
||||
@@ -281,11 +281,6 @@ class AttributeArgument extends Element, @attribute_arg {
|
||||
attribute_arg_constant(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this argument, if its value is an expression.
|
||||
*/
|
||||
Expr getValueExpr() { attribute_arg_expr(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* Gets the attribute to which this is an argument.
|
||||
*/
|
||||
@@ -313,10 +308,7 @@ class AttributeArgument extends Element, @attribute_arg {
|
||||
else
|
||||
if underlyingElement(this) instanceof @attribute_arg_constant_expr
|
||||
then tail = this.getValueConstant().toString()
|
||||
else
|
||||
if underlyingElement(this) instanceof @attribute_arg_expr
|
||||
then tail = this.getValueExpr().toString()
|
||||
else tail = this.getValueText()
|
||||
else tail = this.getValueText()
|
||||
) and
|
||||
result = prefix + tail
|
||||
)
|
||||
|
||||
@@ -234,16 +234,7 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
* int f(int y) { return y; }
|
||||
* ```
|
||||
*/
|
||||
override string getName() {
|
||||
exists(string name |
|
||||
var_decls(underlyingElement(this), _, _, name, _) and
|
||||
(
|
||||
name != "" and result = name
|
||||
or
|
||||
name = "" and result = this.getVariable().(LocalVariable).getName()
|
||||
)
|
||||
)
|
||||
}
|
||||
override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable which is being declared or defined.
|
||||
|
||||
@@ -32,6 +32,9 @@ class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlLocatable */
|
||||
deprecated class XMLLocatable = XmlLocatable;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
@@ -92,6 +95,9 @@ class XmlParent extends @xmlparent {
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlParent */
|
||||
deprecated class XMLParent = XmlParent;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
@@ -113,8 +119,14 @@ class XmlFile extends XmlParent, File {
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
|
||||
/** DEPRECATED: Alias for getADtd */
|
||||
deprecated XmlDtd getADTD() { result = this.getADtd() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlFile */
|
||||
deprecated class XMLFile = XmlFile;
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
@@ -151,6 +163,9 @@ class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlDtd */
|
||||
deprecated class XMLDTD = XmlDtd;
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
@@ -206,6 +221,9 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlElement */
|
||||
deprecated class XMLElement = XmlElement;
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
@@ -236,6 +254,9 @@ class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlAttribute */
|
||||
deprecated class XMLAttribute = XmlAttribute;
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
@@ -252,6 +273,9 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** DEPRECATED: Alias for getUri */
|
||||
deprecated string getURI() { result = this.getUri() }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
@@ -262,6 +286,9 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlNamespace */
|
||||
deprecated class XMLNamespace = XmlNamespace;
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
@@ -282,6 +309,9 @@ class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlComment */
|
||||
deprecated class XMLComment = XmlComment;
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
@@ -305,3 +335,6 @@ class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlCharacters */
|
||||
deprecated class XMLCharacters = XmlCharacters;
|
||||
|
||||
@@ -5,6 +5,9 @@ class NullMacro extends Macro {
|
||||
NullMacro() { this.getHead() = "NULL" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NullMacro */
|
||||
deprecated class NULLMacro = NullMacro;
|
||||
|
||||
/** A use of the NULL macro. */
|
||||
class NULL extends Literal {
|
||||
NULL() { exists(NullMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }
|
||||
|
||||
22
cpp/ql/lib/semmle/code/cpp/commons/Strcat.qll
Normal file
22
cpp/ql/lib/semmle/code/cpp/commons/Strcat.qll
Normal file
@@ -0,0 +1,22 @@
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
|
||||
*
|
||||
* A function that concatenates the string from its second argument
|
||||
* to the string from its first argument, for example `strcat`.
|
||||
*/
|
||||
deprecated class StrcatFunction extends Function {
|
||||
StrcatFunction() {
|
||||
this.getName() =
|
||||
[
|
||||
"strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
"wcscat", // wcscat(dst, src)
|
||||
"_mbscat", // _mbscat(dst, src)
|
||||
"wcsncat", // wcsncat(dst, src, max_amount)
|
||||
"_mbsncat", // _mbsncat(dst, src, max_amount)
|
||||
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* A library for detecting general string concatenations.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.models.implementations.Strcat
|
||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
/**
|
||||
* A call that performs a string concatenation. A string can be either a C
|
||||
* string (i.e., a value of type `char*`), or a C++ string (i.e., a value of
|
||||
* type `std::string`).
|
||||
*/
|
||||
class StringConcatenation extends Call {
|
||||
StringConcatenation() {
|
||||
// sprintf-like functions, i.e., concat through formatting
|
||||
this instanceof FormattingFunctionCall
|
||||
or
|
||||
this.getTarget() instanceof StrcatFunction
|
||||
or
|
||||
this.getTarget() instanceof StrlcatFunction
|
||||
or
|
||||
// operator+ and ostream (<<) concat
|
||||
exists(Call call, Operator op |
|
||||
call.getTarget() = op and
|
||||
op.hasQualifiedName(["std", "bsl"], ["operator+", "operator<<"]) and
|
||||
op.getType()
|
||||
.stripType()
|
||||
.(UserType)
|
||||
.hasQualifiedName(["std", "bsl"], ["basic_string", "basic_ostream"]) and
|
||||
this = call
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an operand of this concatenation (one of the string operands being
|
||||
* concatenated).
|
||||
* Will not return out param for sprintf-like functions, but will consider the format string
|
||||
* to be part of the operands.
|
||||
*/
|
||||
Expr getAnOperand() {
|
||||
// The result is an argument of 'this' (a call)
|
||||
result = this.getAnArgument() and
|
||||
// addresses odd behavior with overloaded operators
|
||||
// i.e., "call to operator+" appearing as an operand
|
||||
// occurs in cases like `string s = s1 + s2 + s3`, which is represented as
|
||||
// `string s = (s1.operator+(s2)).operator+(s3);`
|
||||
// By limiting to non-calls we get the leaf operands (the variables or raw strings)
|
||||
// also, by not enumerating allowed types (variables and strings) we avoid issues
|
||||
// with missed corner cases or extensions/changes to CodeQL in the future which might
|
||||
// invalidate that approach.
|
||||
not result instanceof Call and
|
||||
// Limit the result type to string
|
||||
(
|
||||
result.getUnderlyingType().stripType().getName() = "char"
|
||||
or
|
||||
result
|
||||
.getType()
|
||||
.getUnspecifiedType()
|
||||
.(UserType)
|
||||
.hasQualifiedName(["std", "bsl"], "basic_string")
|
||||
) and
|
||||
// when 'this' is a `FormattingFunctionCall` the result must be the format string argument
|
||||
// or one of the formatting arguments
|
||||
(
|
||||
this instanceof FormattingFunctionCall
|
||||
implies
|
||||
(
|
||||
result = this.(FormattingFunctionCall).getFormat()
|
||||
or
|
||||
exists(int n |
|
||||
result = this.getArgument(n) and
|
||||
n >= this.(FormattingFunctionCall).getTarget().getFirstFormatArgumentIndex()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data flow node representing the concatenation result.
|
||||
*/
|
||||
DataFlow::Node getResultNode() {
|
||||
if this.getTarget() instanceof StrcatFunction
|
||||
then
|
||||
result.asDefiningArgument() =
|
||||
this.getArgument(this.getTarget().(StrcatFunction).getParamDest())
|
||||
or
|
||||
// Hardcoding it is also the return
|
||||
result.asExpr() = this.(Call)
|
||||
else
|
||||
if this.getTarget() instanceof StrlcatFunction
|
||||
then (
|
||||
result.asDefiningArgument() =
|
||||
this.getArgument(this.getTarget().(StrlcatFunction).getParamDest())
|
||||
) else
|
||||
if this instanceof FormattingFunctionCall
|
||||
then result.asDefiningArgument() = this.(FormattingFunctionCall).getOutputArgument(_)
|
||||
else result.asExpr() = this.(Call)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,371 @@ import cpp
|
||||
import semmle.code.cpp.controlflow.BasicBlocks
|
||||
import semmle.code.cpp.controlflow.SSA
|
||||
import semmle.code.cpp.controlflow.Dominance
|
||||
import IRGuards
|
||||
|
||||
/**
|
||||
* A Boolean condition that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements.
|
||||
*/
|
||||
class GuardCondition extends Expr {
|
||||
GuardCondition() { is_condition(this) }
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `testIsTrue`.
|
||||
*
|
||||
* Illustration:
|
||||
*
|
||||
* ```
|
||||
* [ (testIsTrue) ]
|
||||
* [ this ----------------succ ---- controlled ]
|
||||
* [ | | ]
|
||||
* [ (testIsFalse) | ------ ... ]
|
||||
* [ other ]
|
||||
* ```
|
||||
*
|
||||
* The predicate holds if all paths to `controlled` go via the `testIsTrue`
|
||||
* edge of the control-flow graph. In other words, the `testIsTrue` edge
|
||||
* must dominate `controlled`. This means that `controlled` must be
|
||||
* dominated by both `this` and `succ` (the target of the `testIsTrue`
|
||||
* edge). It also means that any other edge into `succ` must be a back-edge
|
||||
* from a node which is dominated by `succ`.
|
||||
*
|
||||
* The short-circuit boolean operations have slightly surprising behavior
|
||||
* here: because the operation itself only dominates one branch (due to
|
||||
* being short-circuited) then it will only control blocks dominated by the
|
||||
* true (for `&&`) or false (for `||`) branch.
|
||||
*/
|
||||
cached
|
||||
predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
this.controlsBlock(controlled, testIsTrue)
|
||||
or
|
||||
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
|
||||
this = binop and
|
||||
lhs = binop.getLeftOperand() and
|
||||
rhs = binop.getRightOperand() and
|
||||
lhs.controls(controlled, testIsTrue) and
|
||||
rhs.controls(controlled, testIsTrue)
|
||||
)
|
||||
or
|
||||
exists(GuardCondition ne, GuardCondition operand |
|
||||
this = operand and
|
||||
operand = ne.(NotExpr).getOperand() and
|
||||
ne.controls(controlled, testIsTrue.booleanNot())
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `left >= right + k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(boolean testIsTrue |
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `left != right + k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(boolean testIsTrue |
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `testIsTrue`. This helper
|
||||
* predicate does not necessarily hold for binary logical operations like
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(BasicBlock thisblock | thisblock.contains(this) |
|
||||
exists(BasicBlock succ |
|
||||
testIsTrue = true and succ = this.getATrueSuccessor()
|
||||
or
|
||||
testIsTrue = false and succ = this.getAFalseSuccessor()
|
||||
|
|
||||
bbDominates(succ, controlled) and
|
||||
forall(BasicBlock pred | pred.getASuccessor() = succ |
|
||||
pred = thisblock or bbDominates(succ, pred) or not reachable(pred)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate is_condition(Expr guard) {
|
||||
guard.isCondition()
|
||||
or
|
||||
is_condition(guard.(BinaryLogicalOperation).getAnOperand())
|
||||
or
|
||||
exists(NotExpr cond | is_condition(cond) and cond.getOperand() = guard)
|
||||
}
|
||||
|
||||
/*
|
||||
* Simplification of equality expressions:
|
||||
* Simplify conditions in the source to the canonical form l op r + k.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
|
||||
*
|
||||
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
|
||||
*/
|
||||
private predicate compares_eq(
|
||||
Expr test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
|
||||
areEqual = true and testIsTrue = eq
|
||||
or
|
||||
areEqual = false and testIsTrue = eq.booleanNot()
|
||||
)
|
||||
or
|
||||
logical_comparison_eq(test, left, right, k, areEqual, testIsTrue)
|
||||
or
|
||||
/* a == b + k => b == a - k */
|
||||
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue))
|
||||
or
|
||||
complex_eq(test, left, right, k, areEqual, testIsTrue)
|
||||
or
|
||||
/* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */
|
||||
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
|
||||
compares_eq(test.(NotExpr).getOperand(), left, right, k, areEqual, isFalse)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If `test => part` and `part => left == right + k` then `test => left == right + k`.
|
||||
* Similarly for the case where `test` is false.
|
||||
*/
|
||||
private predicate logical_comparison_eq(
|
||||
BinaryLogicalOperation test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
exists(boolean partIsTrue, Expr part | test.impliesValue(part, partIsTrue, testIsTrue) |
|
||||
compares_eq(part, left, right, k, areEqual, partIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left == right + k` form. */
|
||||
private predicate simple_comparison_eq(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual
|
||||
) {
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = "==" and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 0 and
|
||||
areEqual = true
|
||||
or
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = "!=" and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 0 and
|
||||
areEqual = false
|
||||
}
|
||||
|
||||
private predicate complex_eq(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
|
||||
or
|
||||
add_eq(cmp, left, right, k, areEqual, testIsTrue)
|
||||
}
|
||||
|
||||
// left - x == right + c => left == right + (c+x)
|
||||
// left == (right - x) + c => left == right + (c-x)
|
||||
private predicate sub_eq(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
exists(SubExpr lhs, int c, int x |
|
||||
compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRightOperand()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(SubExpr rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRightOperand()) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
// left + x == right + c => left == right + (c-x)
|
||||
// left == (right + x) + c => left == right + (c+x)
|
||||
private predicate add_eq(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
exists(AddExpr lhs, int c, int x |
|
||||
compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(AddExpr rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
|
||||
or
|
||||
right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
|
||||
) and
|
||||
k = c + x
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Simplification of inequality expressions:
|
||||
* Simplify conditions in the source to the canonical form l < r + k.
|
||||
*/
|
||||
|
||||
/** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */
|
||||
private predicate compares_lt(
|
||||
Expr test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
/* In the simple case, the test is the comparison, so isLt = testIsTrue */
|
||||
simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true
|
||||
or
|
||||
simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false
|
||||
or
|
||||
logical_comparison_lt(test, left, right, k, isLt, testIsTrue)
|
||||
or
|
||||
complex_lt(test, left, right, k, isLt, testIsTrue)
|
||||
or
|
||||
/* (not (left < right + k)) => (left >= right + k) */
|
||||
exists(boolean isGe | isLt = isGe.booleanNot() |
|
||||
compares_ge(test, left, right, k, isGe, testIsTrue)
|
||||
)
|
||||
or
|
||||
/* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */
|
||||
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
|
||||
compares_lt(test.(NotExpr).getOperand(), left, right, k, isLt, isFalse)
|
||||
)
|
||||
}
|
||||
|
||||
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
|
||||
private predicate compares_ge(
|
||||
Expr test, Expr left, Expr right, int k, boolean isGe, boolean testIsTrue
|
||||
) {
|
||||
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue))
|
||||
}
|
||||
|
||||
/**
|
||||
* If `test => part` and `part => left < right + k` then `test => left < right + k`.
|
||||
* Similarly for the case where `test` evaluates false.
|
||||
*/
|
||||
private predicate logical_comparison_lt(
|
||||
BinaryLogicalOperation test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
exists(boolean partIsTrue, Expr part | test.impliesValue(part, partIsTrue, testIsTrue) |
|
||||
compares_lt(part, left, right, k, isLt, partIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left < right + k` form. */
|
||||
private predicate simple_comparison_lt(ComparisonOperation cmp, Expr left, Expr right, int k) {
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = "<" and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 0
|
||||
or
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = "<=" and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 1
|
||||
or
|
||||
right = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = ">" and
|
||||
left = cmp.getRightOperand() and
|
||||
k = 0
|
||||
or
|
||||
right = cmp.getLeftOperand() and
|
||||
cmp.getOperator() = ">=" and
|
||||
left = cmp.getRightOperand() and
|
||||
k = 1
|
||||
}
|
||||
|
||||
private predicate complex_lt(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
sub_lt(cmp, left, right, k, isLt, testIsTrue)
|
||||
or
|
||||
add_lt(cmp, left, right, k, isLt, testIsTrue)
|
||||
}
|
||||
|
||||
// left - x < right + c => left < right + (c+x)
|
||||
// left < (right - x) + c => left < right + (c-x)
|
||||
private predicate sub_lt(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
exists(SubExpr lhs, int c, int x |
|
||||
compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRightOperand()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(SubExpr rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRightOperand()) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
// left + x < right + c => left < right + (c-x)
|
||||
// left < (right + x) + c => left < right + (c+x)
|
||||
private predicate add_lt(
|
||||
ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
exists(AddExpr lhs, int c, int x |
|
||||
compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(AddExpr rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
|
||||
or
|
||||
right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
|
||||
) and
|
||||
k = c + x
|
||||
)
|
||||
}
|
||||
|
||||
/** The `int` value of integer constant expression. */
|
||||
private int int_value(Expr e) {
|
||||
e.getUnderlyingType() instanceof IntegralType and
|
||||
result = e.getValue().toInt()
|
||||
}
|
||||
|
||||
/** An `SsaDefinition` with an additional predicate `isLt`. */
|
||||
class GuardedSsa extends SsaDefinition {
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
|
||||
|
||||
/**
|
||||
* Holds if `block` consists of an `UnreachedInstruction`.
|
||||
@@ -205,42 +203,12 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(IRBlock irb |
|
||||
ir.controls(irb, testIsTrue) and
|
||||
nonExcludedIRAndBasicBlock(irb, controlled) and
|
||||
irb.getAnInstruction().getAst().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate excludeAsControlledInstruction(Instruction instr) {
|
||||
// Exclude the temporaries generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
instr = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueTrueTempAddressTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueFalseTempAddressTag())
|
||||
)
|
||||
or
|
||||
// Exclude unreached instructions, as their AST is the whole function and not a block.
|
||||
instr instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `irb` is the `IRBlock` corresponding to the AST basic block
|
||||
* `controlled`, and `irb` does not contain any instruction(s) that should make
|
||||
* the `irb` be ignored.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled) {
|
||||
exists(Instruction instr |
|
||||
instr = irb.getAnInstruction() and
|
||||
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not excludeAsControlledInstruction(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the IR that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements. Note that `&&` and `||`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -637,10 +637,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
any(RangeBasedForStmt for |
|
||||
i = -1 and ni = for and spec.isAt()
|
||||
or
|
||||
i = 0 and ni = for.getInitialization() and spec.isAround()
|
||||
or
|
||||
exists(DeclStmt s | s.getADeclaration() = for.getRangeVariable() |
|
||||
i = 1 and ni = s and spec.isAround()
|
||||
i = 0 and ni = s and spec.isAround()
|
||||
)
|
||||
or
|
||||
exists(DeclStmt s |
|
||||
@@ -651,22 +649,22 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
// DeclStmt in that case.
|
||||
exists(s.getADeclaration())
|
||||
|
|
||||
i = 2 and ni = s and spec.isAround()
|
||||
i = 1 and ni = s and spec.isAround()
|
||||
)
|
||||
or
|
||||
i = 3 and ni = for.getCondition() and spec.isBefore()
|
||||
i = 2 and ni = for.getCondition() and spec.isBefore()
|
||||
or
|
||||
i = 4 and /* BARRIER */ ni = for and spec.isBarrier()
|
||||
i = 3 and /* BARRIER */ ni = for and spec.isBarrier()
|
||||
or
|
||||
exists(DeclStmt declStmt | declStmt.getADeclaration() = for.getVariable() |
|
||||
i = 5 and ni = declStmt and spec.isAfter()
|
||||
i = 4 and ni = declStmt and spec.isAfter()
|
||||
)
|
||||
or
|
||||
i = 6 and ni = for.getStmt() and spec.isAround()
|
||||
i = 5 and ni = for.getStmt() and spec.isAround()
|
||||
or
|
||||
i = 7 and ni = for.getUpdate() and spec.isAround()
|
||||
i = 6 and ni = for.getUpdate() and spec.isAround()
|
||||
or
|
||||
i = 8 and ni = for.getCondition() and spec.isBefore()
|
||||
i = 7 and ni = for.getCondition() and spec.isBefore()
|
||||
)
|
||||
or
|
||||
scope =
|
||||
|
||||
@@ -110,8 +110,8 @@ private predicate loopConditionAlwaysUponEntry(ControlFlowNode loop, Expr condit
|
||||
* should be in this relation.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate isFunction(@element el) {
|
||||
el instanceof @function
|
||||
private predicate isFunction(Element el) {
|
||||
el instanceof Function
|
||||
or
|
||||
el.(Expr).getParent() = el
|
||||
}
|
||||
@@ -122,7 +122,7 @@ private predicate isFunction(@element el) {
|
||||
*/
|
||||
pragma[noopt]
|
||||
private predicate callHasNoTarget(@funbindexpr fc) {
|
||||
exists(@function f |
|
||||
exists(Function f |
|
||||
funbind(fc, f) and
|
||||
not isFunction(f)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a local analysis for identifying where a variable address
|
||||
* is effectively taken. Array-like offsets are allowed to pass through but
|
||||
* not field-like offsets.
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
@@ -58,6 +54,18 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
||||
not f.isStatic()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, Function f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user