mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
upgrading to 2.17.5
This commit is contained in:
9
.bazelrc
9
.bazelrc
@@ -10,15 +10,16 @@ common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
|
|||||||
|
|
||||||
build --repo_env=CC=clang --repo_env=CXX=clang++
|
build --repo_env=CC=clang --repo_env=CXX=clang++
|
||||||
|
|
||||||
build:linux --cxxopt=-std=c++20
|
# we use transitions that break builds of `...`, so for `test` to work with that we need the following
|
||||||
# we currently cannot built the swift extractor for ARM
|
test --build_tests_only
|
||||||
build:macos --cxxopt=-std=c++20 --copt=-arch --copt=x86_64 --linkopt=-arch --linkopt=x86_64
|
|
||||||
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
|
|
||||||
|
|
||||||
# this requires developer mode, but is required to have pack installer functioning
|
# this requires developer mode, but is required to have pack installer functioning
|
||||||
startup --windows_enable_symlinks
|
startup --windows_enable_symlinks
|
||||||
common --enable_runfiles
|
common --enable_runfiles
|
||||||
|
|
||||||
|
# with the above, we can avoid building python zips which is the default on windows as that's expensive
|
||||||
|
build --nobuild_python_zip
|
||||||
|
|
||||||
common --registry=file:///%workspace%/misc/bazel/registry
|
common --registry=file:///%workspace%/misc/bazel/registry
|
||||||
common --registry=https://bcr.bazel.build
|
common --registry=https://bcr.bazel.build
|
||||||
|
|
||||||
|
|||||||
37
.gitattributes
vendored
37
.gitattributes
vendored
@@ -50,33 +50,40 @@
|
|||||||
*.dll -text
|
*.dll -text
|
||||||
*.pdb -text
|
*.pdb -text
|
||||||
|
|
||||||
java/ql/test/stubs/**/*.java linguist-generated=true
|
/java/ql/test/stubs/**/*.java linguist-generated=true
|
||||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
/java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||||
|
/java/kotlin-extractor/deps/*.jar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
# Force git not to modify line endings for go or html files under the go/ql directory
|
# Force git not to modify line endings for go or html files under the go/ql directory
|
||||||
go/ql/**/*.go -text
|
/go/ql/**/*.go -text
|
||||||
go/ql/**/*.html -text
|
/go/ql/**/*.html -text
|
||||||
# Force git not to modify line endings for go dbschemes
|
# Force git not to modify line endings for go dbschemes
|
||||||
go/*.dbscheme -text
|
/go/*.dbscheme -text
|
||||||
# Preserve unusual line ending from codeql-go merge
|
# Preserve unusual line ending from codeql-go merge
|
||||||
go/extractor/opencsv/CSVReader.java -text
|
/go/extractor/opencsv/CSVReader.java -text
|
||||||
|
|
||||||
# For some languages, upgrade script testing references really old dbscheme
|
# For some languages, upgrade script testing references really old dbscheme
|
||||||
# files from legacy upgrades that have CRLF line endings. Since upgrade
|
# files from legacy upgrades that have CRLF line endings. Since upgrade
|
||||||
# resolution relies on object hashes, we must suppress line ending conversion
|
# resolution relies on object hashes, we must suppress line ending conversion
|
||||||
# for those testing dbscheme files.
|
# for those testing dbscheme files.
|
||||||
*/ql/lib/upgrades/initial/*.dbscheme -text
|
/*/ql/lib/upgrades/initial/*.dbscheme -text
|
||||||
|
|
||||||
# Auto-generated modeling for Python
|
# Auto-generated modeling for Python
|
||||||
python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
/python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
||||||
|
|
||||||
# auto-generated bazel lock file
|
# auto-generated bazel lock file
|
||||||
ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
/ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
||||||
ruby/extractor/cargo-bazel-lock.json -merge
|
/ruby/extractor/cargo-bazel-lock.json -merge
|
||||||
|
|
||||||
# auto-generated files for the C# build
|
# auto-generated files for the C# build
|
||||||
csharp/paket.lock linguist-generated=true
|
/csharp/paket.lock linguist-generated=true
|
||||||
# needs eol=crlf, as `paket` touches this file and saves it als crlf
|
# needs eol=crlf, as `paket` touches this file and saves it as crlf
|
||||||
csharp/.paket/Paket.Restore.targets linguist-generated=true eol=crlf
|
/csharp/.paket/Paket.Restore.targets linguist-generated=true eol=crlf
|
||||||
csharp/paket.main.bzl linguist-generated=true
|
/csharp/paket.main.bzl linguist-generated=true
|
||||||
csharp/paket.main_extension.bzl linguist-generated=true
|
/csharp/paket.main_extension.bzl linguist-generated=true
|
||||||
|
|
||||||
|
# ripunzip tool
|
||||||
|
/misc/ripunzip/ripunzip-* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
|
# swift prebuilt resources
|
||||||
|
/swift/third_party/resource-dir/*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|||||||
4
.github/workflows/csharp-qltest.yml
vendored
4
.github/workflows/csharp-qltest.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
|||||||
key: csharp-qltest-${{ matrix.slice }}
|
key: csharp-qltest-${{ matrix.slice }}
|
||||||
- name: Run QL tests
|
- name: Run QL tests
|
||||||
run: |
|
run: |
|
||||||
codeql test run --threads=0 --ram 50000 --slice ${{ matrix.slice }} --search-path extractor-pack --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
codeql test run --threads=0 --ram 50000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
unit-tests:
|
unit-tests:
|
||||||
@@ -101,6 +101,6 @@ jobs:
|
|||||||
# Update existing stubs in the repo with the freshly generated ones
|
# Update existing stubs in the repo with the freshly generated ones
|
||||||
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
|
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
|
||||||
git status
|
git status
|
||||||
codeql test run --threads=0 --search-path extractor-pack --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
|
codeql test run --threads=0 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|||||||
3
.github/workflows/go-tests-other-os.yml
vendored
3
.github/workflows/go-tests-other-os.yml
vendored
@@ -7,6 +7,9 @@ on:
|
|||||||
- .github/workflows/go-tests-other-os.yml
|
- .github/workflows/go-tests-other-os.yml
|
||||||
- .github/actions/**
|
- .github/actions/**
|
||||||
- codeql-workspace.yml
|
- codeql-workspace.yml
|
||||||
|
- MODULE.bazel
|
||||||
|
- .bazelrc
|
||||||
|
- misc/bazel/**
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
3
.github/workflows/go-tests.yml
vendored
3
.github/workflows/go-tests.yml
vendored
@@ -15,6 +15,9 @@ on:
|
|||||||
- .github/workflows/go-tests.yml
|
- .github/workflows/go-tests.yml
|
||||||
- .github/actions/**
|
- .github/actions/**
|
||||||
- codeql-workspace.yml
|
- codeql-workspace.yml
|
||||||
|
- MODULE.bazel
|
||||||
|
- .bazelrc
|
||||||
|
- misc/bazel/**
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
28
.github/workflows/kotlin-build.yml
vendored
Normal file
28
.github/workflows/kotlin-build.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: "Kotlin Build"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "java/kotlin-extractor/**"
|
||||||
|
- "misc/bazel/**"
|
||||||
|
- "misc/codegen/**"
|
||||||
|
- "*.bazel*"
|
||||||
|
- .github/workflows/kotlin-build.yml
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- rc/*
|
||||||
|
- codeql-cli-*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: |
|
||||||
|
bazel query //java/kotlin-extractor/...
|
||||||
|
# only build the default version as a quick check that we can build from `codeql`
|
||||||
|
# the full official build will be checked by QLucie
|
||||||
|
bazel build //java/kotlin-extractor
|
||||||
10
.github/workflows/ql-for-ql-build.yml
vendored
10
.github/workflows/ql-for-ql-build.yml
vendored
@@ -49,20 +49,20 @@ jobs:
|
|||||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
||||||
- name: Release build
|
- name: Release build
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: cd ql; ./scripts/create-extractor-pack.sh
|
run: cd ql; ./scripts/create-extractor-pack.sh
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
- name: Cache compilation cache
|
- name: Cache compilation cache
|
||||||
id: query-cache
|
id: query-cache
|
||||||
uses: ./.github/actions/cache-query-compilation
|
uses: ./.github/actions/cache-query-compilation
|
||||||
with:
|
with:
|
||||||
key: run-ql-for-ql
|
key: run-ql-for-ql
|
||||||
- name: Make database and analyze
|
- name: Make database and analyze
|
||||||
run: |
|
run: |
|
||||||
./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse.
|
./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse.
|
||||||
${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB}
|
${CODEQL} database create -l=ql ${DB} --search-path "${{ github.workspace }}"
|
||||||
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
DB: ${{ runner.temp }}/DB
|
DB: ${{ runner.temp }}/DB
|
||||||
LGTM_INDEX_FILTERS: |
|
LGTM_INDEX_FILTERS: |
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ jobs:
|
|||||||
- name: Create database
|
- name: Create database
|
||||||
run: |
|
run: |
|
||||||
"${CODEQL}" database create \
|
"${CODEQL}" database create \
|
||||||
--search-path "ql/extractor-pack" \
|
--search-path "${{ github.workspace }}"
|
||||||
--threads 4 \
|
--threads 4 \
|
||||||
--language ql --source-root "${{ github.workspace }}/repo" \
|
--language ql --source-root "${{ github.workspace }}/repo" \
|
||||||
"${{ runner.temp }}/database"
|
"${{ runner.temp }}/database"
|
||||||
env:
|
env:
|
||||||
|
|||||||
13
.github/workflows/ql-for-ql-tests.yml
vendored
13
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -49,15 +49,15 @@ jobs:
|
|||||||
- name: Cache compilation cache
|
- name: Cache compilation cache
|
||||||
id: query-cache
|
id: query-cache
|
||||||
uses: ./.github/actions/cache-query-compilation
|
uses: ./.github/actions/cache-query-compilation
|
||||||
with:
|
with:
|
||||||
key: ql-for-ql-tests
|
key: ql-for-ql-tests
|
||||||
- name: Run QL tests
|
- name: Run QL tests
|
||||||
run: |
|
run: |
|
||||||
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" ql/ql/test
|
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}" --consistency-queries ql/ql/consistency-queries --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" ql/ql/test
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
|
|
||||||
other-os:
|
other-os:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, windows-latest]
|
os: [macos-latest, windows-latest]
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install GNU tar
|
- name: Install GNU tar
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew install gnu-tar
|
brew install gnu-tar
|
||||||
@@ -100,7 +100,7 @@ jobs:
|
|||||||
- name: Run a single QL tests - Unix
|
- name: Run a single QL tests - Unix
|
||||||
if: runner.os != 'Windows'
|
if: runner.os != 'Windows'
|
||||||
run: |
|
run: |
|
||||||
"${CODEQL}" test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
"${CODEQL}" test run --check-databases --search-path "${{ github.workspace }}" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
- name: Run a single QL tests - Windows
|
- name: Run a single QL tests - Windows
|
||||||
@@ -108,5 +108,4 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
$Env:PATH += ";$(dirname ${{ steps.find-codeql.outputs.codeql-path }})"
|
$Env:PATH += ";$(dirname ${{ steps.find-codeql.outputs.codeql-path }})"
|
||||||
codeql test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
codeql test run --check-databases --search-path "${{ github.workspace }}" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/ruby-dataset-measure.yml
vendored
2
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
|||||||
- name: Create database
|
- name: Create database
|
||||||
run: |
|
run: |
|
||||||
codeql database create \
|
codeql database create \
|
||||||
--search-path "${{ github.workspace }}/ruby/extractor-pack" \
|
--search-path "${{ github.workspace }}" \
|
||||||
--threads 4 \
|
--threads 4 \
|
||||||
--language ruby --source-root "${{ github.workspace }}/repo" \
|
--language ruby --source-root "${{ github.workspace }}/repo" \
|
||||||
"${{ runner.temp }}/database"
|
"${{ runner.temp }}/database"
|
||||||
|
|||||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -64,10 +64,10 @@ jobs:
|
|||||||
- name: Cache compilation cache
|
- name: Cache compilation cache
|
||||||
id: query-cache
|
id: query-cache
|
||||||
uses: ./.github/actions/cache-query-compilation
|
uses: ./.github/actions/cache-query-compilation
|
||||||
with:
|
with:
|
||||||
key: ruby-qltest
|
key: ruby-qltest
|
||||||
- name: Run QL tests
|
- name: Run QL tests
|
||||||
run: |
|
run: |
|
||||||
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|||||||
15
.github/workflows/swift.yml
vendored
15
.github/workflows/swift.yml
vendored
@@ -68,21 +68,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: ./swift/actions/run-ql-tests
|
- 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' }}
|
|
||||||
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:
|
clang-format:
|
||||||
if : ${{ github.event_name == 'pull_request' }}
|
if : ${{ github.event_name == 'pull_request' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
23
.github/workflows/zipmerge-test.yml
vendored
Normal file
23
.github/workflows/zipmerge-test.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: "Test zipmerge code"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "misc/bazel/internal/zipmerge/**"
|
||||||
|
- "MODULE.bazel"
|
||||||
|
- ".bazelrc*"
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- "rc/*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: |
|
||||||
|
bazel test //misc/bazel/internal/zipmerge:test --test_output=all
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -62,3 +62,6 @@ node_modules/
|
|||||||
|
|
||||||
# Temporary folders for working with generated models
|
# Temporary folders for working with generated models
|
||||||
.model-temp
|
.model-temp
|
||||||
|
|
||||||
|
# bazel-built in-tree extractor packs
|
||||||
|
/*/extractor-pack
|
||||||
|
|||||||
@@ -2,4 +2,6 @@
|
|||||||
# codeql is publicly forked by many users, and we don't want any LFS file polluting their working
|
# codeql is publicly forked by many users, and we don't want any LFS file polluting their working
|
||||||
# copies. We therefore exclude everything by default.
|
# copies. We therefore exclude everything by default.
|
||||||
# For files required by bazel builds, use rules in `misc/bazel/lfs.bzl` to download them on demand.
|
# For files required by bazel builds, use rules in `misc/bazel/lfs.bzl` to download them on demand.
|
||||||
|
# we go for `fetchinclude` to something not exsiting rather than `fetchexclude = *` because the
|
||||||
|
# former is easier to override (with `git -c` or a local git config) to fetch something specific
|
||||||
fetchinclude = /nothing
|
fetchinclude = /nothing
|
||||||
|
|||||||
77
MODULE.bazel
77
MODULE.bazel
@@ -22,8 +22,10 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
|||||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
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 = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||||
bazel_dep(name = "fmt", version = "10.0.0")
|
bazel_dep(name = "fmt", version = "10.0.0")
|
||||||
|
bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
|
||||||
bazel_dep(name = "gazelle", version = "0.36.0")
|
bazel_dep(name = "gazelle", version = "0.36.0")
|
||||||
bazel_dep(name = "rules_dotnet", version = "0.15.1")
|
bazel_dep(name = "rules_dotnet", version = "0.15.1")
|
||||||
|
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||||
|
|
||||||
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
||||||
|
|
||||||
@@ -64,9 +66,84 @@ node.toolchain(
|
|||||||
)
|
)
|
||||||
use_repo(node, "nodejs", "nodejs_toolchains")
|
use_repo(node, "nodejs", "nodejs_toolchains")
|
||||||
|
|
||||||
|
kotlin_extractor_deps = use_extension("//java/kotlin-extractor:deps.bzl", "kotlin_extractor_deps")
|
||||||
|
|
||||||
|
# following list can be kept in sync by running `bazel mod tidy` in `codeql`
|
||||||
|
use_repo(
|
||||||
|
kotlin_extractor_deps,
|
||||||
|
"codeql_kotlin_defaults",
|
||||||
|
"codeql_kotlin_embeddable",
|
||||||
|
"kotlin-compiler-1.5.0",
|
||||||
|
"kotlin-compiler-1.5.10",
|
||||||
|
"kotlin-compiler-1.5.20",
|
||||||
|
"kotlin-compiler-1.5.30",
|
||||||
|
"kotlin-compiler-1.6.0",
|
||||||
|
"kotlin-compiler-1.6.20",
|
||||||
|
"kotlin-compiler-1.7.0",
|
||||||
|
"kotlin-compiler-1.7.20",
|
||||||
|
"kotlin-compiler-1.8.0",
|
||||||
|
"kotlin-compiler-1.9.0-Beta",
|
||||||
|
"kotlin-compiler-1.9.20-Beta",
|
||||||
|
"kotlin-compiler-2.0.0-RC1",
|
||||||
|
"kotlin-compiler-embeddable-1.5.0",
|
||||||
|
"kotlin-compiler-embeddable-1.5.10",
|
||||||
|
"kotlin-compiler-embeddable-1.5.20",
|
||||||
|
"kotlin-compiler-embeddable-1.5.30",
|
||||||
|
"kotlin-compiler-embeddable-1.6.0",
|
||||||
|
"kotlin-compiler-embeddable-1.6.20",
|
||||||
|
"kotlin-compiler-embeddable-1.7.0",
|
||||||
|
"kotlin-compiler-embeddable-1.7.20",
|
||||||
|
"kotlin-compiler-embeddable-1.8.0",
|
||||||
|
"kotlin-compiler-embeddable-1.9.0-Beta",
|
||||||
|
"kotlin-compiler-embeddable-1.9.20-Beta",
|
||||||
|
"kotlin-compiler-embeddable-2.0.0-RC1",
|
||||||
|
"kotlin-stdlib-1.5.0",
|
||||||
|
"kotlin-stdlib-1.5.10",
|
||||||
|
"kotlin-stdlib-1.5.20",
|
||||||
|
"kotlin-stdlib-1.5.30",
|
||||||
|
"kotlin-stdlib-1.6.0",
|
||||||
|
"kotlin-stdlib-1.6.20",
|
||||||
|
"kotlin-stdlib-1.7.0",
|
||||||
|
"kotlin-stdlib-1.7.20",
|
||||||
|
"kotlin-stdlib-1.8.0",
|
||||||
|
"kotlin-stdlib-1.9.0-Beta",
|
||||||
|
"kotlin-stdlib-1.9.20-Beta",
|
||||||
|
"kotlin-stdlib-2.0.0-RC1",
|
||||||
|
)
|
||||||
|
|
||||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||||
go_sdk.download(version = "1.22.2")
|
go_sdk.download(version = "1.22.2")
|
||||||
|
|
||||||
|
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
|
||||||
|
|
||||||
|
lfs_files(
|
||||||
|
name = "ripunzip-linux",
|
||||||
|
srcs = ["//misc/ripunzip:ripunzip-linux"],
|
||||||
|
executable = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
lfs_files(
|
||||||
|
name = "ripunzip-windows",
|
||||||
|
srcs = ["//misc/ripunzip:ripunzip-windows.exe"],
|
||||||
|
executable = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
lfs_files(
|
||||||
|
name = "ripunzip-macos",
|
||||||
|
srcs = ["//misc/ripunzip:ripunzip-macos"],
|
||||||
|
executable = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
lfs_files(
|
||||||
|
name = "swift-resource-dir-linux",
|
||||||
|
srcs = ["//swift/third_party/resource-dir:resource-dir-linux.zip"],
|
||||||
|
)
|
||||||
|
|
||||||
|
lfs_files(
|
||||||
|
name = "swift-resource-dir-macos",
|
||||||
|
srcs = ["//swift/third_party/resource-dir:resource-dir-macos.zip"],
|
||||||
|
)
|
||||||
|
|
||||||
register_toolchains(
|
register_toolchains(
|
||||||
"@nodejs_toolchains//:all",
|
"@nodejs_toolchains//:all",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,19 +6,16 @@ provide:
|
|||||||
- "*/ql/consistency-queries/qlpack.yml"
|
- "*/ql/consistency-queries/qlpack.yml"
|
||||||
- "*/ql/automodel/src/qlpack.yml"
|
- "*/ql/automodel/src/qlpack.yml"
|
||||||
- "*/ql/automodel/test/qlpack.yml"
|
- "*/ql/automodel/test/qlpack.yml"
|
||||||
|
- "*/extractor-pack/codeql-extractor.yml"
|
||||||
- "python/extractor/qlpack.yml"
|
- "python/extractor/qlpack.yml"
|
||||||
- "shared/**/qlpack.yml"
|
- "shared/**/qlpack.yml"
|
||||||
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
||||||
- "go/ql/config/legacy-support/qlpack.yml"
|
- "go/ql/config/legacy-support/qlpack.yml"
|
||||||
- "go/build/codeql-extractor-go/codeql-extractor.yml"
|
|
||||||
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
|
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
|
||||||
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
|
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
|
||||||
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"
|
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"
|
||||||
- "misc/legacy-support/*/qlpack.yml"
|
- "misc/legacy-support/*/qlpack.yml"
|
||||||
- "misc/suite-helpers/qlpack.yml"
|
- "misc/suite-helpers/qlpack.yml"
|
||||||
- "ruby/extractor-pack/codeql-extractor.yml"
|
|
||||||
- "swift/extractor-pack/codeql-extractor.yml"
|
|
||||||
- "ql/extractor-pack/codeql-extractor.yml"
|
|
||||||
- ".github/codeql/extensions/**/codeql-pack.yml"
|
- ".github/codeql/extensions/**/codeql-pack.yml"
|
||||||
|
|
||||||
versionPolicies:
|
versionPolicies:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ pkg_files(
|
|||||||
["**"],
|
["**"],
|
||||||
exclude = ["BUILD.bazel"],
|
exclude = ["BUILD.bazel"],
|
||||||
),
|
),
|
||||||
prefix = "cpp/downgrades",
|
prefix = "downgrades",
|
||||||
strip_prefix = strip_prefix.from_pkg(),
|
strip_prefix = strip_prefix.from_pkg(),
|
||||||
visibility = ["//cpp:__pkg__"],
|
visibility = ["//cpp:__pkg__"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ package(default_visibility = ["//cpp:__pkg__"])
|
|||||||
pkg_files(
|
pkg_files(
|
||||||
name = "dbscheme",
|
name = "dbscheme",
|
||||||
srcs = ["semmlecode.cpp.dbscheme"],
|
srcs = ["semmlecode.cpp.dbscheme"],
|
||||||
prefix = "cpp",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pkg_files(
|
pkg_files(
|
||||||
name = "dbscheme-stats",
|
name = "dbscheme-stats",
|
||||||
srcs = ["semmlecode.cpp.dbscheme.stats"],
|
srcs = ["semmlecode.cpp.dbscheme.stats"],
|
||||||
prefix = "cpp",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
9
cpp/ql/lib/change-notes/released/1.1.0.md
Normal file
9
cpp/ql/lib/change-notes/released/1.1.0.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 1.0.0
|
lastReleaseVersion: 1.1.0
|
||||||
|
|||||||
26
cpp/ql/lib/ext/Boost.Asio.model.yml
Normal file
26
cpp/ql/lib/ext/Boost.Asio.model.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
extensions:
|
||||||
|
# partial model of the Boost::Asio network library
|
||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sourceModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||||
|
- ["boost::asio", "", False, "read", "", "", "Argument[*1]", "remote", "manual"]
|
||||||
|
- ["boost::asio", "", False, "read_at", "", "", "Argument[*2]", "remote", "manual"]
|
||||||
|
- ["boost::asio", "", False, "read_until", "", "", "Argument[*1]", "remote", "manual"]
|
||||||
|
- ["boost::asio", "", False, "async_read", "", "", "Argument[*1]", "remote", "manual"]
|
||||||
|
- ["boost::asio", "", False, "async_read_at", "", "", "Argument[*2]", "remote", "manual"]
|
||||||
|
- ["boost::asio", "", False, "async_read_until", "", "", "Argument[*1]", "remote", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sinkModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
|
||||||
|
- ["boost::asio", "", False, "write", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||||
|
- ["boost::asio", "", False, "write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
|
||||||
|
- ["boost::asio", "", False, "async_write", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||||
|
- ["boost::asio", "", False, "async_write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: summaryModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||||
|
- ["boost::asio", "", False, "buffer", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]
|
||||||
15
cpp/ql/lib/ext/empty.model.yml
Normal file
15
cpp/ql/lib/ext/empty.model.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
extensions:
|
||||||
|
# Make sure that the extensible model predicates have at least one definition
|
||||||
|
# to avoid errors about undefined extensionals.
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sourceModel
|
||||||
|
data: []
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sinkModel
|
||||||
|
data: []
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: summaryModel
|
||||||
|
data: []
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 1.0.0
|
version: 1.1.0
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
@@ -14,4 +14,6 @@ dependencies:
|
|||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
codeql/xml: ${workspace}
|
codeql/xml: ${workspace}
|
||||||
|
dataExtensions:
|
||||||
|
- ext/*.model.yml
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
|
|||||||
@@ -410,6 +410,10 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
|
|||||||
or
|
or
|
||||||
orphaned_variables(underlyingElement(this), unresolveElement(result))
|
orphaned_variables(underlyingElement(this), unresolveElement(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate isStatic() {
|
||||||
|
super.isStatic() or orphaned_variables(underlyingElement(this), _)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -375,6 +375,33 @@ cached
|
|||||||
class IRGuardCondition extends Instruction {
|
class IRGuardCondition extends Instruction {
|
||||||
Instruction branch;
|
Instruction branch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An `IRGuardCondition` supports reasoning about four different kinds of
|
||||||
|
* relations:
|
||||||
|
* 1. A unary equality relation of the form `e == k`
|
||||||
|
* 2. A binary equality relation of the form `e1 == e2 + k`
|
||||||
|
* 3. A unary inequality relation of the form `e < k`
|
||||||
|
* 4. A binary inequality relation of the form `e1 < e2 + k`
|
||||||
|
*
|
||||||
|
* where `k` is a constant.
|
||||||
|
*
|
||||||
|
* Furthermore, the unary relations (i.e., case 1 and case 3) are also
|
||||||
|
* inferred from `switch` statement guards: equality relations are inferred
|
||||||
|
* from the unique `case` statement, if any, and inequality relations are
|
||||||
|
* inferred from the [case range](https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html)
|
||||||
|
* gcc extension.
|
||||||
|
*
|
||||||
|
* The implementation of all four follows the same structure: Each relation
|
||||||
|
* has a cached user-facing predicate that. For example,
|
||||||
|
* `GuardCondition::comparesEq` calls `compares_eq`. This predicate has
|
||||||
|
* several cases that recursively decompose the relation to bring it to a
|
||||||
|
* canonical form (i.e., a relation of the form `e1 == e2 + k`). The base
|
||||||
|
* case for this relation (i.e., `simple_comparison_eq`) handles
|
||||||
|
* `CompareEQInstruction`s and `CompareNEInstruction`, and recursive
|
||||||
|
* predicates (e.g., `complex_eq`) rewrites larger expressions such as
|
||||||
|
* `e1 + k1 == e2 + k2` into canonical the form `e1 == e2 + (k2 - k1)`.
|
||||||
|
*/
|
||||||
|
|
||||||
cached
|
cached
|
||||||
IRGuardCondition() { branch = getBranchForCondition(this) }
|
IRGuardCondition() { branch = getBranchForCondition(this) }
|
||||||
|
|
||||||
@@ -776,7 +803,9 @@ private predicate unary_compares_eq(
|
|||||||
Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
|
Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
|
||||||
) {
|
) {
|
||||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||||
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
|
exists(AbstractValue v |
|
||||||
|
unary_simple_comparison_eq(test, k, inNonZeroCase, v) and op.getDef() = test
|
||||||
|
|
|
||||||
areEqual = true and value = v
|
areEqual = true and value = v
|
||||||
or
|
or
|
||||||
areEqual = false and value = v.getDualValue()
|
areEqual = false and value = v.getDualValue()
|
||||||
@@ -821,45 +850,55 @@ private predicate simple_comparison_eq(
|
|||||||
value.(BooleanValue).getValue() = false
|
value.(BooleanValue).getValue() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `test` is an instruction that is part of test that eventually is
|
|
||||||
* used in a conditional branch.
|
|
||||||
*/
|
|
||||||
private predicate relevantUnaryComparison(Instruction test) {
|
|
||||||
not test instanceof CompareInstruction and
|
|
||||||
exists(IRType type, ConditionalBranchInstruction branch |
|
|
||||||
type instanceof IRAddressType or type instanceof IRIntegerType
|
|
||||||
|
|
|
||||||
type = test.getResultIRType() and
|
|
||||||
branch.getCondition() = test
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(LogicalNotInstruction logicalNot |
|
|
||||||
relevantUnaryComparison(logicalNot) and
|
|
||||||
test = logicalNot.getUnary()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rearrange various simple comparisons into `op == k` form.
|
* Rearrange various simple comparisons into `op == k` form.
|
||||||
*/
|
*/
|
||||||
private predicate unary_simple_comparison_eq(
|
private predicate unary_simple_comparison_eq(
|
||||||
Instruction test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
|
Instruction test, int k, boolean inNonZeroCase, AbstractValue value
|
||||||
) {
|
) {
|
||||||
exists(SwitchInstruction switch, CaseEdge case |
|
exists(SwitchInstruction switch, CaseEdge case |
|
||||||
test = switch.getExpression() and
|
test = switch.getExpression() and
|
||||||
op.getDef() = test and
|
|
||||||
case = value.(MatchValue).getCase() and
|
case = value.(MatchValue).getCase() and
|
||||||
exists(switch.getSuccessor(case)) and
|
exists(switch.getSuccessor(case)) and
|
||||||
case.getValue().toInt() = k and
|
case.getValue().toInt() = k and
|
||||||
inNonZeroCase = false
|
inNonZeroCase = false
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// There's no implicit CompareInstruction in files compiled as C since C
|
// Any instruction with an integral type could potentially be part of a
|
||||||
// doesn't have implicit boolean conversions. So instead we check whether
|
// check for nullness when used in a guard. So we include all integral
|
||||||
// there's a branch on a value of pointer or integer type.
|
// typed instructions here. However, since some of these instructions are
|
||||||
relevantUnaryComparison(test) and
|
// already included as guards in other cases, we exclude those here.
|
||||||
op.getDef() = test and
|
// These are instructions that compute a binary equality or inequality
|
||||||
|
// relation. For example, the following:
|
||||||
|
// ```cpp
|
||||||
|
// if(a == b + 42) { ... }
|
||||||
|
// ```
|
||||||
|
// generates the following IR:
|
||||||
|
// ```
|
||||||
|
// r1(glval<int>) = VariableAddress[a] :
|
||||||
|
// r2(int) = Load[a] : &:r1, m1
|
||||||
|
// r3(glval<int>) = VariableAddress[b] :
|
||||||
|
// r4(int) = Load[b] : &:r3, m2
|
||||||
|
// r5(int) = Constant[42] :
|
||||||
|
// r6(int) = Add : r4, r5
|
||||||
|
// r7(bool) = CompareEQ : r2, r6
|
||||||
|
// v1(void) = ConditionalBranch : r7
|
||||||
|
// ```
|
||||||
|
// and since `r7` is an integral typed instruction this predicate could
|
||||||
|
// include a case for when `r7` evaluates to true (in which case we would
|
||||||
|
// infer that `r6` was non-zero, and a case for when `r7` evaluates to false
|
||||||
|
// (in which case we would infer that `r6` was zero).
|
||||||
|
// However, since `a == b + 42` is already supported when reasoning about
|
||||||
|
// binary equalities we exclude those cases here.
|
||||||
|
not test.isGLValue() and
|
||||||
|
not simple_comparison_eq(test, _, _, _, _) and
|
||||||
|
not simple_comparison_lt(test, _, _, _) and
|
||||||
|
not test = any(SwitchInstruction switch).getExpression() and
|
||||||
|
(
|
||||||
|
test.getResultIRType() instanceof IRAddressType or
|
||||||
|
test.getResultIRType() instanceof IRIntegerType or
|
||||||
|
test.getResultIRType() instanceof IRBooleanType
|
||||||
|
) and
|
||||||
(
|
(
|
||||||
k = 1 and
|
k = 1 and
|
||||||
value.(BooleanValue).getValue() = true and
|
value.(BooleanValue).getValue() = true and
|
||||||
@@ -913,7 +952,8 @@ private predicate compares_lt(
|
|||||||
|
|
||||||
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
|
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
|
||||||
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
|
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
|
||||||
simple_comparison_lt(test, op, k, isLt, value)
|
unary_simple_comparison_lt(test, k, isLt, value) and
|
||||||
|
op.getDef() = test
|
||||||
or
|
or
|
||||||
complex_lt(test, op, k, isLt, value)
|
complex_lt(test, op, k, isLt, value)
|
||||||
or
|
or
|
||||||
@@ -960,12 +1000,11 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Rearrange various simple comparisons into `op < k` form. */
|
/** Rearrange various simple comparisons into `op < k` form. */
|
||||||
private predicate simple_comparison_lt(
|
private predicate unary_simple_comparison_lt(
|
||||||
Instruction test, Operand op, int k, boolean isLt, AbstractValue value
|
Instruction test, int k, boolean isLt, AbstractValue value
|
||||||
) {
|
) {
|
||||||
exists(SwitchInstruction switch, CaseEdge case |
|
exists(SwitchInstruction switch, CaseEdge case |
|
||||||
test = switch.getExpression() and
|
test = switch.getExpression() and
|
||||||
op.getDef() = test and
|
|
||||||
case = value.(MatchValue).getCase() and
|
case = value.(MatchValue).getCase() and
|
||||||
exists(switch.getSuccessor(case)) and
|
exists(switch.getSuccessor(case)) and
|
||||||
case.getMaxValue() > case.getMinValue()
|
case.getMaxValue() > case.getMinValue()
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ private import internal.FlowSummaryImpl
|
|||||||
private import internal.FlowSummaryImpl::Public
|
private import internal.FlowSummaryImpl::Public
|
||||||
private import internal.FlowSummaryImpl::Private
|
private import internal.FlowSummaryImpl::Private
|
||||||
private import internal.FlowSummaryImpl::Private::External
|
private import internal.FlowSummaryImpl::Private::External
|
||||||
|
private import internal.ExternalFlowExtensions as Extensions
|
||||||
private import codeql.mad.ModelValidation as SharedModelVal
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
private import codeql.util.Unit
|
private import codeql.util.Unit
|
||||||
|
|
||||||
@@ -138,6 +139,9 @@ predicate sourceModel(
|
|||||||
row.splitAt(";", 7) = kind
|
row.splitAt(";", 7) = kind
|
||||||
) and
|
) and
|
||||||
provenance = "manual"
|
provenance = "manual"
|
||||||
|
or
|
||||||
|
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance,
|
||||||
|
_)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if a sink model exists for the given parameters. */
|
/** Holds if a sink model exists for the given parameters. */
|
||||||
@@ -158,6 +162,8 @@ predicate sinkModel(
|
|||||||
row.splitAt(";", 7) = kind
|
row.splitAt(";", 7) = kind
|
||||||
) and
|
) and
|
||||||
provenance = "manual"
|
provenance = "manual"
|
||||||
|
or
|
||||||
|
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if a summary model exists for the given parameters. */
|
/** Holds if a summary model exists for the given parameters. */
|
||||||
@@ -179,6 +185,9 @@ predicate summaryModel(
|
|||||||
row.splitAt(";", 8) = kind
|
row.splitAt(";", 8) = kind
|
||||||
) and
|
) and
|
||||||
provenance = "manual"
|
provenance = "manual"
|
||||||
|
or
|
||||||
|
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
|
||||||
|
provenance, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate relevantNamespace(string namespace) {
|
private predicate relevantNamespace(string namespace) {
|
||||||
@@ -203,8 +212,10 @@ private predicate canonicalNamespaceLink(string namespace, string subns) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if CSV framework coverage of `namespace` is `n` api endpoints of the
|
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
|
||||||
* kind `(kind, part)`.
|
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
|
||||||
|
* `namespace` which have MaD framework coverage (including `namespace`
|
||||||
|
* itself).
|
||||||
*/
|
*/
|
||||||
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
|
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
|
||||||
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
|
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
|
||||||
@@ -321,10 +332,10 @@ module CsvValidation {
|
|||||||
or
|
or
|
||||||
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
|
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
|
||||||
|
|
|
|
||||||
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
|
||||||
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
|
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
|
||||||
or
|
or
|
||||||
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
|
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]*") and
|
||||||
result = "Dubious type \"" + type + "\" in " + pred + " model."
|
result = "Dubious type \"" + type + "\" in " + pred + " model."
|
||||||
or
|
or
|
||||||
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
|
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* This module provides extensible predicates for defining MaD models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if an external source model exists for the given parameters.
|
||||||
|
*/
|
||||||
|
extensible predicate sourceModel(
|
||||||
|
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if an external sink model exists for the given parameters.
|
||||||
|
*/
|
||||||
|
extensible predicate sinkModel(
|
||||||
|
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if an external summary model exists for the given parameters.
|
||||||
|
*/
|
||||||
|
extensible predicate summaryModel(
|
||||||
|
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
);
|
||||||
@@ -1343,6 +1343,8 @@ predicate nodeIsHidden(Node n) {
|
|||||||
n instanceof FinalGlobalValue
|
n instanceof FinalGlobalValue
|
||||||
or
|
or
|
||||||
n instanceof InitialGlobalValue
|
n instanceof InitialGlobalValue
|
||||||
|
or
|
||||||
|
n instanceof SsaPhiInputNode
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate neverSkipInPathGraph(Node n) {
|
predicate neverSkipInPathGraph(Node n) {
|
||||||
@@ -1641,6 +1643,8 @@ private Instruction getAnInstruction(Node n) {
|
|||||||
or
|
or
|
||||||
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction()
|
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction()
|
||||||
or
|
or
|
||||||
|
result = n.(SsaPhiInputNode).getBasicBlock().getFirstInstruction()
|
||||||
|
or
|
||||||
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _)
|
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _)
|
||||||
or
|
or
|
||||||
not n instanceof IndirectInstruction and
|
not n instanceof IndirectInstruction and
|
||||||
@@ -1770,7 +1774,7 @@ module IteratorFlow {
|
|||||||
crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
|
crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
|
||||||
sv = def.getSourceVariable() and
|
sv = def.getSourceVariable() and
|
||||||
bb.getInstruction(i) = crementCall and
|
bb.getInstruction(i) = crementCall and
|
||||||
Ssa::ssaDefReachesRead(sv, result.asDef(), bb, i)
|
Ssa::ssaDefReachesReadExt(sv, result.asDef(), bb, i)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1804,7 +1808,7 @@ module IteratorFlow {
|
|||||||
isIteratorWrite(writeToDeref, address) and
|
isIteratorWrite(writeToDeref, address) and
|
||||||
operandForFullyConvertedCall(address, starCall) and
|
operandForFullyConvertedCall(address, starCall) and
|
||||||
bbStar.getInstruction(iStar) = starCall and
|
bbStar.getInstruction(iStar) = starCall and
|
||||||
Ssa::ssaDefReachesRead(_, def.asDef(), bbStar, iStar) and
|
Ssa::ssaDefReachesReadExt(_, def.asDef(), bbStar, iStar) and
|
||||||
ultimate = getAnUltimateDefinition*(def) and
|
ultimate = getAnUltimateDefinition*(def) and
|
||||||
beginStore = ultimate.getValue().asInstruction() and
|
beginStore = ultimate.getValue().asInstruction() and
|
||||||
operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)
|
operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ private newtype TIRDataFlowNode =
|
|||||||
or
|
or
|
||||||
Ssa::isModifiableByCall(operand, indirectionIndex)
|
Ssa::isModifiableByCall(operand, indirectionIndex)
|
||||||
} or
|
} or
|
||||||
|
TSsaPhiInputNode(Ssa::PhiNode phi, IRBlock input) { phi.hasInputFromBlock(_, _, _, _, input) } or
|
||||||
TSsaPhiNode(Ssa::PhiNode phi) or
|
TSsaPhiNode(Ssa::PhiNode phi) or
|
||||||
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
|
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
|
||||||
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
|
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
|
||||||
@@ -114,6 +115,13 @@ predicate conversionFlow(
|
|||||||
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
|
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
|
||||||
or
|
or
|
||||||
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
|
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
|
||||||
|
or
|
||||||
|
exists(BuiltInInstruction builtIn |
|
||||||
|
builtIn = instrTo and
|
||||||
|
// __builtin_bit_cast
|
||||||
|
builtIn.getBuiltInOperation() instanceof BuiltInBitCast and
|
||||||
|
opFrom = builtIn.getAnOperand()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
additional = true and
|
additional = true and
|
||||||
@@ -158,6 +166,12 @@ class Node extends TIRDataFlowNode {
|
|||||||
/** Gets the operands corresponding to this node, if any. */
|
/** Gets the operands corresponding to this node, if any. */
|
||||||
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operand that is indirectly tracked by this node behind `index`
|
||||||
|
* number of indirections.
|
||||||
|
*/
|
||||||
|
Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this node is at index `i` in basic block `block`.
|
* Holds if this node is at index `i` in basic block `block`.
|
||||||
*
|
*
|
||||||
@@ -170,6 +184,9 @@ class Node extends TIRDataFlowNode {
|
|||||||
or
|
or
|
||||||
this.(SsaPhiNode).getPhiNode().getBasicBlock() = block and i = -1
|
this.(SsaPhiNode).getPhiNode().getBasicBlock() = block and i = -1
|
||||||
or
|
or
|
||||||
|
this.(SsaPhiInputNode).getBlock() = block and
|
||||||
|
i = block.getInstructionCount()
|
||||||
|
or
|
||||||
this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i)
|
this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i)
|
||||||
or
|
or
|
||||||
this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i)
|
this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i)
|
||||||
@@ -622,7 +639,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
|||||||
|
|
||||||
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
|
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
|
||||||
|
|
||||||
override string toStringImpl() { result = "Phi" }
|
override string toStringImpl() { result = phi.toString() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node that is used as input to this phi node.
|
* Gets a node that is used as input to this phi node.
|
||||||
@@ -631,7 +648,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
final Node getAnInput(boolean fromBackEdge) {
|
final Node getAnInput(boolean fromBackEdge) {
|
||||||
localFlowStep(result, this) and
|
result.(SsaPhiInputNode).getPhiNode() = phi and
|
||||||
exists(IRBlock bPhi, IRBlock bResult |
|
exists(IRBlock bPhi, IRBlock bResult |
|
||||||
bPhi = phi.getBasicBlock() and bResult = result.getBasicBlock()
|
bPhi = phi.getBasicBlock() and bResult = result.getBasicBlock()
|
||||||
|
|
|
|
||||||
@@ -654,6 +671,58 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
|||||||
predicate isPhiRead() { phi.isPhiRead() }
|
predicate isPhiRead() { phi.isPhiRead() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL: Do not use.
|
||||||
|
*
|
||||||
|
* A node that is used as an input to a phi node.
|
||||||
|
*
|
||||||
|
* This class exists to allow more powerful barrier guards. Consider this
|
||||||
|
* example:
|
||||||
|
*
|
||||||
|
* ```cpp
|
||||||
|
* int x = source();
|
||||||
|
* if(!safe(x)) {
|
||||||
|
* x = clear();
|
||||||
|
* }
|
||||||
|
* // phi node for x here
|
||||||
|
* sink(x);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* At the phi node for `x` it is neither the case that `x` is dominated by
|
||||||
|
* `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
|
||||||
|
*
|
||||||
|
* By inserting a "phi input" node as the last entry in the basic block that
|
||||||
|
* defines the inputs to the phi we can conclude that each of those inputs are
|
||||||
|
* safe to pass to `sink`.
|
||||||
|
*/
|
||||||
|
class SsaPhiInputNode extends Node, TSsaPhiInputNode {
|
||||||
|
Ssa::PhiNode phi;
|
||||||
|
IRBlock block;
|
||||||
|
|
||||||
|
SsaPhiInputNode() { this = TSsaPhiInputNode(phi, block) }
|
||||||
|
|
||||||
|
/** Gets the phi node associated with this node. */
|
||||||
|
Ssa::PhiNode getPhiNode() { result = phi }
|
||||||
|
|
||||||
|
/** Gets the basic block in which this input originates. */
|
||||||
|
IRBlock getBlock() { result = block }
|
||||||
|
|
||||||
|
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||||
|
|
||||||
|
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||||
|
|
||||||
|
override DataFlowType getType() { result = this.getSourceVariable().getType() }
|
||||||
|
|
||||||
|
override predicate isGLValue() { phi.getSourceVariable().isGLValue() }
|
||||||
|
|
||||||
|
final override Location getLocationImpl() { result = block.getLastInstruction().getLocation() }
|
||||||
|
|
||||||
|
override string toStringImpl() { result = "Phi input" }
|
||||||
|
|
||||||
|
/** Gets the source variable underlying this phi node. */
|
||||||
|
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL: do not use.
|
* INTERNAL: do not use.
|
||||||
*
|
*
|
||||||
@@ -2176,6 +2245,9 @@ private module Cached {
|
|||||||
// Def-use/Use-use flow
|
// Def-use/Use-use flow
|
||||||
Ssa::ssaFlow(nodeFrom, nodeTo)
|
Ssa::ssaFlow(nodeFrom, nodeTo)
|
||||||
or
|
or
|
||||||
|
// Phi input -> Phi
|
||||||
|
nodeFrom.(SsaPhiInputNode).getPhiNode() = nodeTo.(SsaPhiNode).getPhiNode()
|
||||||
|
or
|
||||||
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
|
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
|
||||||
or
|
or
|
||||||
// Operand -> Instruction flow
|
// Operand -> Instruction flow
|
||||||
@@ -2614,6 +2686,22 @@ class ContentSet instanceof Content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate guardControlsPhiInput(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::Definition def, IRBlock input, Ssa::PhiNode phi
|
||||||
|
) {
|
||||||
|
phi.hasInputFromBlock(def, _, _, _, input) and
|
||||||
|
(
|
||||||
|
g.controls(input, branch)
|
||||||
|
or
|
||||||
|
exists(EdgeKind kind |
|
||||||
|
g.getBlock() = input and
|
||||||
|
kind = getConditionalEdge(branch) and
|
||||||
|
input.getSuccessor(kind) = phi.getBasicBlock()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||||
*
|
*
|
||||||
@@ -2662,13 +2750,21 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
ExprNode getABarrierNode() {
|
Node getABarrierNode() {
|
||||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||||
result.getConvertedExpr() = e and
|
result.asConvertedExpr() = e and
|
||||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||||
g.controls(result.getBasicBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||||
|
|
|
||||||
|
guardChecks(g, def.getARead().asOperand().getDef().getConvertedResultExpression(), branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi, input)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2704,7 +2800,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
||||||
@@ -2740,13 +2836,23 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
|
Node getAnIndirectBarrierNode(int indirectionIndex) {
|
||||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||||
result.getConvertedExpr(indirectionIndex) = e and
|
result.asIndirectConvertedExpr(indirectionIndex) = e and
|
||||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||||
g.controls(result.getBasicBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||||
|
|
|
||||||
|
guardChecks(g,
|
||||||
|
def.getARead().asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
|
||||||
|
branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi, input)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2755,6 +2861,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*/
|
*/
|
||||||
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
||||||
|
|
||||||
|
private EdgeKind getConditionalEdge(boolean branch) {
|
||||||
|
branch = true and
|
||||||
|
result instanceof TrueEdge
|
||||||
|
or
|
||||||
|
branch = false and
|
||||||
|
result instanceof FalseEdge
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a set of barrier nodes for a guard that validates an instruction.
|
* Provides a set of barrier nodes for a guard that validates an instruction.
|
||||||
*
|
*
|
||||||
@@ -2763,12 +2877,20 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
|
|||||||
*/
|
*/
|
||||||
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
||||||
/** Gets a node that is safely guarded by the given guard check. */
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
ExprNode getABarrierNode() {
|
Node getABarrierNode() {
|
||||||
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
|
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
|
||||||
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
||||||
use = value.getAnInstruction().getAUse() and
|
use = value.getAnInstruction().getAUse() and
|
||||||
result.asOperand() = use and
|
result.asOperand() = use and
|
||||||
g.controls(use.getDef().getBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||||
|
|
|
||||||
|
instructionGuardChecks(g, def.getARead().asOperand().getDef(), branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi, input)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -657,19 +657,9 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
|
|||||||
*/
|
*/
|
||||||
predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
|
predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
|
||||||
adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
|
adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
|
||||||
or
|
|
||||||
exists(PhiNode phi |
|
|
||||||
lastRefRedefExt(_, sv, bb1, i1, phi) and
|
|
||||||
phi.definesAt(sv, bb2, i2, _)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
|
predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
|
||||||
exists(Phi phi |
|
|
||||||
phi.asPhi().definesAt(sv, bb, i, _) and
|
|
||||||
nodeTo = phi.getNode()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(UseImpl use |
|
exists(UseImpl use |
|
||||||
use.hasIndexInBlock(bb, i, sv) and
|
use.hasIndexInBlock(bb, i, sv) and
|
||||||
nodeTo = use.getNode()
|
nodeTo = use.getNode()
|
||||||
@@ -723,46 +713,26 @@ predicate nodeToDefOrUse(Node node, SourceVariable sv, IRBlock bb, int i, boolea
|
|||||||
*/
|
*/
|
||||||
private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
|
private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
|
||||||
not exists(SourceVariable sv, IRBlock bb2, int i2 |
|
not exists(SourceVariable sv, IRBlock bb2, int i2 |
|
||||||
nodeToDefOrUse(nTo, sv, bb2, i2, _) and
|
useToNode(bb2, i2, sv, nTo) and
|
||||||
adjacentDefRead(bb2, i2, sv, _, _)
|
adjacentDefRead(bb2, i2, sv, _, _)
|
||||||
) and
|
) and
|
||||||
(
|
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
||||||
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
||||||
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
|
||||||
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
|
instr = op2.getDef() and
|
||||||
instr = op2.getDef() and
|
conversionFlow(op1, instr, _, _)
|
||||||
conversionFlow(op1, instr, _, _)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
|
||||||
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
|
||||||
hasOperandAndIndex(nTo, op2, indirectionIndex - 1) and
|
|
||||||
instr = op2.getDef() and
|
|
||||||
isDereference(instr, op1, _)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reason for this predicate is a bit annoying:
|
* Holds if `node` is a phi input node that should receive flow from the
|
||||||
* We cannot mark a `PointerArithmeticInstruction` that computes an offset based on some SSA
|
* definition to (or use of) `sv` at `(bb1, i1)`.
|
||||||
* variable `x` as a use of `x` since this creates taint-flow in the following example:
|
|
||||||
* ```c
|
|
||||||
* int x = array[source]
|
|
||||||
* sink(*array)
|
|
||||||
* ```
|
|
||||||
* This is because `source` would flow from the operand of `PointerArithmeticInstruction` to the
|
|
||||||
* result of the instruction, and into the `IndirectOperand` that represents the value of `*array`.
|
|
||||||
* Then, via use-use flow, flow will arrive at `*array` in `sink(*array)`.
|
|
||||||
*
|
|
||||||
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
|
|
||||||
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
|
|
||||||
*/
|
*/
|
||||||
private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, IRBlock bb2, int i2) {
|
private predicate phiToNode(SsaPhiInputNode node, SourceVariable sv, IRBlock bb1, int i1) {
|
||||||
exists(IRBlock bb1, int i1, Node adjusted |
|
exists(PhiNode phi, IRBlock input |
|
||||||
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
|
phi.hasInputFromBlock(_, sv, bb1, i1, input) and
|
||||||
nodeToDefOrUse(adjusted, sv, bb1, i1, _) and
|
node.getPhiNode() = phi and
|
||||||
adjacentDefRead(bb1, i1, sv, bb2, i2)
|
node.getBlock() = input
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,10 +747,14 @@ private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, I
|
|||||||
private predicate ssaFlowImpl(
|
private predicate ssaFlowImpl(
|
||||||
IRBlock bb1, int i1, SourceVariable sv, Node nodeFrom, Node nodeTo, boolean uncertain
|
IRBlock bb1, int i1, SourceVariable sv, Node nodeFrom, Node nodeTo, boolean uncertain
|
||||||
) {
|
) {
|
||||||
exists(IRBlock bb2, int i2 |
|
nodeToDefOrUse(nodeFrom, sv, bb1, i1, uncertain) and
|
||||||
nodeToDefOrUse(nodeFrom, sv, bb1, i1, uncertain) and
|
(
|
||||||
adjacentDefRead(bb1, i1, sv, bb2, i2) and
|
exists(IRBlock bb2, int i2 |
|
||||||
useToNode(bb2, i2, sv, nodeTo)
|
adjacentDefRead(bb1, i1, sv, bb2, i2) and
|
||||||
|
useToNode(bb2, i2, sv, nodeTo)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
phiToNode(nodeTo, sv, bb1, i1)
|
||||||
) and
|
) and
|
||||||
nodeFrom != nodeTo
|
nodeFrom != nodeTo
|
||||||
}
|
}
|
||||||
@@ -789,7 +763,7 @@ private predicate ssaFlowImpl(
|
|||||||
private Node getAPriorDefinition(DefinitionExt next) {
|
private Node getAPriorDefinition(DefinitionExt next) {
|
||||||
exists(IRBlock bb, int i, SourceVariable sv |
|
exists(IRBlock bb, int i, SourceVariable sv |
|
||||||
lastRefRedefExt(_, pragma[only_bind_into](sv), pragma[only_bind_into](bb),
|
lastRefRedefExt(_, pragma[only_bind_into](sv), pragma[only_bind_into](bb),
|
||||||
pragma[only_bind_into](i), next) and
|
pragma[only_bind_into](i), _, next) and
|
||||||
nodeToDefOrUse(result, sv, bb, i, _)
|
nodeToDefOrUse(result, sv, bb, i, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -896,9 +870,31 @@ private predicate isArgumentOfCallable(DataFlowCall call, Node n) {
|
|||||||
* Holds if there is use-use flow from `pun`'s pre-update node to `n`.
|
* Holds if there is use-use flow from `pun`'s pre-update node to `n`.
|
||||||
*/
|
*/
|
||||||
private predicate postUpdateNodeToFirstUse(PostUpdateNode pun, Node n) {
|
private predicate postUpdateNodeToFirstUse(PostUpdateNode pun, Node n) {
|
||||||
exists(SourceVariable sv, IRBlock bb2, int i2 |
|
// We cannot mark a `PointerArithmeticInstruction` that computes an offset
|
||||||
adjustForPointerArith(pun, sv, bb2, i2) and
|
// based on some SSA
|
||||||
useToNode(bb2, i2, sv, n)
|
// variable `x` as a use of `x` since this creates taint-flow in the
|
||||||
|
// following example:
|
||||||
|
// ```c
|
||||||
|
// int x = array[source]
|
||||||
|
// sink(*array)
|
||||||
|
// ```
|
||||||
|
// This is because `source` would flow from the operand of `PointerArithmetic`
|
||||||
|
// instruction to the result of the instruction, and into the `IndirectOperand`
|
||||||
|
// that represents the value of `*array`. Then, via use-use flow, flow will
|
||||||
|
// arrive at `*array` in `sink(*array)`.
|
||||||
|
// So this predicate recurses back along conversions and `PointerArithmetic`
|
||||||
|
// instructions to find the first use that has provides use-use flow, and
|
||||||
|
// uses that target as the target of the `nodeFrom`.
|
||||||
|
exists(Node adjusted, IRBlock bb1, int i1, SourceVariable sv |
|
||||||
|
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
|
||||||
|
useToNode(bb1, i1, sv, adjusted)
|
||||||
|
|
|
||||||
|
exists(IRBlock bb2, int i2 |
|
||||||
|
adjacentDefRead(bb1, i1, sv, bb2, i2) and
|
||||||
|
useToNode(bb2, i2, sv, n)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
phiToNode(n, sv, bb1, i1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -953,11 +949,16 @@ predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
|
|||||||
|
|
||||||
/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
|
/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
|
||||||
predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
|
predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
|
||||||
exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2 |
|
exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1 |
|
||||||
phi = nodeFrom.getPhiNode() and
|
phi = nodeFrom.getPhiNode() and
|
||||||
phi.definesAt(sv, bb1, i1, _) and
|
phi.definesAt(sv, bb1, i1, _)
|
||||||
adjacentDefRead(bb1, i1, sv, bb2, i2) and
|
|
|
||||||
useToNode(bb2, i2, sv, nodeTo)
|
exists(IRBlock bb2, int i2 |
|
||||||
|
adjacentDefRead(bb1, i1, sv, bb2, i2) and
|
||||||
|
useToNode(bb2, i2, sv, nodeTo)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
phiToNode(nodeTo, sv, bb1, i1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,22 +1032,26 @@ module SsaCached {
|
|||||||
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
|
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
|
||||||
* `def`. The reference is last because it can reach another write `next`,
|
* `def`. The reference is last because it can reach another write `next`,
|
||||||
* without passing through another read or write.
|
* without passing through another read or write.
|
||||||
|
*
|
||||||
|
* The path from node `i` in `bb` to `next` goes via basic block `input`,
|
||||||
|
* which is either a predecessor of the basic block of `next`, or `input` =
|
||||||
|
* `bb` in case `next` occurs in basic block `bb`.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate lastRefRedefExt(
|
predicate lastRefRedefExt(
|
||||||
DefinitionExt def, SourceVariable sv, IRBlock bb, int i, DefinitionExt next
|
DefinitionExt def, SourceVariable sv, IRBlock bb, int i, IRBlock input, DefinitionExt next
|
||||||
) {
|
) {
|
||||||
SsaImpl::lastRefRedefExt(def, sv, bb, i, next)
|
SsaImpl::lastRefRedefExt(def, sv, bb, i, input, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
Definition phiHasInputFromBlock(PhiNode phi, IRBlock bb) {
|
Definition phiHasInputFromBlockExt(PhiNode phi, IRBlock bb) {
|
||||||
SsaImpl::phiHasInputFromBlock(phi, result, bb)
|
SsaImpl::phiHasInputFromBlockExt(phi, result, bb)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate ssaDefReachesRead(SourceVariable v, Definition def, IRBlock bb, int i) {
|
predicate ssaDefReachesReadExt(SourceVariable v, DefinitionExt def, IRBlock bb, int i) {
|
||||||
SsaImpl::ssaDefReachesRead(v, def, bb, i)
|
SsaImpl::ssaDefReachesReadExt(v, def, bb, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate variableRead = SsaInput::variableRead/4;
|
predicate variableRead = SsaInput::variableRead/4;
|
||||||
@@ -1198,11 +1203,11 @@ class Phi extends TPhi, SsaDef {
|
|||||||
|
|
||||||
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
|
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
|
||||||
|
|
||||||
override string toString() { result = "Phi" }
|
override string toString() { result = phi.toString() }
|
||||||
|
|
||||||
SsaPhiNode getNode() { result.getPhiNode() = phi }
|
SsaPhiInputNode getNode(IRBlock block) { result.getPhiNode() = phi and result.getBlock() = block }
|
||||||
|
|
||||||
predicate hasInputFromBlock(Definition inp, IRBlock bb) { inp = phiHasInputFromBlock(phi, bb) }
|
predicate hasInputFromBlock(Definition inp, IRBlock bb) { inp = phiHasInputFromBlockExt(phi, bb) }
|
||||||
|
|
||||||
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
|
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
|
||||||
}
|
}
|
||||||
@@ -1228,13 +1233,21 @@ class PhiNode extends SsaImpl::DefinitionExt {
|
|||||||
*/
|
*/
|
||||||
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
|
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
|
||||||
|
|
||||||
/** Holds if `inp` is an input to this phi node along the edge originating in `bb`. */
|
/**
|
||||||
predicate hasInputFromBlock(Definition inp, IRBlock bb) {
|
* Holds if the node at index `i` in `bb` is a last reference to SSA
|
||||||
inp = SsaCached::phiHasInputFromBlock(this, bb)
|
* definition `def` of `sv`. The reference is last because it can reach
|
||||||
|
* this phi node, without passing through another read or write.
|
||||||
|
*
|
||||||
|
* The path from node `i` in `bb` to this phi node goes via basic block
|
||||||
|
* `input`, which is either a predecessor of the basic block of this phi
|
||||||
|
* node, or `input` = `bb` in case this phi node occurs in basic block `bb`.
|
||||||
|
*/
|
||||||
|
predicate hasInputFromBlock(DefinitionExt def, SourceVariable sv, IRBlock bb, int i, IRBlock input) {
|
||||||
|
SsaCached::lastRefRedefExt(def, sv, bb, i, input, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a definition that is an input to this phi node. */
|
/** Gets a definition that is an input to this phi node. */
|
||||||
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
|
final Definition getAnInput() { this.hasInputFromBlock(result, _, _, _, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An static single assignment (SSA) definition. */
|
/** An static single assignment (SSA) definition. */
|
||||||
@@ -1249,6 +1262,15 @@ class DefinitionExt extends SsaImpl::DefinitionExt {
|
|||||||
result = this.getAPhiInputOrPriorDefinition*() and
|
result = this.getAPhiInputOrPriorDefinition*() and
|
||||||
not result instanceof PhiNode
|
not result instanceof PhiNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets a node that represents a read of this SSA definition. */
|
||||||
|
Node getARead() {
|
||||||
|
exists(SourceVariable sv, IRBlock bb, int i | SsaCached::ssaDefReachesReadExt(sv, this, bb, i) |
|
||||||
|
useToNode(bb, i, sv, result)
|
||||||
|
or
|
||||||
|
phiToNode(result, sv, bb, i)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Definition = SsaImpl::Definition;
|
class Definition = SsaImpl::Definition;
|
||||||
|
|||||||
@@ -3208,9 +3208,20 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
|
|||||||
|
|
||||||
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
|
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rnk'th (0-indexed) child for which a `TranslatedElement` exists.
|
||||||
|
*
|
||||||
|
* We use this predicate to filter out `TypeName` expressions that sometimes
|
||||||
|
* occur in builtin operations since the IR doesn't have an instruction to
|
||||||
|
* represent a reference to a type.
|
||||||
|
*/
|
||||||
|
private TranslatedElement getRankedChild(int rnk) {
|
||||||
|
result = rank[rnk + 1](int id, TranslatedElement te | te = this.getChild(id) | te order by id)
|
||||||
|
}
|
||||||
|
|
||||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||||
if exists(this.getChild(0))
|
if exists(this.getRankedChild(0))
|
||||||
then result = this.getChild(0).getFirstInstruction(kind)
|
then result = this.getRankedChild(0).getFirstInstruction(kind)
|
||||||
else (
|
else (
|
||||||
kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
|
kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
|
||||||
)
|
)
|
||||||
@@ -3230,11 +3241,11 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||||
exists(int id | child = this.getChild(id) |
|
exists(int id | child = this.getRankedChild(id) |
|
||||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
result = this.getRankedChild(id + 1).getFirstInstruction(kind)
|
||||||
or
|
or
|
||||||
kind instanceof GotoEdge and
|
kind instanceof GotoEdge and
|
||||||
not exists(this.getChild(id + 1)) and
|
not exists(this.getRankedChild(id + 1)) and
|
||||||
result = this.getInstruction(OnlyInstructionTag())
|
result = this.getInstruction(OnlyInstructionTag())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3249,7 +3260,7 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
|
|||||||
tag = OnlyInstructionTag() and
|
tag = OnlyInstructionTag() and
|
||||||
exists(int index |
|
exists(int index |
|
||||||
operandTag = positionalArgumentOperand(index) and
|
operandTag = positionalArgumentOperand(index) and
|
||||||
result = this.getChild(index).(TranslatedExpr).getResult()
|
result = this.getRankedChild(index).(TranslatedExpr).getResult()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* The `cpp/dangerous-function-overflow` no longer produces a false positive alert when the `gets` function does not have exactly one parameter.
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ class LoopWithAlloca extends Stmt {
|
|||||||
DataFlow::localFlow(result, DataFlow::exprNode(va)) and
|
DataFlow::localFlow(result, DataFlow::exprNode(va)) and
|
||||||
// Phi nodes will be preceded by nodes that represent actual definitions
|
// Phi nodes will be preceded by nodes that represent actual definitions
|
||||||
not result instanceof DataFlow::SsaPhiNode and
|
not result instanceof DataFlow::SsaPhiNode and
|
||||||
|
not result instanceof DataFlow::SsaPhiInputNode and
|
||||||
// A source is outside the loop if it's not inside the loop
|
// A source is outside the loop if it's not inside the loop
|
||||||
not exists(Expr e | e = getExpr(result) | this = getAnEnclosingLoopOfExpr(e))
|
not exists(Expr e | e = getExpr(result) | this = getAnEnclosingLoopOfExpr(e))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ import cpp
|
|||||||
from FunctionCall call, Function target
|
from FunctionCall call, Function target
|
||||||
where
|
where
|
||||||
call.getTarget() = target and
|
call.getTarget() = target and
|
||||||
target.hasGlobalOrStdName("gets")
|
target.hasGlobalOrStdName("gets") and
|
||||||
|
target.getNumberOfParameters() = 1
|
||||||
select call, "'gets' does not guard against buffer overflow."
|
select call, "'gets' does not guard against buffer overflow."
|
||||||
|
|||||||
5
cpp/ql/src/change-notes/released/1.0.1.md
Normal file
5
cpp/ql/src/change-notes/released/1.0.1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* The `cpp/dangerous-function-overflow` no longer produces a false positive alert when the `gets` function does not have exactly one parameter.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 1.0.0
|
lastReleaseVersion: 1.0.1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-queries
|
name: codeql/cpp-queries
|
||||||
version: 1.0.0
|
version: 1.0.1
|
||||||
groups:
|
groups:
|
||||||
- cpp
|
- cpp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ astGuardsCompare
|
|||||||
| 34 | j >= 10+0 when ... < ... is false |
|
| 34 | j >= 10+0 when ... < ... is false |
|
||||||
| 42 | 10 < j+1 when ... < ... is false |
|
| 42 | 10 < j+1 when ... < ... is false |
|
||||||
| 42 | 10 >= j+1 when ... < ... is true |
|
| 42 | 10 >= j+1 when ... < ... is true |
|
||||||
|
| 42 | call to getABool != 0 when call to getABool is true |
|
||||||
|
| 42 | call to getABool == 0 when call to getABool is false |
|
||||||
| 42 | j < 10+0 when ... < ... is true |
|
| 42 | j < 10+0 when ... < ... is true |
|
||||||
| 42 | j >= 10+0 when ... < ... is false |
|
| 42 | j >= 10+0 when ... < ... is false |
|
||||||
| 44 | 0 < z+0 when ... > ... is true |
|
| 44 | 0 < z+0 when ... > ... is true |
|
||||||
@@ -537,6 +539,8 @@ astGuardsEnsure_const
|
|||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
|
||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
|
||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
|
||||||
|
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | != | 0 | 43 | 45 |
|
||||||
|
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | == | 0 | 53 | 53 |
|
||||||
irGuards
|
irGuards
|
||||||
| test.c:7:9:7:13 | CompareGT: ... > ... |
|
| test.c:7:9:7:13 | CompareGT: ... > ... |
|
||||||
| test.c:17:8:17:12 | CompareLT: ... < ... |
|
| test.c:17:8:17:12 | CompareLT: ... < ... |
|
||||||
@@ -613,6 +617,8 @@ irGuardsCompare
|
|||||||
| 34 | j >= 10+0 when CompareLT: ... < ... is false |
|
| 34 | j >= 10+0 when CompareLT: ... < ... is false |
|
||||||
| 42 | 10 < j+1 when CompareLT: ... < ... is false |
|
| 42 | 10 < j+1 when CompareLT: ... < ... is false |
|
||||||
| 42 | 10 >= j+1 when CompareLT: ... < ... is true |
|
| 42 | 10 >= j+1 when CompareLT: ... < ... is true |
|
||||||
|
| 42 | call to getABool != 0 when Call: call to getABool is true |
|
||||||
|
| 42 | call to getABool == 0 when Call: call to getABool is false |
|
||||||
| 42 | j < 10 when CompareLT: ... < ... is true |
|
| 42 | j < 10 when CompareLT: ... < ... is true |
|
||||||
| 42 | j < 10+0 when CompareLT: ... < ... is true |
|
| 42 | j < 10+0 when CompareLT: ... < ... is true |
|
||||||
| 42 | j >= 10 when CompareLT: ... < ... is false |
|
| 42 | j >= 10 when CompareLT: ... < ... is false |
|
||||||
@@ -1081,3 +1087,5 @@ irGuardsEnsure_const
|
|||||||
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 |
|
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 |
|
||||||
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 |
|
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 |
|
||||||
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 32 | 32 |
|
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 32 | 32 |
|
||||||
|
| test.cpp:42:13:42:20 | Call: call to getABool | test.cpp:42:13:42:20 | Call: call to getABool | != | 0 | 44 | 44 |
|
||||||
|
| test.cpp:42:13:42:20 | Call: call to getABool | test.cpp:42:13:42:20 | Call: call to getABool | == | 0 | 53 | 53 |
|
||||||
|
|||||||
@@ -42,3 +42,6 @@
|
|||||||
| test.cpp:99:6:99:6 | f |
|
| test.cpp:99:6:99:6 | f |
|
||||||
| test.cpp:105:6:105:14 | ... != ... |
|
| test.cpp:105:6:105:14 | ... != ... |
|
||||||
| test.cpp:111:6:111:14 | ... != ... |
|
| test.cpp:111:6:111:14 | ... != ... |
|
||||||
|
| test.cpp:122:9:122:9 | b |
|
||||||
|
| test.cpp:125:13:125:20 | ! ... |
|
||||||
|
| test.cpp:125:14:125:17 | call to safe |
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
| 34 | j >= 10+0 when ... < ... is false |
|
| 34 | j >= 10+0 when ... < ... is false |
|
||||||
| 42 | 10 < j+1 when ... < ... is false |
|
| 42 | 10 < j+1 when ... < ... is false |
|
||||||
| 42 | 10 >= j+1 when ... < ... is true |
|
| 42 | 10 >= j+1 when ... < ... is true |
|
||||||
|
| 42 | call to getABool != 0 when call to getABool is true |
|
||||||
|
| 42 | call to getABool == 0 when call to getABool is false |
|
||||||
| 42 | j < 10 when ... < ... is true |
|
| 42 | j < 10 when ... < ... is true |
|
||||||
| 42 | j < 10+0 when ... < ... is true |
|
| 42 | j < 10+0 when ... < ... is true |
|
||||||
| 42 | j >= 10 when ... < ... is false |
|
| 42 | j >= 10 when ... < ... is false |
|
||||||
@@ -149,6 +151,13 @@
|
|||||||
| 111 | 0.0 == i+0 when ... != ... is false |
|
| 111 | 0.0 == i+0 when ... != ... is false |
|
||||||
| 111 | i != 0.0+0 when ... != ... is true |
|
| 111 | i != 0.0+0 when ... != ... is true |
|
||||||
| 111 | i == 0.0+0 when ... != ... is false |
|
| 111 | i == 0.0+0 when ... != ... is false |
|
||||||
|
| 122 | b != 0 when b is true |
|
||||||
|
| 122 | b == 0 when b is false |
|
||||||
|
| 125 | ! ... != 0 when ! ... is true |
|
||||||
|
| 125 | ! ... == 0 when ! ... is false |
|
||||||
|
| 125 | call to safe != 0 when ! ... is false |
|
||||||
|
| 125 | call to safe != 0 when call to safe is true |
|
||||||
|
| 125 | call to safe == 0 when call to safe is false |
|
||||||
| 126 | 1 != 0 when 1 is true |
|
| 126 | 1 != 0 when 1 is true |
|
||||||
| 126 | 1 != 0 when ... && ... is true |
|
| 126 | 1 != 0 when ... && ... is true |
|
||||||
| 126 | 1 == 0 when 1 is false |
|
| 126 | 1 == 0 when 1 is false |
|
||||||
|
|||||||
@@ -100,3 +100,7 @@
|
|||||||
| test.cpp:99:6:99:6 | f | true | 99 | 100 |
|
| test.cpp:99:6:99:6 | f | true | 99 | 100 |
|
||||||
| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 |
|
| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 |
|
||||||
| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 |
|
| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 |
|
||||||
|
| test.cpp:122:9:122:9 | b | true | 123 | 125 |
|
||||||
|
| test.cpp:122:9:122:9 | b | true | 125 | 125 |
|
||||||
|
| test.cpp:125:13:125:20 | ! ... | true | 125 | 125 |
|
||||||
|
| test.cpp:125:14:125:17 | call to safe | false | 125 | 125 |
|
||||||
|
|||||||
@@ -257,6 +257,8 @@ unary
|
|||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
|
||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
|
||||||
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
|
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
|
||||||
|
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | != | 0 | 43 | 45 |
|
||||||
|
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | == | 0 | 53 | 53 |
|
||||||
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 0 | 62 | 64 |
|
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 0 | 62 | 64 |
|
||||||
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 1 | 65 | 66 |
|
| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 1 | 65 | 66 |
|
||||||
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 11 | 75 | 77 |
|
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 11 | 75 | 77 |
|
||||||
@@ -264,3 +266,7 @@ unary
|
|||||||
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 0 | 75 | 77 |
|
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 0 | 75 | 77 |
|
||||||
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 11 | 78 | 79 |
|
| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 11 | 78 | 79 |
|
||||||
| test.cpp:93:6:93:6 | c | test.cpp:93:6:93:6 | c | != | 0 | 93 | 94 |
|
| test.cpp:93:6:93:6 | c | test.cpp:93:6:93:6 | c | != | 0 | 93 | 94 |
|
||||||
|
| test.cpp:122:9:122:9 | b | test.cpp:122:9:122:9 | b | != | 0 | 123 | 125 |
|
||||||
|
| test.cpp:122:9:122:9 | b | test.cpp:122:9:122:9 | b | != | 0 | 125 | 125 |
|
||||||
|
| test.cpp:125:13:125:20 | ! ... | test.cpp:125:13:125:20 | ! ... | != | 0 | 125 | 125 |
|
||||||
|
| test.cpp:125:14:125:17 | call to safe | test.cpp:125:14:125:17 | call to safe | == | 0 | 125 | 125 |
|
||||||
|
|||||||
@@ -112,3 +112,17 @@ void int_float_comparison(int i) {
|
|||||||
use(i);
|
use(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int source();
|
||||||
|
bool safe(int);
|
||||||
|
|
||||||
|
void test(bool b)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
x = source();
|
||||||
|
if (!safe(x)) return;
|
||||||
|
}
|
||||||
|
use(x);
|
||||||
|
}
|
||||||
@@ -75,4 +75,54 @@ void bg_indirect_expr() {
|
|||||||
if (guarded(buf)) {
|
if (guarded(buf)) {
|
||||||
sink(buf);
|
sink(buf);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_guard_and_reassign() {
|
||||||
|
int x = source();
|
||||||
|
|
||||||
|
if(!guarded(x)) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
sink(x); // $ SPURIOUS: ast
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_phi_read_guard(bool b) {
|
||||||
|
int x = source();
|
||||||
|
|
||||||
|
if(b) {
|
||||||
|
if(!guarded(x))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(!guarded(x))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sink(x); // $ SPURIOUS: ast
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unsafe(int);
|
||||||
|
|
||||||
|
void test_guard_and_reassign_2() {
|
||||||
|
int x = source();
|
||||||
|
|
||||||
|
if(unsafe(x)) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
sink(x); // $ SPURIOUS: ast
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_phi_read_guard_2(bool b) {
|
||||||
|
int x = source();
|
||||||
|
|
||||||
|
if(b) {
|
||||||
|
if(unsafe(x))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(unsafe(x))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sink(x); // $ SPURIOUS: ast
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,17 @@ module AstTest {
|
|||||||
* S in `if (guarded(x)) S`.
|
* S in `if (guarded(x)) S`.
|
||||||
*/
|
*/
|
||||||
// This is tested in `BarrierGuard.cpp`.
|
// This is tested in `BarrierGuard.cpp`.
|
||||||
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
|
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean branch) {
|
||||||
g.(FunctionCall).getTarget().getName() = "guarded" and
|
exists(Call call, boolean b |
|
||||||
checked = g.(FunctionCall).getArgument(0) and
|
checked = call.getArgument(0) and
|
||||||
isTrue = true
|
g.comparesEq(call, 0, b, any(BooleanValue bv | bv.getValue() = branch))
|
||||||
|
|
|
||||||
|
call.getTarget().hasName("guarded") and
|
||||||
|
b = false
|
||||||
|
or
|
||||||
|
call.getTarget().hasName("unsafe") and
|
||||||
|
b = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Common data flow configuration to be used by tests. */
|
/** Common data flow configuration to be used by tests. */
|
||||||
@@ -102,12 +109,16 @@ module IRTest {
|
|||||||
* S in `if (guarded(x)) S`.
|
* S in `if (guarded(x)) S`.
|
||||||
*/
|
*/
|
||||||
// This is tested in `BarrierGuard.cpp`.
|
// This is tested in `BarrierGuard.cpp`.
|
||||||
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
|
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean branch) {
|
||||||
exists(Call call |
|
exists(CallInstruction call, boolean b |
|
||||||
call = g.getUnconvertedResultExpression() and
|
checked = call.getArgument(0).getUnconvertedResultExpression() and
|
||||||
call.getTarget().hasName("guarded") and
|
g.comparesEq(call.getAUse(), 0, b, any(BooleanValue bv | bv.getValue() = branch))
|
||||||
checked = call.getArgument(0) and
|
|
|
||||||
isTrue = true
|
call.getStaticCallTarget().hasName("guarded") and
|
||||||
|
b = false
|
||||||
|
or
|
||||||
|
call.getStaticCallTarget().hasName("unsafe") and
|
||||||
|
b = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,3 +52,9 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr ir-def=*cleanArray1 ir-d
|
|||||||
sink(stackArray); // $ ast,ir
|
sink(stackArray); // $ ast,ir
|
||||||
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
|
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_bitcast() {
|
||||||
|
unsigned long x = source();
|
||||||
|
double d = __builtin_bit_cast(double, x);
|
||||||
|
sink(d); // $ ir MISSING: ast
|
||||||
|
}
|
||||||
@@ -69,45 +69,61 @@
|
|||||||
| test.cpp:8:8:8:9 | t1 | test.cpp:9:8:9:9 | t1 |
|
| test.cpp:8:8:8:9 | t1 | test.cpp:9:8:9:9 | t1 |
|
||||||
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
|
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
|
||||||
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
|
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
|
||||||
|
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | Phi input |
|
||||||
|
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | Phi input |
|
||||||
| test.cpp:10:8:10:9 | t2 | test.cpp:13:10:13:11 | t2 |
|
| test.cpp:10:8:10:9 | t2 | test.cpp:13:10:13:11 | t2 |
|
||||||
| test.cpp:10:8:10:9 | t2 | test.cpp:15:3:15:6 | Phi |
|
| test.cpp:11:7:11:8 | Phi input | test.cpp:15:3:15:6 | SSA phi read(t2) |
|
||||||
| test.cpp:10:8:10:9 | t2 | test.cpp:15:3:15:6 | Phi |
|
| test.cpp:11:7:11:8 | Phi input | test.cpp:15:3:15:6 | SSA phi(*t2) |
|
||||||
| test.cpp:11:7:11:8 | t1 | test.cpp:21:8:21:9 | t1 |
|
| test.cpp:11:7:11:8 | t1 | test.cpp:21:8:21:9 | t1 |
|
||||||
| test.cpp:12:5:12:10 | ... = ... | test.cpp:13:10:13:11 | t2 |
|
| test.cpp:12:5:12:10 | ... = ... | test.cpp:13:10:13:11 | t2 |
|
||||||
| test.cpp:12:10:12:10 | 0 | test.cpp:12:5:12:10 | ... = ... |
|
| test.cpp:12:10:12:10 | 0 | test.cpp:12:5:12:10 | ... = ... |
|
||||||
| test.cpp:13:10:13:11 | t2 | test.cpp:15:3:15:6 | Phi |
|
| test.cpp:13:5:13:8 | Phi input | test.cpp:15:3:15:6 | SSA phi read(t2) |
|
||||||
| test.cpp:13:10:13:11 | t2 | test.cpp:15:3:15:6 | Phi |
|
| test.cpp:13:5:13:8 | Phi input | test.cpp:15:3:15:6 | SSA phi(*t2) |
|
||||||
| test.cpp:15:3:15:6 | Phi | test.cpp:15:8:15:9 | t2 |
|
| test.cpp:13:10:13:11 | t2 | test.cpp:13:5:13:8 | Phi input |
|
||||||
| test.cpp:15:3:15:6 | Phi | test.cpp:15:8:15:9 | t2 |
|
| test.cpp:13:10:13:11 | t2 | test.cpp:13:5:13:8 | Phi input |
|
||||||
| test.cpp:15:8:15:9 | t2 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:15:3:15:6 | SSA phi read(t2) | test.cpp:15:8:15:9 | t2 |
|
||||||
| test.cpp:15:8:15:9 | t2 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:15:3:15:6 | SSA phi(*t2) | test.cpp:15:8:15:9 | t2 |
|
||||||
|
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | Phi input |
|
||||||
|
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | Phi input |
|
||||||
| test.cpp:17:3:17:8 | ... = ... | test.cpp:21:8:21:9 | t1 |
|
| test.cpp:17:3:17:8 | ... = ... | test.cpp:21:8:21:9 | t1 |
|
||||||
| test.cpp:17:8:17:8 | 0 | test.cpp:17:3:17:8 | ... = ... |
|
| test.cpp:17:8:17:8 | 0 | test.cpp:17:3:17:8 | ... = ... |
|
||||||
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:21:8:21:9 | t1 | test.cpp:23:15:23:16 | Phi input |
|
||||||
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:21:8:21:9 | t1 | test.cpp:23:15:23:16 | Phi input |
|
||||||
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | 0 |
|
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | 0 |
|
||||||
| test.cpp:23:15:23:16 | 0 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | Phi input |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:23:19:23:19 | i |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(*t2) |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:23:19:23:19 | i |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(i) |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:23:23:23:24 | t1 |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t1) |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:23:23:23:24 | t1 |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t2) |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:24:10:24:11 | t2 |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi(*i) |
|
||||||
| test.cpp:23:19:23:19 | Phi | test.cpp:24:10:24:11 | t2 |
|
| test.cpp:23:15:23:16 | Phi input | test.cpp:23:19:23:19 | SSA phi(*t1) |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi read(*t2) | test.cpp:24:10:24:11 | t2 |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi read(i) | test.cpp:23:19:23:19 | i |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi read(t1) | test.cpp:23:23:23:24 | t1 |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi read(t2) | test.cpp:24:10:24:11 | t2 |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi(*i) | test.cpp:23:19:23:19 | i |
|
||||||
|
| test.cpp:23:19:23:19 | SSA phi(*t1) | test.cpp:23:23:23:24 | t1 |
|
||||||
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
|
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
|
||||||
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
|
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
|
||||||
| test.cpp:23:23:23:24 | t1 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:23:23:24 | t1 | test.cpp:23:27:23:29 | Phi input |
|
||||||
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
|
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
|
||||||
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
|
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
|
||||||
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | *i |
|
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | *i |
|
||||||
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | i |
|
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | i |
|
||||||
| test.cpp:23:27:23:27 | i | test.cpp:23:19:23:19 | Phi |
|
|
||||||
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
|
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
|
||||||
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
|
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
|
||||||
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:29 | Phi input |
|
||||||
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | ... ++ |
|
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | ... ++ |
|
||||||
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | Phi input |
|
||||||
| test.cpp:24:10:24:11 | t2 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(*t2) |
|
||||||
| test.cpp:24:10:24:11 | t2 | test.cpp:23:19:23:19 | Phi |
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(i) |
|
||||||
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t1) |
|
||||||
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi read(t2) |
|
||||||
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi(*i) |
|
||||||
|
| test.cpp:23:27:23:29 | Phi input | test.cpp:23:19:23:19 | SSA phi(*t1) |
|
||||||
|
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:27:23:29 | Phi input |
|
||||||
|
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | Phi input |
|
||||||
|
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | Phi input |
|
||||||
| test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... |
|
| test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... |
|
||||||
| test.cpp:382:48:382:54 | source1 | test.cpp:384:16:384:23 | *& ... |
|
| test.cpp:382:48:382:54 | source1 | test.cpp:384:16:384:23 | *& ... |
|
||||||
| test.cpp:383:12:383:13 | 0 | test.cpp:383:12:383:13 | 0 |
|
| test.cpp:383:12:383:13 | 0 | test.cpp:383:12:383:13 | 0 |
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ astFlow
|
|||||||
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:62:14:62:14 | x |
|
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:62:14:62:14 | x |
|
||||||
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
|
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
|
||||||
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
|
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
|
||||||
|
| BarrierGuard.cpp:81:11:81:16 | call to source | BarrierGuard.cpp:86:8:86:8 | x |
|
||||||
|
| BarrierGuard.cpp:90:11:90:16 | call to source | BarrierGuard.cpp:101:8:101:8 | x |
|
||||||
|
| BarrierGuard.cpp:107:11:107:16 | call to source | BarrierGuard.cpp:112:8:112:8 | x |
|
||||||
|
| BarrierGuard.cpp:116:11:116:16 | call to source | BarrierGuard.cpp:127:8:127:8 | x |
|
||||||
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
|
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
|
||||||
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
|
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
|
||||||
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:22:8:22:20 | & ... |
|
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:22:8:22:20 | & ... |
|
||||||
@@ -153,6 +157,7 @@ irFlow
|
|||||||
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
||||||
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
||||||
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | *stackArray |
|
||||||
|
| clang.cpp:57:21:57:28 | call to source | clang.cpp:59:8:59:8 | d |
|
||||||
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
|
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
|
||||||
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
|
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
|
||||||
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |
|
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
// --- stub library headers ---
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
#define SIZE_MAX 0xFFFFFFFF
|
||||||
|
|
||||||
|
template <class T> class allocator {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class charT> struct char_traits {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||||
|
class basic_string {
|
||||||
|
public:
|
||||||
|
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef basic_string<char> string;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace system {
|
||||||
|
class error_code {
|
||||||
|
public:
|
||||||
|
operator bool() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
template<typename Protocol/*, typename Executor*/>
|
||||||
|
class basic_stream_socket /*: public basic_socket<Protocol, Executor>*/ {
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ip {
|
||||||
|
class tcp {
|
||||||
|
public:
|
||||||
|
typedef basic_stream_socket<tcp> socket;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Allocator = std::allocator<char>> class basic_streambuf {
|
||||||
|
public:
|
||||||
|
basic_streambuf(
|
||||||
|
std::size_t maximum_size = SIZE_MAX,
|
||||||
|
const Allocator &allocator = Allocator());
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef basic_streambuf<> streambuf;
|
||||||
|
|
||||||
|
class mutable_buffer {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Elem, typename Traits, typename Allocator>
|
||||||
|
mutable_buffer buffer(std::basic_string<Elem, Traits, Allocator> & data);
|
||||||
|
|
||||||
|
template<typename SyncReadStream, typename Allocator> std::size_t read_until(
|
||||||
|
SyncReadStream &s,
|
||||||
|
asio::basic_streambuf<Allocator> &b,
|
||||||
|
char delim,
|
||||||
|
boost::system::error_code &ec);
|
||||||
|
|
||||||
|
template<typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(
|
||||||
|
SyncWriteStream &s,
|
||||||
|
const ConstBufferSequence &buffers,
|
||||||
|
boost::system::error_code &ec,
|
||||||
|
int constraint = 0); // simplified
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- test code ---
|
||||||
|
|
||||||
|
char *source();
|
||||||
|
void sink(char *);
|
||||||
|
void sink(std::string);
|
||||||
|
void sink(boost::asio::streambuf);
|
||||||
|
void sink(boost::asio::mutable_buffer);
|
||||||
|
|
||||||
|
char *getenv(const char *name);
|
||||||
|
int send(int, const void*, int, int);
|
||||||
|
|
||||||
|
void test(boost::asio::ip::tcp::socket &socket) {
|
||||||
|
boost::asio::streambuf recv_buffer;
|
||||||
|
boost::system::error_code error;
|
||||||
|
|
||||||
|
boost::asio::read_until(socket, recv_buffer, '\0', error);
|
||||||
|
if (error) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
sink(recv_buffer); // $ ir
|
||||||
|
|
||||||
|
boost::asio::write(socket, recv_buffer, error); // $ ir
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
std::string send_str = std::string(source());
|
||||||
|
sink(send_str); // $ ir
|
||||||
|
|
||||||
|
boost::asio::mutable_buffer send_buffer = boost::asio::buffer(send_str);
|
||||||
|
sink(send_buffer); // $ ir
|
||||||
|
|
||||||
|
boost::asio::write(socket, send_buffer, error); // $ ir
|
||||||
|
if (error) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
testFailures
|
||||||
|
failures
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sourceModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||||
|
- ["", "", False, "ymlSource", "", "", "ReturnValue", "local", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sinkModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
|
||||||
|
- ["", "", False, "ymlSink", "", "", "Argument[0]", "test-sink", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: summaryModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||||
|
- ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||||
34
cpp/ql/test/library-tests/dataflow/external-models/flow.ql
Normal file
34
cpp/ql/test/library-tests/dataflow/external-models/flow.ql
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import TestUtilities.dataflow.FlowTestCommon
|
||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.security.FlowSources
|
||||||
|
|
||||||
|
module IRTest {
|
||||||
|
private import semmle.code.cpp.ir.IR
|
||||||
|
private import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
|
|
||||||
|
/** Common data flow configuration to be used by tests. */
|
||||||
|
module TestAllocationConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
// external flow source node
|
||||||
|
sourceNode(source, _)
|
||||||
|
or
|
||||||
|
// test source function
|
||||||
|
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
// external flow sink node
|
||||||
|
sinkNode(sink, _)
|
||||||
|
or
|
||||||
|
// test sink function
|
||||||
|
exists(FunctionCall call |
|
||||||
|
call.getTarget().getName() = "sink" and
|
||||||
|
sink.asExpr() = call.getAnArgument()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module IRFlow = TaintTracking::Global<TestAllocationConfig>;
|
||||||
|
}
|
||||||
|
|
||||||
|
import MakeTest<IRFlowTest<IRTest::IRFlow>>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
| asio_streams.cpp:93:29:93:39 | *recv_buffer | remote-sink |
|
||||||
|
| asio_streams.cpp:103:29:103:39 | *send_buffer | remote-sink |
|
||||||
|
| test.cpp:9:10:9:10 | 0 | test-sink |
|
||||||
|
| test.cpp:11:10:11:10 | x | test-sink |
|
||||||
|
| test.cpp:15:10:15:10 | y | test-sink |
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sinkModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
|
||||||
|
- ["", "", False, "ymlSink", "", "", "Argument[0]", "test-sink", "manual"]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
|
import semmle.code.cpp.dataflow.ExternalFlow
|
||||||
|
|
||||||
|
from DataFlow::Node node, string kind
|
||||||
|
where sinkNode(node, kind)
|
||||||
|
select node, kind
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| asio_streams.cpp:87:34:87:44 | read_until output argument | remote |
|
||||||
|
| test.cpp:7:10:7:18 | call to ymlSource | local |
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: sourceModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||||
|
- ["", "", False, "ymlSource", "", "", "ReturnValue", "local", "manual"]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
|
import semmle.code.cpp.dataflow.ExternalFlow
|
||||||
|
|
||||||
|
from DataFlow::Node node, string kind
|
||||||
|
where sourceNode(node, kind)
|
||||||
|
select node, kind
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer |
|
||||||
|
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep |
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: summaryModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||||
|
- ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
|
import semmle.code.cpp.dataflow.ExternalFlow
|
||||||
|
import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||||
|
|
||||||
|
from DataFlow::Node node1, DataFlow::Node node2
|
||||||
|
where FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2, _)
|
||||||
|
select node1, node2
|
||||||
16
cpp/ql/test/library-tests/dataflow/external-models/test.cpp
Normal file
16
cpp/ql/test/library-tests/dataflow/external-models/test.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
int ymlSource();
|
||||||
|
void ymlSink(int value);
|
||||||
|
int ymlStep(int value);
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
int x = ymlSource();
|
||||||
|
|
||||||
|
ymlSink(0);
|
||||||
|
|
||||||
|
ymlSink(x); // $ ir
|
||||||
|
|
||||||
|
int y = ymlStep(x);
|
||||||
|
|
||||||
|
ymlSink(y); // $ ir
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.dataflow.ExternalFlow::CsvValidation
|
||||||
@@ -184,6 +184,7 @@ postWithInFlow
|
|||||||
| simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
| simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. |
|
| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. |
|
| struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. |
|
| struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
viableImplInCallContextTooLarge
|
viableImplInCallContextTooLarge
|
||||||
|
|||||||
@@ -842,6 +842,10 @@ edges
|
|||||||
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:108:17:108:26 | call to user_input | provenance | |
|
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:108:17:108:26 | call to user_input | provenance | |
|
||||||
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:109:43:109:43 | x | provenance | |
|
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:109:43:109:43 | x | provenance | |
|
||||||
| simple.cpp:109:43:109:43 | x | simple.cpp:103:24:103:24 | x | provenance | |
|
| simple.cpp:109:43:109:43 | x | simple.cpp:103:24:103:24 | x | provenance | |
|
||||||
|
| simple.cpp:118:5:118:5 | *a [post update] [i] | simple.cpp:120:8:120:8 | *a [i] | provenance | |
|
||||||
|
| simple.cpp:118:5:118:22 | ... = ... | simple.cpp:118:5:118:5 | *a [post update] [i] | provenance | |
|
||||||
|
| simple.cpp:118:11:118:20 | call to user_input | simple.cpp:118:5:118:22 | ... = ... | provenance | |
|
||||||
|
| simple.cpp:120:8:120:8 | *a [i] | simple.cpp:120:10:120:10 | i | provenance | |
|
||||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
|
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
|
||||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
|
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
|
||||||
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||||
@@ -1747,6 +1751,11 @@ nodes
|
|||||||
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
|
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
|
||||||
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
|
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
|
||||||
| simple.cpp:109:43:109:43 | x | semmle.label | x |
|
| simple.cpp:109:43:109:43 | x | semmle.label | x |
|
||||||
|
| simple.cpp:118:5:118:5 | *a [post update] [i] | semmle.label | *a [post update] [i] |
|
||||||
|
| simple.cpp:118:5:118:22 | ... = ... | semmle.label | ... = ... |
|
||||||
|
| simple.cpp:118:11:118:20 | call to user_input | semmle.label | call to user_input |
|
||||||
|
| simple.cpp:120:8:120:8 | *a [i] | semmle.label | *a [i] |
|
||||||
|
| simple.cpp:120:10:120:10 | i | semmle.label | i |
|
||||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||||
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
|
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
|
||||||
@@ -1957,6 +1966,7 @@ subpaths
|
|||||||
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
||||||
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
||||||
| simple.cpp:104:14:104:14 | x | simple.cpp:108:17:108:26 | call to user_input | simple.cpp:104:14:104:14 | x | x flows from $@ | simple.cpp:108:17:108:26 | call to user_input | call to user_input |
|
| simple.cpp:104:14:104:14 | x | simple.cpp:108:17:108:26 | call to user_input | simple.cpp:104:14:104:14 | x | x flows from $@ | simple.cpp:108:17:108:26 | call to user_input | call to user_input |
|
||||||
|
| simple.cpp:120:10:120:10 | i | simple.cpp:118:11:118:20 | call to user_input | simple.cpp:120:10:120:10 | i | i flows from $@ | simple.cpp:118:11:118:20 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
||||||
|
|||||||
@@ -289,3 +289,5 @@ WARNING: Module DataFlow has been deprecated and may be removed in future (parti
|
|||||||
| simple.cpp:83:12:83:13 | f1 | AST only |
|
| simple.cpp:83:12:83:13 | f1 | AST only |
|
||||||
| simple.cpp:92:7:92:7 | i | AST only |
|
| simple.cpp:92:7:92:7 | i | AST only |
|
||||||
| simple.cpp:94:10:94:11 | a2 | IR only |
|
| simple.cpp:94:10:94:11 | a2 | IR only |
|
||||||
|
| simple.cpp:118:7:118:7 | i | AST only |
|
||||||
|
| simple.cpp:120:8:120:8 | a | IR only |
|
||||||
|
|||||||
@@ -649,6 +649,8 @@
|
|||||||
| simple.cpp:84:14:84:20 | this |
|
| simple.cpp:84:14:84:20 | this |
|
||||||
| simple.cpp:92:5:92:5 | a |
|
| simple.cpp:92:5:92:5 | a |
|
||||||
| simple.cpp:94:10:94:11 | a2 |
|
| simple.cpp:94:10:94:11 | a2 |
|
||||||
|
| simple.cpp:118:5:118:5 | a |
|
||||||
|
| simple.cpp:120:8:120:8 | a |
|
||||||
| struct_init.c:15:8:15:9 | ab |
|
| struct_init.c:15:8:15:9 | ab |
|
||||||
| struct_init.c:15:12:15:12 | a |
|
| struct_init.c:15:12:15:12 | a |
|
||||||
| struct_init.c:16:8:16:9 | ab |
|
| struct_init.c:16:8:16:9 | ab |
|
||||||
|
|||||||
@@ -579,6 +579,8 @@ WARNING: Module DataFlow has been deprecated and may be removed in future (parti
|
|||||||
| simple.cpp:84:14:84:20 | this |
|
| simple.cpp:84:14:84:20 | this |
|
||||||
| simple.cpp:92:5:92:5 | a |
|
| simple.cpp:92:5:92:5 | a |
|
||||||
| simple.cpp:92:7:92:7 | i |
|
| simple.cpp:92:7:92:7 | i |
|
||||||
|
| simple.cpp:118:5:118:5 | a |
|
||||||
|
| simple.cpp:118:7:118:7 | i |
|
||||||
| struct_init.c:15:8:15:9 | ab |
|
| struct_init.c:15:8:15:9 | ab |
|
||||||
| struct_init.c:15:12:15:12 | a |
|
| struct_init.c:15:12:15:12 | a |
|
||||||
| struct_init.c:16:8:16:9 | ab |
|
| struct_init.c:16:8:16:9 | ab |
|
||||||
|
|||||||
@@ -731,6 +731,10 @@ edges
|
|||||||
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] | provenance | |
|
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] | provenance | |
|
||||||
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... | provenance | |
|
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... | provenance | |
|
||||||
| simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i | provenance | |
|
| simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i | provenance | |
|
||||||
|
| simple.cpp:118:5:118:5 | a [post update] [i] | simple.cpp:120:8:120:8 | a [i] | provenance | |
|
||||||
|
| simple.cpp:118:5:118:22 | ... = ... | simple.cpp:118:5:118:5 | a [post update] [i] | provenance | |
|
||||||
|
| simple.cpp:118:11:118:20 | call to user_input | simple.cpp:118:5:118:22 | ... = ... | provenance | |
|
||||||
|
| simple.cpp:120:8:120:8 | a [i] | simple.cpp:120:10:120:10 | i | provenance | |
|
||||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
|
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
|
||||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | provenance | |
|
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | provenance | |
|
||||||
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||||
@@ -1538,6 +1542,11 @@ nodes
|
|||||||
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
|
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
|
||||||
| simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] |
|
| simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] |
|
||||||
| simple.cpp:94:13:94:13 | i | semmle.label | i |
|
| simple.cpp:94:13:94:13 | i | semmle.label | i |
|
||||||
|
| simple.cpp:118:5:118:5 | a [post update] [i] | semmle.label | a [post update] [i] |
|
||||||
|
| simple.cpp:118:5:118:22 | ... = ... | semmle.label | ... = ... |
|
||||||
|
| simple.cpp:118:11:118:20 | call to user_input | semmle.label | call to user_input |
|
||||||
|
| simple.cpp:120:8:120:8 | a [i] | semmle.label | a [i] |
|
||||||
|
| simple.cpp:120:10:120:10 | i | semmle.label | i |
|
||||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||||
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
|
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
|
||||||
@@ -1751,6 +1760,7 @@ subpaths
|
|||||||
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
|
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
|
||||||
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
||||||
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
||||||
|
| simple.cpp:120:10:120:10 | i | simple.cpp:118:11:118:20 | call to user_input | simple.cpp:120:10:120:10 | i | i flows from $@ | simple.cpp:118:11:118:20 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
||||||
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
||||||
|
|||||||
@@ -111,4 +111,13 @@ namespace TestAdditionalCallTargets {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post_update_to_phi_input(bool b)
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
if(b) {
|
||||||
|
a.i = user_input();
|
||||||
|
}
|
||||||
|
sink(a.i); // $ ast,ir
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Simple
|
} // namespace Simple
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
// --- stub library headers ---
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
#define SIZE_MAX 0xFFFFFFFF
|
||||||
|
|
||||||
|
template <class T> class allocator {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class charT> struct char_traits {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||||
|
class basic_string {
|
||||||
|
public:
|
||||||
|
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef basic_string<char> string;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace system {
|
||||||
|
class error_code {
|
||||||
|
public:
|
||||||
|
operator bool() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
template<typename Protocol/*, typename Executor*/>
|
||||||
|
class basic_stream_socket /*: public basic_socket<Protocol, Executor>*/ {
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ip {
|
||||||
|
class tcp {
|
||||||
|
public:
|
||||||
|
typedef basic_stream_socket<tcp> socket;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Allocator = std::allocator<char>> class basic_streambuf {
|
||||||
|
public:
|
||||||
|
basic_streambuf(
|
||||||
|
std::size_t maximum_size = SIZE_MAX,
|
||||||
|
const Allocator &allocator = Allocator());
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef basic_streambuf<> streambuf;
|
||||||
|
|
||||||
|
class mutable_buffer {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Elem, typename Traits, typename Allocator>
|
||||||
|
mutable_buffer buffer(std::basic_string<Elem, Traits, Allocator> & data);
|
||||||
|
|
||||||
|
template<typename SyncReadStream, typename Allocator> std::size_t read_until(
|
||||||
|
SyncReadStream &s,
|
||||||
|
asio::basic_streambuf<Allocator> &b,
|
||||||
|
char delim,
|
||||||
|
boost::system::error_code &ec);
|
||||||
|
|
||||||
|
template<typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(
|
||||||
|
SyncWriteStream &s,
|
||||||
|
const ConstBufferSequence &buffers,
|
||||||
|
boost::system::error_code &ec,
|
||||||
|
int constraint = 0); // simplified
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- test code ---
|
||||||
|
|
||||||
|
void test(boost::asio::ip::tcp::socket &socket) {
|
||||||
|
boost::asio::streambuf recv_buffer;
|
||||||
|
boost::system::error_code error;
|
||||||
|
|
||||||
|
boost::asio::read_until(socket, recv_buffer, '\0', error); // $ remote_source
|
||||||
|
if (error) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string send_str = std::string("message");
|
||||||
|
boost::asio::mutable_buffer send_buffer = boost::asio::buffer(send_str);
|
||||||
|
boost::asio::write(socket, send_buffer, error); // $ remote_sink
|
||||||
|
if (error) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22734,6 +22734,25 @@ ir.cpp:
|
|||||||
# 2552| Type = [Class] ClassWithDestructor
|
# 2552| Type = [Class] ClassWithDestructor
|
||||||
# 2552| ValueCategory = xvalue
|
# 2552| ValueCategory = xvalue
|
||||||
# 2553| getStmt(1): [ReturnStmt] return ...
|
# 2553| getStmt(1): [ReturnStmt] return ...
|
||||||
|
# 2555| [TopLevelFunction] void builtin_bitcast(unsigned long)
|
||||||
|
# 2555| <params>:
|
||||||
|
# 2555| getParameter(0): [Parameter] ul
|
||||||
|
# 2555| Type = [LongType] unsigned long
|
||||||
|
# 2555| getEntryPoint(): [BlockStmt] { ... }
|
||||||
|
# 2556| getStmt(0): [DeclStmt] declaration
|
||||||
|
# 2556| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
|
||||||
|
# 2556| Type = [DoubleType] double
|
||||||
|
# 2556| getVariable().getInitializer(): [Initializer] initializer for d
|
||||||
|
# 2556| getExpr(): [BuiltInBitCast] __builtin_bit_cast
|
||||||
|
# 2556| Type = [DoubleType] double
|
||||||
|
# 2556| ValueCategory = prvalue
|
||||||
|
# 2556| getChild(0): [TypeName] double
|
||||||
|
# 2556| Type = [DoubleType] double
|
||||||
|
# 2556| ValueCategory = prvalue
|
||||||
|
# 2556| getChild(1): [VariableAccess] ul
|
||||||
|
# 2556| Type = [LongType] unsigned long
|
||||||
|
# 2556| ValueCategory = prvalue(load)
|
||||||
|
# 2557| getStmt(1): [ReturnStmt] return ...
|
||||||
perf-regression.cpp:
|
perf-regression.cpp:
|
||||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||||
# 4| <params>:
|
# 4| <params>:
|
||||||
|
|||||||
@@ -13430,6 +13430,32 @@ ir.cpp:
|
|||||||
# 1898| v1898_6(void) = AliasedUse : m1898_3
|
# 1898| v1898_6(void) = AliasedUse : m1898_3
|
||||||
# 1898| v1898_7(void) = ExitFunction :
|
# 1898| v1898_7(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 1899| const char[17] __PRETTY_FUNCTION__
|
||||||
|
# 1899| Block 0
|
||||||
|
# 1899| v1899_1(void) = EnterFunction :
|
||||||
|
# 1899| m1899_2(unknown) = AliasedDefinition :
|
||||||
|
# 1899| r1899_3(glval<char[17]>) = VariableAddress[__PRETTY_FUNCTION__] :
|
||||||
|
# 1899| r1899_4(glval<char[17]>) = StringConstant[__PRETTY_FUNCTION__] :
|
||||||
|
# 1899| r1899_5(char[17]) = Load[?] : &:r1899_4, ~m?
|
||||||
|
# 1899| m1899_6(char[17]) = Store[__PRETTY_FUNCTION__] : &:r1899_3, r1899_5
|
||||||
|
# 1899| m1899_7(unknown) = Chi : total:m1899_2, partial:m1899_6
|
||||||
|
# 1899| v1899_8(void) = ReturnVoid :
|
||||||
|
# 1899| v1899_9(void) = AliasedUse : ~m1899_7
|
||||||
|
# 1899| v1899_10(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 1900| const char[10] __func__
|
||||||
|
# 1900| Block 0
|
||||||
|
# 1900| v1900_1(void) = EnterFunction :
|
||||||
|
# 1900| m1900_2(unknown) = AliasedDefinition :
|
||||||
|
# 1900| r1900_3(glval<char[10]>) = VariableAddress[__func__] :
|
||||||
|
# 1900| r1900_4(glval<char[10]>) = StringConstant[__func__] :
|
||||||
|
# 1900| r1900_5(char[10]) = Load[?] : &:r1900_4, ~m?
|
||||||
|
# 1900| m1900_6(char[10]) = Store[__func__] : &:r1900_3, r1900_5
|
||||||
|
# 1900| m1900_7(unknown) = Chi : total:m1900_2, partial:m1900_6
|
||||||
|
# 1900| v1900_8(void) = ReturnVoid :
|
||||||
|
# 1900| v1900_9(void) = AliasedUse : ~m1900_7
|
||||||
|
# 1900| v1900_10(void) = ExitFunction :
|
||||||
|
|
||||||
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
|
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
|
||||||
# 1911| Block 0
|
# 1911| Block 0
|
||||||
# 1911| v1911_1(void) = EnterFunction :
|
# 1911| v1911_1(void) = EnterFunction :
|
||||||
@@ -18351,6 +18377,24 @@ ir.cpp:
|
|||||||
# 2550| Block 2
|
# 2550| Block 2
|
||||||
# 2550| v2550_10(void) = Unreached :
|
# 2550| v2550_10(void) = Unreached :
|
||||||
|
|
||||||
|
# 2555| void builtin_bitcast(unsigned long)
|
||||||
|
# 2555| Block 0
|
||||||
|
# 2555| v2555_1(void) = EnterFunction :
|
||||||
|
# 2555| m2555_2(unknown) = AliasedDefinition :
|
||||||
|
# 2555| m2555_3(unknown) = InitializeNonLocal :
|
||||||
|
# 2555| m2555_4(unknown) = Chi : total:m2555_2, partial:m2555_3
|
||||||
|
# 2555| r2555_5(glval<unsigned long>) = VariableAddress[ul] :
|
||||||
|
# 2555| m2555_6(unsigned long) = InitializeParameter[ul] : &:r2555_5
|
||||||
|
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
|
||||||
|
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
|
||||||
|
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, m2555_6
|
||||||
|
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
|
||||||
|
# 2556| m2556_5(double) = Store[d] : &:r2556_1, r2556_4
|
||||||
|
# 2557| v2557_1(void) = NoOp :
|
||||||
|
# 2555| v2555_7(void) = ReturnVoid :
|
||||||
|
# 2555| v2555_8(void) = AliasedUse : m2555_3
|
||||||
|
# 2555| v2555_9(void) = ExitFunction :
|
||||||
|
|
||||||
perf-regression.cpp:
|
perf-regression.cpp:
|
||||||
# 6| void Big::Big()
|
# 6| void Big::Big()
|
||||||
# 6| Block 0
|
# 6| Block 0
|
||||||
|
|||||||
@@ -2552,4 +2552,8 @@ void constexpr_inconsistency(bool b) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void builtin_bitcast(unsigned long ul) {
|
||||||
|
double d = __builtin_bit_cast(double, ul);
|
||||||
|
}
|
||||||
|
|
||||||
// semmle-extractor-options: -std=c++20 --clang
|
// semmle-extractor-options: -std=c++20 --clang
|
||||||
|
|||||||
@@ -12384,6 +12384,30 @@ ir.cpp:
|
|||||||
# 1898| v1898_5(void) = AliasedUse : ~m?
|
# 1898| v1898_5(void) = AliasedUse : ~m?
|
||||||
# 1898| v1898_6(void) = ExitFunction :
|
# 1898| v1898_6(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 1899| const char[17] __PRETTY_FUNCTION__
|
||||||
|
# 1899| Block 0
|
||||||
|
# 1899| v1899_1(void) = EnterFunction :
|
||||||
|
# 1899| mu1899_2(unknown) = AliasedDefinition :
|
||||||
|
# 1899| r1899_3(glval<char[17]>) = VariableAddress[__PRETTY_FUNCTION__] :
|
||||||
|
# 1899| r1899_4(glval<char[17]>) = StringConstant[__PRETTY_FUNCTION__] :
|
||||||
|
# 1899| r1899_5(char[17]) = Load[?] : &:r1899_4, ~m?
|
||||||
|
# 1899| mu1899_6(char[17]) = Store[__PRETTY_FUNCTION__] : &:r1899_3, r1899_5
|
||||||
|
# 1899| v1899_7(void) = ReturnVoid :
|
||||||
|
# 1899| v1899_8(void) = AliasedUse : ~m?
|
||||||
|
# 1899| v1899_9(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 1900| const char[10] __func__
|
||||||
|
# 1900| Block 0
|
||||||
|
# 1900| v1900_1(void) = EnterFunction :
|
||||||
|
# 1900| mu1900_2(unknown) = AliasedDefinition :
|
||||||
|
# 1900| r1900_3(glval<char[10]>) = VariableAddress[__func__] :
|
||||||
|
# 1900| r1900_4(glval<char[10]>) = StringConstant[__func__] :
|
||||||
|
# 1900| r1900_5(char[10]) = Load[?] : &:r1900_4, ~m?
|
||||||
|
# 1900| mu1900_6(char[10]) = Store[__func__] : &:r1900_3, r1900_5
|
||||||
|
# 1900| v1900_7(void) = ReturnVoid :
|
||||||
|
# 1900| v1900_8(void) = AliasedUse : ~m?
|
||||||
|
# 1900| v1900_9(void) = ExitFunction :
|
||||||
|
|
||||||
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
|
# 1911| void* missing_declaration_entries::Bar1<int>::missing_type_decl_entry(missing_declaration_entries::Bar1<int>::pointer)
|
||||||
# 1911| Block 0
|
# 1911| Block 0
|
||||||
# 1911| v1911_1(void) = EnterFunction :
|
# 1911| v1911_1(void) = EnterFunction :
|
||||||
@@ -16693,6 +16717,23 @@ ir.cpp:
|
|||||||
# 2550| v2550_7(void) = AliasedUse : ~m?
|
# 2550| v2550_7(void) = AliasedUse : ~m?
|
||||||
# 2550| v2550_8(void) = ExitFunction :
|
# 2550| v2550_8(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 2555| void builtin_bitcast(unsigned long)
|
||||||
|
# 2555| Block 0
|
||||||
|
# 2555| v2555_1(void) = EnterFunction :
|
||||||
|
# 2555| mu2555_2(unknown) = AliasedDefinition :
|
||||||
|
# 2555| mu2555_3(unknown) = InitializeNonLocal :
|
||||||
|
# 2555| r2555_4(glval<unsigned long>) = VariableAddress[ul] :
|
||||||
|
# 2555| mu2555_5(unsigned long) = InitializeParameter[ul] : &:r2555_4
|
||||||
|
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
|
||||||
|
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
|
||||||
|
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, ~m?
|
||||||
|
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
|
||||||
|
# 2556| mu2556_5(double) = Store[d] : &:r2556_1, r2556_4
|
||||||
|
# 2557| v2557_1(void) = NoOp :
|
||||||
|
# 2555| v2555_6(void) = ReturnVoid :
|
||||||
|
# 2555| v2555_7(void) = AliasedUse : ~m?
|
||||||
|
# 2555| v2555_8(void) = ExitFunction :
|
||||||
|
|
||||||
perf-regression.cpp:
|
perf-regression.cpp:
|
||||||
# 6| void Big::Big()
|
# 6| void Big::Big()
|
||||||
# 6| Block 0
|
# 6| Block 0
|
||||||
|
|||||||
@@ -39,3 +39,4 @@
|
|||||||
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
|
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
|
||||||
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
|
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
|
||||||
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||||
|
| variables.cpp:60:10:60:17 | __func__ | file://:0:0:0:0 | const char[9] | GlobalLikeVariable, StaticInitializedStaticLocalVariable | | static |
|
||||||
|
|||||||
@@ -55,3 +55,7 @@ struct address {
|
|||||||
void hasExtern() {
|
void hasExtern() {
|
||||||
extern int externInFunction;
|
extern int externInFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* isStatic() {
|
||||||
|
return __func__;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ char *gets(char *s);
|
|||||||
|
|
||||||
void testGets() {
|
void testGets() {
|
||||||
char buf1[1024];
|
char buf1[1024];
|
||||||
char buf2 = malloc(1024);
|
char *buf2 = malloc(1024);
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
gets(buf1); // BAD: use of gets
|
gets(buf1); // BAD: use of gets
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
char *gets();
|
||||||
|
|
||||||
|
void testOtherGets() {
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = gets(); // GOOD: this is not the gets from stdio.h
|
||||||
|
}
|
||||||
1
csharp/.gitignore
vendored
1
csharp/.gitignore
vendored
@@ -14,5 +14,4 @@ csharp.log
|
|||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
|
|
||||||
extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||||
extractor-pack
|
|
||||||
paket-files/
|
paket-files/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup", "pkg_files")
|
load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup", "pkg_files")
|
||||||
load("@semmle_code//:dist.bzl", "dist")
|
load("//misc/bazel:pkg.bzl", "codeql_pack", "codeql_pkg_files_overlay")
|
||||||
load("//misc/bazel:pkg.bzl", "codeql_pkg_files_overlay")
|
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
@@ -59,22 +58,16 @@ codeql_pkg_files_overlay(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
dist(
|
codeql_pack(
|
||||||
name = "extractor-arch",
|
name = "csharp",
|
||||||
srcs = [":extractor-arch-overlay"],
|
|
||||||
)
|
|
||||||
|
|
||||||
dist(
|
|
||||||
name = "extractor-generic",
|
|
||||||
srcs = [
|
srcs = [
|
||||||
":dbscheme-group",
|
":dbscheme-group",
|
||||||
":extra-files",
|
":extra-files",
|
||||||
|
":extractor-arch-overlay",
|
||||||
":extractor-asp",
|
":extractor-asp",
|
||||||
"//csharp/downgrades",
|
"//csharp/downgrades",
|
||||||
"//csharp/tools",
|
"//csharp/tools",
|
||||||
],
|
],
|
||||||
prefix = "csharp",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
test_suite(
|
test_suite(
|
||||||
|
|||||||
@@ -7,10 +7,11 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
|
||||||
<Company>GitHub</Company>
|
<Company>GitHub</Company>
|
||||||
|
<Product>CodeQL</Product>
|
||||||
<Copyright>Copyright © $([System.DateTime]::Now.Year) $(Company)</Copyright>
|
<Copyright>Copyright © $([System.DateTime]::Now.Year) $(Company)</Copyright>
|
||||||
<Version>1.0.0.0</Version>
|
<Version>1.0.0.0</Version>
|
||||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.0</FileVersion>
|
<FileVersion>$(Version)</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_xunit_test(
|
|||||||
name = "Semmle.Autobuild.CSharp.Tests",
|
name = "Semmle.Autobuild.CSharp.Tests",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
deps = [
|
deps = [
|
||||||
"//csharp/autobuilder/Semmle.Autobuild.CSharp:bin/Semmle.Autobuild.CSharp",
|
"//csharp/autobuilder/Semmle.Autobuild.CSharp:bin/Semmle.Autobuild.CSharp",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_binary(
|
|||||||
name = "Semmle.Autobuild.CSharp",
|
name = "Semmle.Autobuild.CSharp",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
visibility = ["//csharp:__subpackages__"],
|
visibility = ["//csharp:__subpackages__"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Semmle.Autobuild.CSharp
|
|||||||
public class CSharpAutobuildOptions : AutobuildOptionsShared
|
public class CSharpAutobuildOptions : AutobuildOptionsShared
|
||||||
{
|
{
|
||||||
private const string buildModeEnvironmentVariable = "CODEQL_EXTRACTOR_CSHARP_BUILD_MODE";
|
private const string buildModeEnvironmentVariable = "CODEQL_EXTRACTOR_CSHARP_BUILD_MODE";
|
||||||
private const string extractorOptionPrefix = "CODEQL_EXTRACTOR_CSHARP_OPTION_";
|
internal const string ExtractorOptionBuildless = "CODEQL_EXTRACTOR_CSHARP_OPTION_BUILDLESS";
|
||||||
|
|
||||||
public bool Buildless { get; }
|
public bool Buildless { get; }
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ namespace Semmle.Autobuild.CSharp
|
|||||||
public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
|
public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
|
||||||
{
|
{
|
||||||
Buildless =
|
Buildless =
|
||||||
actions.GetEnvironmentVariable(extractorOptionPrefix + "BUILDLESS").AsBool("buildless", false) ||
|
actions.GetEnvironmentVariable(ExtractorOptionBuildless).AsBool("buildless", false) ||
|
||||||
actions.GetEnvironmentVariable(buildModeEnvironmentVariable)?.ToLower() == "none";
|
actions.GetEnvironmentVariable(buildModeEnvironmentVariable)?.ToLower() == "none";
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ namespace Semmle.Autobuild.CSharp
|
|||||||
case CSharpBuildStrategy.Buildless:
|
case CSharpBuildStrategy.Buildless:
|
||||||
// No need to check that the extractor has been executed in buildless mode
|
// No need to check that the extractor has been executed in buildless mode
|
||||||
attempt = BuildScript.Bind(
|
attempt = BuildScript.Bind(
|
||||||
AddBuildlessStartedDiagnostic() & new StandaloneBuildRule().Analyse(this, false),
|
AddBuildlessWronglyConfiguredWarning() & AddBuildlessStartedDiagnostic() & new StandaloneBuildRule().Analyse(this, false),
|
||||||
AddBuildlessEndedDiagnostic);
|
AddBuildlessEndedDiagnostic);
|
||||||
break;
|
break;
|
||||||
case CSharpBuildStrategy.Auto:
|
case CSharpBuildStrategy.Auto:
|
||||||
@@ -81,6 +81,27 @@ namespace Semmle.Autobuild.CSharp
|
|||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private BuildScript AddBuildlessWronglyConfiguredWarning()
|
||||||
|
{
|
||||||
|
return BuildScript.Create(actions =>
|
||||||
|
{
|
||||||
|
if (actions.GetEnvironmentVariable(CSharpAutobuildOptions.ExtractorOptionBuildless) is null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddDiagnostic(new DiagnosticMessage(
|
||||||
|
Options.Language,
|
||||||
|
"buildless/use-build-mode",
|
||||||
|
"C# was extracted with the deprecated 'buildless' option, use build-mode instead",
|
||||||
|
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
|
||||||
|
markdownMessage: "C# was extracted with the deprecated 'buildless' option, use build-mode instead.",
|
||||||
|
severity: DiagnosticMessage.TspSeverity.Warning
|
||||||
|
));
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private BuildScript AddBuildlessStartedDiagnostic()
|
private BuildScript AddBuildlessStartedDiagnostic()
|
||||||
{
|
{
|
||||||
return BuildScript.Create(actions =>
|
return BuildScript.Create(actions =>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_xunit_test(
|
|||||||
name = "Semmle.Autobuild.Cpp.Tests",
|
name = "Semmle.Autobuild.Cpp.Tests",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
deps = [
|
deps = [
|
||||||
"//csharp/autobuilder/Semmle.Autobuild.Cpp:bin/Semmle.Autobuild.Cpp",
|
"//csharp/autobuilder/Semmle.Autobuild.Cpp:bin/Semmle.Autobuild.Cpp",
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ codeql_csharp_binary(
|
|||||||
name = "Semmle.Autobuild.Cpp",
|
name = "Semmle.Autobuild.Cpp",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
language_prefix = "cpp",
|
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//csharp/autobuilder/Semmle.Autobuild.Shared",
|
"//csharp/autobuilder/Semmle.Autobuild.Shared",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_library(
|
|||||||
name = "Semmle.Autobuild.Shared",
|
name = "Semmle.Autobuild.Shared",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -4,41 +4,41 @@ Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,,,,,
|
|||||||
Dapper,55,42,1,,,,,,,,,,55,,42,,,,,,,,1
|
Dapper,55,42,1,,,,,,,,,,55,,42,,,,,,,,1
|
||||||
ILCompiler,,,81,,,,,,,,,,,,,,,,,,,81,
|
ILCompiler,,,81,,,,,,,,,,,,,,,,,,,81,
|
||||||
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,,,,,63,
|
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,,,,,63,
|
||||||
ILLink.Shared,,,32,,,,,,,,,,,,,,,,,,,29,3
|
ILLink.Shared,,,32,,,,,,,,,,,,,,,,,,,30,2
|
||||||
ILLink.Tasks,,,3,,,,,,,,,,,,,,,,,,,3,
|
ILLink.Tasks,,,3,,,,,,,,,,,,,,,,,,,3,
|
||||||
Internal.IL,,,69,,,,,,,,,,,,,,,,,,,67,2
|
Internal.IL,,,46,,,,,,,,,,,,,,,,,,,44,2
|
||||||
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,,,8,1
|
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,,,8,1
|
||||||
Internal.TypeSystem,,,367,,,,,,,,,,,,,,,,,,,331,36
|
Internal.TypeSystem,,,291,,,,,,,,,,,,,,,,,,,275,16
|
||||||
JsonToItemsTaskFactory,,,5,,,,,,,,,,,,,,,,,,,5,
|
JsonToItemsTaskFactory,,,5,,,,,,,,,,,,,,,,,,,5,
|
||||||
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,,,,,14,
|
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,,,,,14,
|
||||||
Microsoft.Apple.Build,,,5,,,,,,,,,,,,,,,,,,,5,
|
Microsoft.Apple.Build,,,5,,,,,,,,,,,,,,,,,,,5,
|
||||||
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,,,
|
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,,,
|
||||||
Microsoft.CSharp,,,24,,,,,,,,,,,,,,,,,,,24,
|
Microsoft.CSharp,,,10,,,,,,,,,,,,,,,,,,,10,
|
||||||
Microsoft.Diagnostics.Tools.Pgo,,,13,,,,,,,,,,,,,,,,,,,13,
|
Microsoft.Diagnostics.Tools.Pgo,,,12,,,,,,,,,,,,,,,,,,,12,
|
||||||
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,,,12
|
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,,,12
|
||||||
Microsoft.Extensions.Caching.Distributed,,,9,,,,,,,,,,,,,,,,,,,9,
|
Microsoft.Extensions.Caching.Distributed,,,9,,,,,,,,,,,,,,,,,,,9,
|
||||||
Microsoft.Extensions.Caching.Memory,,,30,,,,,,,,,,,,,,,,,,,29,1
|
Microsoft.Extensions.Caching.Memory,,,30,,,,,,,,,,,,,,,,,,,29,1
|
||||||
Microsoft.Extensions.Configuration,,2,83,,,,,,,,,,,,,2,,,,,,81,2
|
Microsoft.Extensions.Configuration,,2,77,,,,,,,,,,,,,2,,,,,,76,1
|
||||||
Microsoft.Extensions.DependencyInjection,,,120,,,,,,,,,,,,,,,,,,,120,
|
Microsoft.Extensions.DependencyInjection,,,96,,,,,,,,,,,,,,,,,,,95,1
|
||||||
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,,,,,,12,
|
Microsoft.Extensions.DependencyModel,,,9,,,,,,,,,,,,,,,,,,,9,
|
||||||
Microsoft.Extensions.Diagnostics.Metrics,,,13,,,,,,,,,,,,,,,,,,,13,
|
Microsoft.Extensions.Diagnostics.Metrics,,,15,,,,,,,,,,,,,,,,,,,15,
|
||||||
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,,,,,15,
|
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,,,,,15,
|
||||||
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,,,,,14,2
|
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,,,,,14,2
|
||||||
Microsoft.Extensions.Hosting,,,23,,,,,,,,,,,,,,,,,,,22,1
|
Microsoft.Extensions.Hosting,,,26,,,,,,,,,,,,,,,,,,,25,1
|
||||||
Microsoft.Extensions.Http,,,8,,,,,,,,,,,,,,,,,,,8,
|
Microsoft.Extensions.Http,,,8,,,,,,,,,,,,,,,,,,,8,
|
||||||
Microsoft.Extensions.Logging,,,60,,,,,,,,,,,,,,,,,,,59,1
|
Microsoft.Extensions.Logging,,,53,,,,,,,,,,,,,,,,,,,52,1
|
||||||
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,,,,,8,
|
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,,,,,8,
|
||||||
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,,,,,64,
|
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,,,,,64,
|
||||||
Microsoft.Interop,,,78,,,,,,,,,,,,,,,,,,,78,
|
Microsoft.Interop,,,73,,,,,,,,,,,,,,,,,,,73,
|
||||||
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,,,,,1,
|
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,,,,,1,
|
||||||
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,,,,,7,
|
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,,,,,7,
|
||||||
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,,,,,,5,5
|
Microsoft.VisualBasic,,,6,,,,,,,,,,,,,,,,,,,1,5
|
||||||
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,,,,,3,
|
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,,,,,3,
|
||||||
Microsoft.Win32,,4,4,,,,,,,,,,,,,,,,,,4,4,
|
Microsoft.Win32,,4,4,,,,,,,,,,,,,,,,,,4,4,
|
||||||
Mono.Linker,,,161,,,,,,,,,,,,,,,,,,,161,
|
Mono.Linker,,,158,,,,,,,,,,,,,,,,,,,158,
|
||||||
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,,,
|
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,,,
|
||||||
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,,73,18
|
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,,73,18
|
||||||
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,,7,
|
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,,7,
|
||||||
SourceGenerators,,,4,,,,,,,,,,,,,,,,,,,4,
|
SourceGenerators,,,4,,,,,,,,,,,,,,,,,,,4,
|
||||||
System,59,44,10429,,8,8,1,,,4,5,,33,2,,3,15,17,3,4,,8460,1969
|
System,49,44,9873,,3,3,1,,,4,5,,33,2,,3,15,17,3,4,,7968,1905
|
||||||
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,,
|
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,,
|
||||||
|
|||||||
|
@@ -8,7 +8,7 @@ C# framework & library support
|
|||||||
|
|
||||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
||||||
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
||||||
System,"``System.*``, ``System``",44,10429,59,9
|
System,"``System.*``, ``System``",44,9873,49,9
|
||||||
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",54,1518,148,
|
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",54,1357,148,
|
||||||
Totals,,98,11954,401,9
|
Totals,,98,11237,391,9
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_library(
|
|||||||
name = "Semmle.Extraction.CSharp.DependencyFetching",
|
name = "Semmle.Extraction.CSharp.DependencyFetching",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
"SourceGenerators/**/*.cs",
|
"SourceGenerators/**/*.cs",
|
||||||
]),
|
]),
|
||||||
allow_unsafe_blocks = True,
|
allow_unsafe_blocks = True,
|
||||||
|
|||||||
@@ -97,6 +97,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return envVarPath;
|
return envVarPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
var nugetExesInRepo = fileProvider.NugetExes;
|
var nugetExesInRepo = fileProvider.NugetExes;
|
||||||
if (nugetExesInRepo.Count > 1)
|
if (nugetExesInRepo.Count > 1)
|
||||||
{
|
{
|
||||||
@@ -119,7 +128,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return nugetPath;
|
return nugetPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
throw new Exception("Could not find or download nuget.exe.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string DownloadNugetExe(string sourceDir)
|
private string DownloadNugetExe(string sourceDir)
|
||||||
@@ -136,28 +145,20 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
|
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
logger.LogInfo("Attempting to download nuget.exe");
|
logger.LogInfo("Attempting to download nuget.exe");
|
||||||
try
|
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget);
|
||||||
{
|
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
||||||
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget);
|
return nuget;
|
||||||
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
|
||||||
return nuget;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Download failed.
|
|
||||||
throw new FileNotFoundException("Download of nuget.exe failed.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restore all files in a specified package.
|
/// Restore all packages in the specified packages.config file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="package">The package file.</param>
|
/// <param name="packagesConfig">The packages.config file.</param>
|
||||||
private bool TryRestoreNugetPackage(string package)
|
private bool TryRestoreNugetPackage(string packagesConfig)
|
||||||
{
|
{
|
||||||
logger.LogInfo($"Restoring file {package}...");
|
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
|
||||||
|
|
||||||
/* Use nuget.exe to install a package.
|
/* Use nuget.exe to install a package.
|
||||||
* Note that there is a clutch of NuGet assemblies which could be used to
|
* Note that there is a clutch of NuGet assemblies which could be used to
|
||||||
@@ -169,12 +170,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
if (RunWithMono)
|
if (RunWithMono)
|
||||||
{
|
{
|
||||||
exe = "mono";
|
exe = "mono";
|
||||||
args = $"{nugetExe} install -OutputDirectory {packageDirectory} {package}";
|
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exe = nugetExe!;
|
exe = nugetExe!;
|
||||||
args = $"install -OutputDirectory {packageDirectory} {package}";
|
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
var pi = new ProcessStartInfo(exe, args)
|
var pi = new ProcessStartInfo(exe, args)
|
||||||
@@ -195,7 +196,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInfo($"Restored file {package}");
|
logger.LogInfo($"Restored file \"{packagesConfig}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +206,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int InstallPackages()
|
public int InstallPackages()
|
||||||
{
|
{
|
||||||
return fileProvider.PackagesConfigs.Count(package => TryRestoreNugetPackage(package));
|
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HasNoPackageSource()
|
private bool HasNoPackageSource()
|
||||||
@@ -239,7 +240,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
if (RunWithMono)
|
if (RunWithMono)
|
||||||
{
|
{
|
||||||
exe = "mono";
|
exe = "mono";
|
||||||
args = $"{nugetExe} {command}";
|
args = $"\"{nugetExe}\" {command}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
// Expose internals for testing purposes.
|
|
||||||
[assembly: InternalsVisibleTo("Semmle.Extraction.Tests")]
|
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||||
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
|
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
|
||||||
|
|
||||||
|
<InternalsVisibleTo Include="Semmle.Extraction.Tests" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="..\..\.paket\Paket.Restore.targets" />
|
<Import Project="..\..\.paket\Paket.Restore.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_binary(
|
|||||||
name = "Semmle.Extraction.CSharp.DependencyStubGenerator",
|
name = "Semmle.Extraction.CSharp.DependencyStubGenerator",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
visibility = ["//csharp:__pkg__"],
|
visibility = ["//csharp:__pkg__"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_binary(
|
|||||||
name = "Semmle.Extraction.CSharp.Driver",
|
name = "Semmle.Extraction.CSharp.Driver",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
visibility = ["//csharp:__pkg__"],
|
visibility = ["//csharp:__pkg__"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ codeql_csharp_binary(
|
|||||||
name = "Semmle.Extraction.CSharp.Standalone",
|
name = "Semmle.Extraction.CSharp.Standalone",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"*.cs",
|
"*.cs",
|
||||||
"Properties/*.cs",
|
|
||||||
]),
|
]),
|
||||||
visibility = ["//csharp:__subpackages__"],
|
visibility = ["//csharp:__subpackages__"],
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user