mirror of
https://github.com/github/codeql.git
synced 2026-07-07 20:45:28 +02:00
Compare commits
2 Commits
codeql-cli
...
edoardo/tr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb31cacd9e | ||
|
|
2e1c394946 |
2
.github/actions/fetch-codeql/action.yml
vendored
2
.github/actions/fetch-codeql/action.yml
vendored
@@ -7,7 +7,7 @@ runs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
gh extension install github/gh-codeql
|
gh extension install github/gh-codeql
|
||||||
gh codeql set-channel nightly
|
gh codeql set-channel release
|
||||||
gh codeql version
|
gh codeql version
|
||||||
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"
|
gh codeql version --format=json | jq -r .unpackedLocation >> "${GITHUB_PATH}"
|
||||||
env:
|
env:
|
||||||
|
|||||||
1
.github/labeler.yml
vendored
1
.github/labeler.yml
vendored
@@ -42,4 +42,3 @@ documentation:
|
|||||||
|
|
||||||
"QL-for-QL":
|
"QL-for-QL":
|
||||||
- ql/**/*
|
- ql/**/*
|
||||||
- .github/workflows/ql-for-ql*
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
uses: ./script/.github/actions/fetch-codeql
|
uses: ./.github/actions/fetch-codeql
|
||||||
- name: Build modeled package list
|
- name: Build modeled package list
|
||||||
run: |
|
run: |
|
||||||
python script/misc/scripts/library-coverage/generate-timeseries.py codeqlModels
|
python script/misc/scripts/library-coverage/generate-timeseries.py codeqlModels
|
||||||
|
|||||||
2
.github/workflows/csv-coverage-update.yml
vendored
2
.github/workflows/csv-coverage-update.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
uses: ./ql/.github/actions/fetch-codeql
|
uses: ./.github/actions/fetch-codeql
|
||||||
- name: Generate coverage files
|
- name: Generate coverage files
|
||||||
run: |
|
run: |
|
||||||
python ql/misc/scripts/library-coverage/generate-report.py ci ql ql
|
python ql/misc/scripts/library-coverage/generate-report.py ci ql ql
|
||||||
|
|||||||
2
.github/workflows/csv-coverage.yml
vendored
2
.github/workflows/csv-coverage.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Download CodeQL CLI
|
- name: Download CodeQL CLI
|
||||||
uses: ./script/.github/actions/fetch-codeql
|
uses: ./.github/actions/fetch-codeql
|
||||||
- name: Build modeled package list
|
- name: Build modeled package list
|
||||||
run: |
|
run: |
|
||||||
python script/misc/scripts/library-coverage/generate-report.py ci codeqlModels script
|
python script/misc/scripts/library-coverage/generate-report.py ci codeqlModels script
|
||||||
|
|||||||
12
.github/workflows/go-tests.yml
vendored
12
.github/workflows/go-tests.yml
vendored
@@ -11,10 +11,10 @@ jobs:
|
|||||||
name: Test Linux (Ubuntu)
|
name: Test Linux (Ubuntu)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.19
|
- name: Set up Go 1.18.1
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: 1.18.1
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
@@ -57,10 +57,10 @@ jobs:
|
|||||||
name: Test MacOS
|
name: Test MacOS
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.19
|
- name: Set up Go 1.18.1
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: 1.18.1
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
@@ -87,10 +87,10 @@ jobs:
|
|||||||
name: Test Windows
|
name: Test Windows
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.19
|
- name: Set up Go 1.18.1
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: 1.18.1
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
|
|||||||
117
.github/workflows/ql-for-ql-build.yml
vendored
117
.github/workflows/ql-for-ql-build.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
|
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- name: Get CodeQL version
|
- name: Get CodeQL version
|
||||||
@@ -27,37 +27,30 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
- name: Cache entire pack
|
|
||||||
id: cache-pack
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ runner.temp }}/pack
|
|
||||||
key: ${{ runner.os }}-pack-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
|
|
||||||
- name: Cache queries
|
- name: Cache queries
|
||||||
if: steps.cache-pack.outputs.cache-hit != 'true'
|
|
||||||
id: cache-queries
|
id: cache-queries
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/queries
|
path: ${{ runner.temp }}/query-pack.zip
|
||||||
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
|
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}
|
||||||
- name: Build query pack
|
- name: Build query pack
|
||||||
if: steps.cache-queries.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-queries.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
cd ql/ql/src
|
cd ql/ql/src
|
||||||
"${CODEQL}" pack create -j 16
|
"${CODEQL}" pack create
|
||||||
mv .codeql/pack/codeql/ql/0.0.0 ${{ runner.temp }}/queries
|
cd .codeql/pack/codeql/ql/0.0.0
|
||||||
env:
|
zip "${PACKZIP}" -r .
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
|
||||||
- name: Move cache queries to pack
|
|
||||||
if: steps.cache-pack.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cp -r ${{ runner.temp }}/queries ${{ runner.temp }}/pack
|
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
|
PACKZIP: ${{ runner.temp }}/query-pack.zip
|
||||||
|
- name: Upload query pack
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: query-pack-zip
|
||||||
|
path: ${{ runner.temp }}/query-pack.zip
|
||||||
|
|
||||||
### Build the extractor ###
|
### Build the extractor ###
|
||||||
- name: Cache entire extractor
|
- name: Cache entire extractor
|
||||||
if: steps.cache-pack.outputs.cache-hit != 'true'
|
|
||||||
id: cache-extractor
|
id: cache-extractor
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
@@ -68,7 +61,7 @@ jobs:
|
|||||||
ql/target/release/ql-extractor.exe
|
ql/target/release/ql-extractor.exe
|
||||||
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
|
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||||
- name: Cache cargo
|
- name: Cache cargo
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -77,35 +70,72 @@ jobs:
|
|||||||
ql/target
|
ql/target
|
||||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: cd ql; cargo fmt --all -- --check
|
run: cd ql; cargo fmt --all -- --check
|
||||||
- name: Build
|
- name: Build
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: cd ql; cargo build --verbose
|
run: cd ql; cargo build --verbose
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: cd ql; cargo test --verbose
|
run: cd ql; cargo test --verbose
|
||||||
- name: Release build
|
- name: Release build
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: cd ql; cargo build --release
|
run: cd ql; cargo build --release
|
||||||
- name: Generate dbscheme
|
- name: Generate dbscheme
|
||||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
|
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||||
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
|
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: extractor-ubuntu-latest
|
||||||
|
path: |
|
||||||
|
ql/target/release/ql-autobuilder
|
||||||
|
ql/target/release/ql-autobuilder.exe
|
||||||
|
ql/target/release/ql-extractor
|
||||||
|
ql/target/release/ql-extractor.exe
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
### Package the queries and extractor ###
|
### Package the queries and extractor ###
|
||||||
- name: Package pack
|
- uses: actions/download-artifact@v3
|
||||||
if: steps.cache-pack.outputs.cache-hit != 'true'
|
with:
|
||||||
run: |
|
name: query-pack-zip
|
||||||
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats ${PACK}/
|
path: query-pack-zip
|
||||||
mkdir -p ${PACK}/tools/linux64
|
- uses: actions/download-artifact@v3
|
||||||
cp ql/target/release/ql-autobuilder ${PACK}/tools/linux64/autobuilder
|
with:
|
||||||
cp ql/target/release/ql-extractor ${PACK}/tools/linux64/extractor
|
name: extractor-ubuntu-latest
|
||||||
chmod +x ${PACK}/tools/linux64/autobuilder
|
path: linux64
|
||||||
chmod +x ${PACK}/tools/linux64/extractor
|
- run: |
|
||||||
env:
|
unzip query-pack-zip/*.zip -d pack
|
||||||
PACK: ${{ runner.temp }}/pack
|
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
|
||||||
|
mkdir -p pack/tools/linux64
|
||||||
|
if [[ -f linux64/ql-autobuilder ]]; then
|
||||||
|
cp linux64/ql-autobuilder pack/tools/linux64/autobuilder
|
||||||
|
chmod +x pack/tools/linux64/autobuilder
|
||||||
|
fi
|
||||||
|
if [[ -f linux64/ql-extractor ]]; then
|
||||||
|
cp linux64/ql-extractor pack/tools/linux64/extractor
|
||||||
|
chmod +x pack/tools/linux64/extractor
|
||||||
|
fi
|
||||||
|
cd pack
|
||||||
|
zip -rq ../codeql-ql.zip .
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: codeql-ql-pack
|
||||||
|
path: codeql-ql.zip
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
### Run the analysis ###
|
### Run the analysis ###
|
||||||
|
- name: Download pack
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: codeql-ql-pack
|
||||||
|
path: ${{ runner.temp }}/codeql-ql-pack-artifact
|
||||||
|
|
||||||
|
- name: Prepare pack
|
||||||
|
run: |
|
||||||
|
unzip "${PACK_ARTIFACT}/*.zip" -d "${PACK}"
|
||||||
|
env:
|
||||||
|
PACK_ARTIFACT: ${{ runner.temp }}/codeql-ql-pack-artifact
|
||||||
|
PACK: ${{ runner.temp }}/pack
|
||||||
- name: Hack codeql-action options
|
- name: Hack codeql-action options
|
||||||
run: |
|
run: |
|
||||||
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||||
@@ -119,26 +149,21 @@ jobs:
|
|||||||
echo " - ql/ql/test" >> ${CONF}
|
echo " - ql/ql/test" >> ${CONF}
|
||||||
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
|
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
|
||||||
echo "disable-default-queries: true" >> ${CONF}
|
echo "disable-default-queries: true" >> ${CONF}
|
||||||
echo "queries:" >> ${CONF}
|
echo "packs:" >> ${CONF}
|
||||||
echo " - uses: ./ql/ql/src/codeql-suites/ql-code-scanning.qls" >> ${CONF}
|
echo " - codeql/ql" >> ${CONF}
|
||||||
echo "Config file: "
|
echo "Config file: "
|
||||||
cat ${CONF}
|
cat ${CONF}
|
||||||
env:
|
env:
|
||||||
CONF: ./ql-for-ql-config.yml
|
CONF: ./ql-for-ql-config.yml
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
|
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||||
with:
|
with:
|
||||||
languages: ql
|
languages: ql
|
||||||
db-location: ${{ runner.temp }}/db
|
db-location: ${{ runner.temp }}/db
|
||||||
config-file: ./ql-for-ql-config.yml
|
config-file: ./ql-for-ql-config.yml
|
||||||
- name: Move pack cache
|
|
||||||
run: |
|
|
||||||
cp -r ${PACK}/.cache ql/ql/src/.cache
|
|
||||||
env:
|
|
||||||
PACK: ${{ runner.temp }}/pack
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
|
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||||
with:
|
with:
|
||||||
category: "ql-for-ql"
|
category: "ql-for-ql"
|
||||||
- name: Copy sarif file to CWD
|
- name: Copy sarif file to CWD
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
|
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
|
|||||||
4
.github/workflows/ql-for-ql-tests.yml
vendored
4
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
|
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
- name: Check QL formatting
|
- name: Check QL formatting
|
||||||
run: |
|
run: |
|
||||||
find ql/ql/src "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
|
find ql/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
|
||||||
env:
|
env:
|
||||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||||
- name: Check QL compilation
|
- name: Check QL compilation
|
||||||
|
|||||||
@@ -392,8 +392,7 @@
|
|||||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||||
"go/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
"go/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||||
"swift/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
|
||||||
],
|
],
|
||||||
"C++ ExternalAPIs": [
|
"C++ ExternalAPIs": [
|
||||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||||
@@ -485,39 +484,28 @@
|
|||||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll"
|
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll"
|
||||||
],
|
],
|
||||||
"ReDoS Util Python/JS/Ruby/Java": [
|
"ReDoS Util Python/JS/Ruby/Java": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll",
|
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
|
||||||
"python/ql/lib/semmle/python/security/regexp/NfaUtils.qll",
|
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll",
|
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll",
|
||||||
"java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll"
|
"java/ql/lib/semmle/code/java/security/performance/ReDoSUtil.qll"
|
||||||
],
|
],
|
||||||
"ReDoS Exponential Python/JS/Ruby/Java": [
|
"ReDoS Exponential Python/JS/Ruby/Java": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll",
|
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",
|
||||||
"python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll",
|
"python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll",
|
"ruby/ql/lib/codeql/ruby/security/performance/ExponentialBackTracking.qll",
|
||||||
"java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll"
|
"java/ql/lib/semmle/code/java/security/performance/ExponentialBackTracking.qll"
|
||||||
],
|
],
|
||||||
"ReDoS Polynomial Python/JS/Ruby/Java": [
|
"ReDoS Polynomial Python/JS/Ruby/Java": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/regexp/SuperlinearBackTracking.qll",
|
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
|
||||||
"python/ql/lib/semmle/python/security/regexp/SuperlinearBackTracking.qll",
|
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/security/regexp/SuperlinearBackTracking.qll",
|
"ruby/ql/lib/codeql/ruby/security/performance/SuperlinearBackTracking.qll",
|
||||||
"java/ql/lib/semmle/code/java/security/regexp/SuperlinearBackTracking.qll"
|
"java/ql/lib/semmle/code/java/security/performance/SuperlinearBackTracking.qll"
|
||||||
],
|
|
||||||
"RegexpMatching Python/JS/Ruby": [
|
|
||||||
"javascript/ql/lib/semmle/javascript/security/regexp/RegexpMatching.qll",
|
|
||||||
"python/ql/lib/semmle/python/security/regexp/RegexpMatching.qll",
|
|
||||||
"ruby/ql/lib/codeql/ruby/security/regexp/RegexpMatching.qll"
|
|
||||||
],
|
],
|
||||||
"BadTagFilterQuery Python/JS/Ruby": [
|
"BadTagFilterQuery Python/JS/Ruby": [
|
||||||
"javascript/ql/lib/semmle/javascript/security/BadTagFilterQuery.qll",
|
"javascript/ql/lib/semmle/javascript/security/BadTagFilterQuery.qll",
|
||||||
"python/ql/lib/semmle/python/security/BadTagFilterQuery.qll",
|
"python/ql/lib/semmle/python/security/BadTagFilterQuery.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/security/BadTagFilterQuery.qll"
|
"ruby/ql/lib/codeql/ruby/security/BadTagFilterQuery.qll"
|
||||||
],
|
],
|
||||||
"OverlyLargeRange Python/JS/Ruby/Java": [
|
|
||||||
"javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll",
|
|
||||||
"python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll",
|
|
||||||
"ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll",
|
|
||||||
"java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll"
|
|
||||||
],
|
|
||||||
"CFG": [
|
"CFG": [
|
||||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll",
|
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||||
@@ -597,9 +585,5 @@
|
|||||||
"Swift patterns test file": [
|
"Swift patterns test file": [
|
||||||
"swift/ql/test/extractor-tests/patterns/patterns.swift",
|
"swift/ql/test/extractor-tests/patterns/patterns.swift",
|
||||||
"swift/ql/test/library-tests/parent/patterns.swift"
|
"swift/ql/test/library-tests/parent/patterns.swift"
|
||||||
],
|
|
||||||
"IncompleteMultiCharacterSanitization JS/Ruby": [
|
|
||||||
"javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll",
|
|
||||||
"ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
class AttributeArgument extends @attribute_arg {
|
|
||||||
string toString() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
class Attribute extends @attribute {
|
|
||||||
string toString() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
class LocationDefault extends @location_default {
|
|
||||||
string toString() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
from AttributeArgument arg, int kind, Attribute attr, int index, LocationDefault location
|
|
||||||
where
|
|
||||||
attribute_args(arg, kind, attr, index, location) and
|
|
||||||
not arg instanceof @attribute_arg_constant_expr
|
|
||||||
select arg, kind, attr, index, location
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
|||||||
description: Support all constant attribute arguments
|
|
||||||
compatibility: backwards
|
|
||||||
attribute_arg_constant.rel: delete
|
|
||||||
attribute_args.rel: run attribute_args.qlo
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
class Expr extends @expr {
|
|
||||||
string toString() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
class Location extends @location_expr {
|
|
||||||
string toString() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
from Expr expr, int kind, int kind_new, Location location
|
|
||||||
where
|
|
||||||
exprs(expr, kind, location) and
|
|
||||||
if expr instanceof @blockassignexpr then kind_new = 0 else kind_new = kind
|
|
||||||
select expr, kind_new, location
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
|||||||
description: Support block assignment
|
|
||||||
compatibility: partial
|
|
||||||
exprs.rel: run exprs.qlo
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
|||||||
description: Add relation for orphaned local variables
|
|
||||||
compatibility: full
|
|
||||||
orphaned_variables.rel: delete
|
|
||||||
@@ -1,37 +1,3 @@
|
|||||||
## 0.3.4
|
|
||||||
|
|
||||||
### Deprecated APIs
|
|
||||||
|
|
||||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
|
||||||
The old name still exists as a deprecated alias.
|
|
||||||
|
|
||||||
### New Features
|
|
||||||
|
|
||||||
* Added support for getting the link targets of global and namespace variables.
|
|
||||||
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
|
||||||
|
|
||||||
## 0.3.3
|
|
||||||
|
|
||||||
### New Features
|
|
||||||
|
|
||||||
* Added a predicate `getValueConstant` to `AttributeArgument` that yields the argument value as an `Expr` when the value is a constant expression.
|
|
||||||
* A new class predicate `MustFlowConfiguration::allowInterproceduralFlow` has been added to the `semmle.code.cpp.ir.dataflow.MustFlow` library. The new predicate can be overridden to disable interprocedural flow.
|
|
||||||
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.
|
|
||||||
|
|
||||||
### Major Analysis Improvements
|
|
||||||
|
|
||||||
* The IR dataflow library now includes flow through global variables. This enables new findings in many scenarios.
|
|
||||||
|
|
||||||
## 0.3.2
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.
|
|
||||||
|
|
||||||
## 0.3.1
|
## 0.3.1
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
## 0.3.2
|
---
|
||||||
|
category: fix
|
||||||
### Bug Fixes
|
---
|
||||||
|
|
||||||
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.
|
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: feature
|
||||||
|
---
|
||||||
|
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
## 0.3.3
|
|
||||||
|
|
||||||
### New Features
|
|
||||||
|
|
||||||
* Added a predicate `getValueConstant` to `AttributeArgument` that yields the argument value as an `Expr` when the value is a constant expression.
|
|
||||||
* A new class predicate `MustFlowConfiguration::allowInterproceduralFlow` has been added to the `semmle.code.cpp.ir.dataflow.MustFlow` library. The new predicate can be overridden to disable interprocedural flow.
|
|
||||||
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.
|
|
||||||
|
|
||||||
### Major Analysis Improvements
|
|
||||||
|
|
||||||
* The IR dataflow library now includes flow through global variables. This enables new findings in many scenarios.
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
## 0.3.4
|
|
||||||
|
|
||||||
### Deprecated APIs
|
|
||||||
|
|
||||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
|
||||||
The old name still exists as a deprecated alias.
|
|
||||||
|
|
||||||
### New Features
|
|
||||||
|
|
||||||
* Added support for getting the link targets of global and namespace variables.
|
|
||||||
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.3.4
|
lastReleaseVersion: 0.3.1
|
||||||
|
|||||||
@@ -119,67 +119,27 @@ module SemanticExprConfig {
|
|||||||
result = block.getDisplayIndex()
|
result = block.getDisplayIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
newtype TSsaVariable =
|
class SsaVariable instanceof IR::Instruction {
|
||||||
TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or
|
SsaVariable() { super.hasMemoryResult() }
|
||||||
TSsaOperand(IR::Operand op) { op.isDefinitionInexact() }
|
|
||||||
|
|
||||||
class SsaVariable extends TSsaVariable {
|
final string toString() { result = super.toString() }
|
||||||
string toString() { none() }
|
|
||||||
|
|
||||||
Location getLocation() { none() }
|
final Location getLocation() { result = super.getLocation() }
|
||||||
|
|
||||||
IR::Instruction asInstruction() { none() }
|
|
||||||
|
|
||||||
IR::Operand asOperand() { none() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SsaInstructionVariable extends SsaVariable, TSsaInstruction {
|
predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { v = sourceExpr }
|
||||||
IR::Instruction instr;
|
|
||||||
|
|
||||||
SsaInstructionVariable() { this = TSsaInstruction(instr) }
|
predicate phi(SsaVariable v) { v instanceof IR::PhiInstruction }
|
||||||
|
|
||||||
final override string toString() { result = instr.toString() }
|
SsaVariable getAPhiInput(SsaVariable v) { result = v.(IR::PhiInstruction).getAnInput() }
|
||||||
|
|
||||||
final override Location getLocation() { result = instr.getLocation() }
|
Expr getAUse(SsaVariable v) { result.(IR::LoadInstruction).getSourceValue() = v }
|
||||||
|
|
||||||
final override IR::Instruction asInstruction() { result = instr }
|
|
||||||
}
|
|
||||||
|
|
||||||
class SsaOperand extends SsaVariable, TSsaOperand {
|
|
||||||
IR::Operand op;
|
|
||||||
|
|
||||||
SsaOperand() { this = TSsaOperand(op) }
|
|
||||||
|
|
||||||
final override string toString() { result = op.toString() }
|
|
||||||
|
|
||||||
final override Location getLocation() { result = op.getLocation() }
|
|
||||||
|
|
||||||
final override IR::Operand asOperand() { result = op }
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { v.asInstruction() = sourceExpr }
|
|
||||||
|
|
||||||
predicate phi(SsaVariable v) { v.asInstruction() instanceof IR::PhiInstruction }
|
|
||||||
|
|
||||||
SsaVariable getAPhiInput(SsaVariable v) {
|
|
||||||
exists(IR::PhiInstruction instr |
|
|
||||||
result.asInstruction() = instr.getAnInput()
|
|
||||||
or
|
|
||||||
result.asOperand() = instr.getAnInputOperand()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr getAUse(SsaVariable v) { result.(IR::LoadInstruction).getSourceValue() = v.asInstruction() }
|
|
||||||
|
|
||||||
SemType getSsaVariableType(SsaVariable v) {
|
SemType getSsaVariableType(SsaVariable v) {
|
||||||
result = getSemanticType(v.asInstruction().getResultIRType())
|
result = getSemanticType(v.(IR::Instruction).getResultIRType())
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicBlock getSsaVariableBasicBlock(SsaVariable v) {
|
BasicBlock getSsaVariableBasicBlock(SsaVariable v) { result = v.(IR::Instruction).getBlock() }
|
||||||
result = v.asInstruction().getBlock()
|
|
||||||
or
|
|
||||||
result = v.asOperand().getUse().getBlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TReadPosition =
|
private newtype TReadPosition =
|
||||||
TReadPositionBlock(IR::IRBlock block) or
|
TReadPositionBlock(IR::IRBlock block) or
|
||||||
@@ -209,9 +169,7 @@ module SemanticExprConfig {
|
|||||||
|
|
||||||
final override predicate hasRead(SsaVariable v) {
|
final override predicate hasRead(SsaVariable v) {
|
||||||
exists(IR::Operand operand |
|
exists(IR::Operand operand |
|
||||||
operand.getDef() = v.asInstruction() and
|
operand.getDef() = v and not operand instanceof IR::PhiInputOperand
|
||||||
not operand instanceof IR::PhiInputOperand and
|
|
||||||
operand.getUse().getBlock() = block
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,7 +186,7 @@ module SemanticExprConfig {
|
|||||||
|
|
||||||
final override predicate hasRead(SsaVariable v) {
|
final override predicate hasRead(SsaVariable v) {
|
||||||
exists(IR::PhiInputOperand operand |
|
exists(IR::PhiInputOperand operand |
|
||||||
operand.getDef() = v.asInstruction() and
|
operand.getDef() = v and
|
||||||
operand.getPredecessorBlock() = pred and
|
operand.getPredecessorBlock() = pred and
|
||||||
operand.getUse().getBlock() = succ
|
operand.getUse().getBlock() = succ
|
||||||
)
|
)
|
||||||
@@ -247,16 +205,17 @@ module SemanticExprConfig {
|
|||||||
exists(IR::PhiInputOperand operand |
|
exists(IR::PhiInputOperand operand |
|
||||||
pos = TReadPositionPhiInputEdge(operand.getPredecessorBlock(), operand.getUse().getBlock())
|
pos = TReadPositionPhiInputEdge(operand.getPredecessorBlock(), operand.getUse().getBlock())
|
||||||
|
|
|
|
||||||
phi.asInstruction() = operand.getUse() and
|
phi = operand.getUse() and input = operand.getDef()
|
||||||
(
|
|
||||||
input.asInstruction() = operand.getDef()
|
|
||||||
or
|
|
||||||
input.asOperand() = operand
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bound instanceof IRBound::Bound {
|
class Bound instanceof IRBound::Bound {
|
||||||
|
Bound() {
|
||||||
|
this instanceof IRBound::ZeroBound
|
||||||
|
or
|
||||||
|
this.(IRBound::ValueNumberBound).getValueNumber().getAnInstruction() instanceof SsaVariable
|
||||||
|
}
|
||||||
|
|
||||||
string toString() { result = super.toString() }
|
string toString() { result = super.toString() }
|
||||||
|
|
||||||
final Location getLocation() { result = super.getLocation() }
|
final Location getLocation() { result = super.getLocation() }
|
||||||
@@ -269,13 +228,13 @@ module SemanticExprConfig {
|
|||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
result =
|
result =
|
||||||
min(SsaVariable v |
|
min(SsaVariable instr |
|
||||||
v.asInstruction() = bound.getValueNumber().getAnInstruction()
|
instr = bound.getValueNumber().getAnInstruction()
|
||||||
|
|
|
|
||||||
v
|
instr
|
||||||
order by
|
order by
|
||||||
v.asInstruction().getBlock().getDisplayIndex(),
|
instr.(IR::Instruction).getBlock().getDisplayIndex(),
|
||||||
v.asInstruction().getDisplayIndexInBlock()
|
instr.(IR::Instruction).getDisplayIndexInBlock()
|
||||||
).toString()
|
).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +242,7 @@ module SemanticExprConfig {
|
|||||||
predicate zeroBound(Bound bound) { bound instanceof IRBound::ZeroBound }
|
predicate zeroBound(Bound bound) { bound instanceof IRBound::ZeroBound }
|
||||||
|
|
||||||
predicate ssaBound(Bound bound, SsaVariable v) {
|
predicate ssaBound(Bound bound, SsaVariable v) {
|
||||||
v.asInstruction() = bound.(IRBound::ValueNumberBound).getValueNumber().getAnInstruction()
|
v = bound.(IRBound::ValueNumberBound).getValueNumber().getAnInstruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr getBoundExpr(Bound bound, int delta) {
|
Expr getBoundExpr(Bound bound, int delta) {
|
||||||
@@ -292,20 +251,22 @@ module SemanticExprConfig {
|
|||||||
|
|
||||||
class Guard = IRGuards::IRGuardCondition;
|
class Guard = IRGuards::IRGuardCondition;
|
||||||
|
|
||||||
predicate guard(Guard guard, BasicBlock block) { block = guard.getBlock() }
|
predicate guard(Guard guard, BasicBlock block) {
|
||||||
|
block = guard.(IRGuards::IRGuardCondition).getBlock()
|
||||||
|
}
|
||||||
|
|
||||||
Expr getGuardAsExpr(Guard guard) { result = guard }
|
Expr getGuardAsExpr(Guard guard) { result = guard }
|
||||||
|
|
||||||
predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) {
|
predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) {
|
||||||
guard.comparesEq(e1.getAUse(), e2.getAUse(), 0, true, polarity)
|
guard.(IRGuards::IRGuardCondition).comparesEq(e1.getAUse(), e2.getAUse(), 0, true, polarity)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock controlled, boolean branch) {
|
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock controlled, boolean branch) {
|
||||||
guard.controls(controlled, branch)
|
guard.(IRGuards::IRGuardCondition).controls(controlled, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate guardHasBranchEdge(Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
predicate guardHasBranchEdge(Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||||
guard.controlsEdge(bb1, bb2, branch)
|
guard.(IRGuards::IRGuardCondition).controlsEdge(bb1, bb2, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
Guard comparisonGuard(Expr e) { result = e }
|
Guard comparisonGuard(Expr e) { result = e }
|
||||||
@@ -323,13 +284,9 @@ SemBasicBlock getSemanticBasicBlock(IR::IRBlock block) { result = block }
|
|||||||
|
|
||||||
IR::IRBlock getCppBasicBlock(SemBasicBlock block) { block = result }
|
IR::IRBlock getCppBasicBlock(SemBasicBlock block) { block = result }
|
||||||
|
|
||||||
SemSsaVariable getSemanticSsaVariable(IR::Instruction instr) {
|
SemSsaVariable getSemanticSsaVariable(IR::Instruction instr) { result = instr }
|
||||||
result.(SemanticExprConfig::SsaVariable).asInstruction() = instr
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::Instruction getCppSsaVariableInstruction(SemSsaVariable var) {
|
IR::Instruction getCppSsaVariableInstruction(SemSsaVariable v) { v = result }
|
||||||
var.(SemanticExprConfig::SsaVariable).asInstruction() = result
|
|
||||||
}
|
|
||||||
|
|
||||||
SemBound getSemanticBound(IRBound::Bound bound) { result = bound }
|
SemBound getSemanticBound(IRBound::Bound bound) { result = bound }
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,6 @@ private predicate phiModulusInit(SemSsaPhiNode phi, SemBound b, int val, int mod
|
|||||||
/**
|
/**
|
||||||
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
|
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
|
||||||
private predicate phiModulusRankStep(SemSsaPhiNode phi, SemBound b, int val, int mod, int rix) {
|
private predicate phiModulusRankStep(SemSsaPhiNode phi, SemBound b, int val, int mod, int rix) {
|
||||||
rix = 0 and
|
rix = 0 and
|
||||||
phiModulusInit(phi, b, val, mod)
|
phiModulusInit(phi, b, val, mod)
|
||||||
@@ -170,7 +169,7 @@ private predicate phiModulusRankStep(SemSsaPhiNode phi, SemBound b, int val, int
|
|||||||
val = remainder(v1, mod)
|
val = remainder(v1, mod)
|
||||||
|
|
|
|
||||||
exists(int v2, int m2 |
|
exists(int v2, int m2 |
|
||||||
rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
|
rankedPhiInput(phi, inp, edge, rix) and
|
||||||
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
||||||
ssaModulus(inp, edge, b, v2, m2) and
|
ssaModulus(inp, edge, b, v2, m2) and
|
||||||
mod = m1.gcd(m2).gcd(v1 - v2)
|
mod = m1.gcd(m2).gcd(v1 - v2)
|
||||||
|
|||||||
@@ -342,10 +342,7 @@ private class ConvertOrBoxExpr extends SemUnaryExpr {
|
|||||||
* A cast that can be ignored for the purpose of range analysis.
|
* A cast that can be ignored for the purpose of range analysis.
|
||||||
*/
|
*/
|
||||||
private class SafeCastExpr extends ConvertOrBoxExpr {
|
private class SafeCastExpr extends ConvertOrBoxExpr {
|
||||||
SafeCastExpr() {
|
SafeCastExpr() { conversionCannotOverflow(getTrackedType(getOperand()), getTrackedType(this)) }
|
||||||
conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())),
|
|
||||||
getTrackedType(this))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -189,12 +189,9 @@ private class BinarySignExpr extends FlowSignExpr {
|
|||||||
BinarySignExpr() { binary = this }
|
BinarySignExpr() { binary = this }
|
||||||
|
|
||||||
override Sign getSignRestriction() {
|
override Sign getSignRestriction() {
|
||||||
exists(SemExpr left, SemExpr right |
|
result =
|
||||||
binaryExprOperands(binary, left, right) and
|
semExprSign(binary.getLeftOperand())
|
||||||
result =
|
.applyBinaryOp(semExprSign(binary.getRightOperand()), binary.getOpcode())
|
||||||
semExprSign(pragma[only_bind_out](left))
|
|
||||||
.applyBinaryOp(semExprSign(pragma[only_bind_out](right)), binary.getOpcode())
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
exists(SemDivExpr div | div = binary |
|
exists(SemDivExpr div | div = binary |
|
||||||
result = semExprSign(div.getLeftOperand()) and
|
result = semExprSign(div.getLeftOperand()) and
|
||||||
@@ -204,10 +201,6 @@ private class BinarySignExpr extends FlowSignExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) {
|
|
||||||
binary.getLeftOperand() = left and binary.getRightOperand() = right
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `Convert`, `Box`, or `Unbox` expression.
|
* A `Convert`, `Box`, or `Unbox` expression.
|
||||||
*/
|
*/
|
||||||
@@ -228,7 +221,7 @@ private class UnarySignExpr extends FlowSignExpr {
|
|||||||
UnarySignExpr() { unary = this and not this instanceof SemCastExpr }
|
UnarySignExpr() { unary = this and not this instanceof SemCastExpr }
|
||||||
|
|
||||||
override Sign getSignRestriction() {
|
override Sign getSignRestriction() {
|
||||||
result = semExprSign(pragma[only_bind_out](unary.getOperand())).applyUnaryOp(unary.getOpcode())
|
result = semExprSign(unary.getOperand()).applyUnaryOp(unary.getOpcode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 0.3.4
|
version: 0.3.2-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -218,6 +218,8 @@ class Folder extends Container, @folder {
|
|||||||
class File extends Container, @file {
|
class File extends Container, @file {
|
||||||
override string getAbsolutePath() { files(underlyingElement(this), result) }
|
override string getAbsolutePath() { files(underlyingElement(this), result) }
|
||||||
|
|
||||||
|
override string toString() { result = Container.super.toString() }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "File" }
|
override string getAPrimaryQlClass() { result = "File" }
|
||||||
|
|
||||||
override Location getLocation() {
|
override Location getLocation() {
|
||||||
|
|||||||
@@ -41,15 +41,6 @@ class LinkTarget extends @link_target {
|
|||||||
* translation units which contributed to this link target.
|
* translation units which contributed to this link target.
|
||||||
*/
|
*/
|
||||||
Class getAClass() { link_parent(unresolveElement(result), this) }
|
Class getAClass() { link_parent(unresolveElement(result), this) }
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a global or namespace variable which was compiled into this
|
|
||||||
* link target, or had its declaration included by one of the translation
|
|
||||||
* units which contributed to this link target.
|
|
||||||
*/
|
|
||||||
GlobalOrNamespaceVariable getAGlobalOrNamespaceVariable() {
|
|
||||||
link_parent(unresolveElement(result), this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ private import semmle.code.cpp.internal.ResolveClass
|
|||||||
class Specifier extends Element, @specifier {
|
class Specifier extends Element, @specifier {
|
||||||
/** Gets a dummy location for the specifier. */
|
/** Gets a dummy location for the specifier. */
|
||||||
override Location getLocation() {
|
override Location getLocation() {
|
||||||
exists(this) and
|
suppressUnusedThis(this) and
|
||||||
result instanceof UnknownDefaultLocation
|
result instanceof UnknownDefaultLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +256,9 @@ class AttributeArgument extends Element, @attribute_arg {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the text for the value of this argument, if its value is
|
* Gets the text for the value of this argument, if its value is
|
||||||
* a constant or a token.
|
* a string or a number.
|
||||||
*/
|
*/
|
||||||
string getValueText() {
|
string getValueText() { attribute_arg_value(underlyingElement(this), result) }
|
||||||
if underlyingElement(this) instanceof @attribute_arg_constant_expr
|
|
||||||
then result = this.getValueConstant().getValue()
|
|
||||||
else attribute_arg_value(underlyingElement(this), result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of this argument, if its value is integral.
|
* Gets the value of this argument, if its value is integral.
|
||||||
@@ -274,13 +270,6 @@ class AttributeArgument extends Element, @attribute_arg {
|
|||||||
*/
|
*/
|
||||||
Type getValueType() { attribute_arg_type(underlyingElement(this), unresolveElement(result)) }
|
Type getValueType() { attribute_arg_type(underlyingElement(this), unresolveElement(result)) }
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of this argument, if its value is a constant.
|
|
||||||
*/
|
|
||||||
Expr getValueConstant() {
|
|
||||||
attribute_arg_constant(underlyingElement(this), unresolveElement(result))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the attribute to which this is an argument.
|
* Gets the attribute to which this is an argument.
|
||||||
*/
|
*/
|
||||||
@@ -305,12 +294,11 @@ class AttributeArgument extends Element, @attribute_arg {
|
|||||||
(
|
(
|
||||||
if underlyingElement(this) instanceof @attribute_arg_type
|
if underlyingElement(this) instanceof @attribute_arg_type
|
||||||
then tail = this.getValueType().getName()
|
then tail = this.getValueType().getName()
|
||||||
else
|
else tail = this.getValueText()
|
||||||
if underlyingElement(this) instanceof @attribute_arg_constant_expr
|
|
||||||
then tail = this.getValueConstant().toString()
|
|
||||||
else tail = this.getValueText()
|
|
||||||
) and
|
) and
|
||||||
result = prefix + tail
|
result = prefix + tail
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate suppressUnusedThis(Specifier s) { any() }
|
||||||
|
|||||||
@@ -398,8 +398,6 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
|
|||||||
exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result)
|
exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result)
|
||||||
or
|
or
|
||||||
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
|
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
|
||||||
or
|
|
||||||
orphaned_variables(underlyingElement(this), unresolveElement(result))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,9 +471,6 @@ class GlobalOrNamespaceVariable extends Variable, @globalvariable {
|
|||||||
override Type getType() { globalvariables(underlyingElement(this), unresolveElement(result), _) }
|
override Type getType() { globalvariables(underlyingElement(this), unresolveElement(result), _) }
|
||||||
|
|
||||||
override Element getEnclosingElement() { none() }
|
override Element getEnclosingElement() { none() }
|
||||||
|
|
||||||
/** Gets a link target which compiled or referenced this global or namespace variable. */
|
|
||||||
LinkTarget getALinkTarget() { this = result.getAGlobalOrNamespaceVariable() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
107
cpp/ql/lib/semmle/code/cpp/XML.qll
Normal file → Executable file
107
cpp/ql/lib/semmle/code/cpp/XML.qll
Normal file → Executable file
@@ -8,7 +8,7 @@ private class TXmlLocatable =
|
|||||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||||
|
|
||||||
/** An XML element that has a location. */
|
/** An XML element that has a location. */
|
||||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
class XMLLocatable extends @xmllocatable, TXmlLocatable {
|
||||||
/** Gets the source location for this element. */
|
/** Gets the source location for this element. */
|
||||||
Location getLocation() { xmllocations(this, result) }
|
Location getLocation() { xmllocations(this, result) }
|
||||||
|
|
||||||
@@ -32,16 +32,13 @@ class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
|||||||
string toString() { none() } // overridden in subclasses
|
string toString() { none() } // overridden in subclasses
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlLocatable */
|
|
||||||
deprecated class XMLLocatable = XmlLocatable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
* An `XMLParent` is either an `XMLElement` or an `XMLFile`,
|
||||||
* both of which can contain other elements.
|
* both of which can contain other elements.
|
||||||
*/
|
*/
|
||||||
class XmlParent extends @xmlparent {
|
class XMLParent extends @xmlparent {
|
||||||
XmlParent() {
|
XMLParent() {
|
||||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
// explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
|
||||||
// the type `@xmlparent` currently also includes non-XML files
|
// the type `@xmlparent` currently also includes non-XML files
|
||||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||||
}
|
}
|
||||||
@@ -53,28 +50,28 @@ class XmlParent extends @xmlparent {
|
|||||||
string getName() { none() } // overridden in subclasses
|
string getName() { none() } // overridden in subclasses
|
||||||
|
|
||||||
/** Gets the file to which this XML parent belongs. */
|
/** Gets the file to which this XML parent belongs. */
|
||||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
XMLFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||||
|
|
||||||
/** Gets the child element at a specified index of this XML parent. */
|
/** Gets the child element at a specified index of this XML parent. */
|
||||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
XMLElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||||
|
|
||||||
/** Gets a child element of this XML parent. */
|
/** Gets a child element of this XML parent. */
|
||||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
XMLElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||||
|
|
||||||
/** Gets a child element of this XML parent with the given `name`. */
|
/** Gets a child element of this XML parent with the given `name`. */
|
||||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
XMLElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||||
|
|
||||||
/** Gets a comment that is a child of this XML parent. */
|
/** Gets a comment that is a child of this XML parent. */
|
||||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
XMLComment getAComment() { xmlComments(result, _, this, _) }
|
||||||
|
|
||||||
/** Gets a character sequence that is a child of this XML parent. */
|
/** Gets a character sequence that is a child of this XML parent. */
|
||||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
XMLCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||||
|
|
||||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
/** Gets the depth in the tree. (Overridden in XMLElement.) */
|
||||||
int getDepth() { result = 0 }
|
int getDepth() { result = 0 }
|
||||||
|
|
||||||
/** Gets the number of child XML elements of this XML parent. */
|
/** Gets the number of child XML elements of this XML parent. */
|
||||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
int getNumberOfChildren() { result = count(XMLElement e | xmlElements(e, _, this, _, _)) }
|
||||||
|
|
||||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||||
@@ -95,12 +92,9 @@ class XmlParent extends @xmlparent {
|
|||||||
string toString() { result = this.getName() }
|
string toString() { result = this.getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlParent */
|
|
||||||
deprecated class XMLParent = XmlParent;
|
|
||||||
|
|
||||||
/** An XML file. */
|
/** An XML file. */
|
||||||
class XmlFile extends XmlParent, File {
|
class XMLFile extends XMLParent, File {
|
||||||
XmlFile() { xmlEncoding(this, _) }
|
XMLFile() { xmlEncoding(this, _) }
|
||||||
|
|
||||||
/** Gets a printable representation of this XML file. */
|
/** Gets a printable representation of this XML file. */
|
||||||
override string toString() { result = this.getName() }
|
override string toString() { result = this.getName() }
|
||||||
@@ -126,21 +120,15 @@ class XmlFile extends XmlParent, File {
|
|||||||
string getEncoding() { xmlEncoding(this, result) }
|
string getEncoding() { xmlEncoding(this, result) }
|
||||||
|
|
||||||
/** Gets the XML file itself. */
|
/** Gets the XML file itself. */
|
||||||
override XmlFile getFile() { result = this }
|
override XMLFile getFile() { result = this }
|
||||||
|
|
||||||
/** Gets a top-most element in an XML file. */
|
/** Gets a top-most element in an XML file. */
|
||||||
XmlElement getARootElement() { result = this.getAChild() }
|
XMLElement getARootElement() { result = this.getAChild() }
|
||||||
|
|
||||||
/** Gets a DTD associated with this XML file. */
|
/** Gets a DTD associated with this XML file. */
|
||||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
XMLDTD getADTD() { xmlDTDs(result, _, _, _, this) }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getADtd */
|
|
||||||
deprecated XmlDtd getADTD() { result = this.getADtd() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlFile */
|
|
||||||
deprecated class XMLFile = XmlFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An XML document type definition (DTD).
|
* An XML document type definition (DTD).
|
||||||
*
|
*
|
||||||
@@ -152,7 +140,7 @@ deprecated class XMLFile = XmlFile;
|
|||||||
* <!ELEMENT lastName (#PCDATA)>
|
* <!ELEMENT lastName (#PCDATA)>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
class XMLDTD extends XMLLocatable, @xmldtd {
|
||||||
/** Gets the name of the root element of this DTD. */
|
/** Gets the name of the root element of this DTD. */
|
||||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||||
|
|
||||||
@@ -166,7 +154,7 @@ class XmlDtd extends XmlLocatable, @xmldtd {
|
|||||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||||
|
|
||||||
/** Gets the parent of this DTD. */
|
/** Gets the parent of this DTD. */
|
||||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
XMLParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
this.isPublic() and
|
this.isPublic() and
|
||||||
@@ -177,9 +165,6 @@ class XmlDtd extends XmlLocatable, @xmldtd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlDtd */
|
|
||||||
deprecated class XMLDTD = XmlDtd;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An XML element in an XML file.
|
* An XML element in an XML file.
|
||||||
*
|
*
|
||||||
@@ -191,7 +176,7 @@ deprecated class XMLDTD = XmlDtd;
|
|||||||
* </manifest>
|
* </manifest>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||||
/** Holds if this XML element has the given `name`. */
|
/** Holds if this XML element has the given `name`. */
|
||||||
predicate hasName(string name) { name = this.getName() }
|
predicate hasName(string name) { name = this.getName() }
|
||||||
|
|
||||||
@@ -199,10 +184,10 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
|||||||
override string getName() { xmlElements(this, result, _, _, _) }
|
override string getName() { xmlElements(this, result, _, _, _) }
|
||||||
|
|
||||||
/** Gets the XML file in which this XML element occurs. */
|
/** Gets the XML file in which this XML element occurs. */
|
||||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
override XMLFile getFile() { xmlElements(this, _, _, _, result) }
|
||||||
|
|
||||||
/** Gets the parent of this XML element. */
|
/** Gets the parent of this XML element. */
|
||||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
XMLParent getParent() { xmlElements(this, _, result, _, _) }
|
||||||
|
|
||||||
/** Gets the index of this XML element among its parent's children. */
|
/** Gets the index of this XML element among its parent's children. */
|
||||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||||
@@ -211,7 +196,7 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
|||||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||||
|
|
||||||
/** Gets the namespace of this XML element, if any. */
|
/** Gets the namespace of this XML element, if any. */
|
||||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
XMLNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||||
|
|
||||||
/** Gets the index of this XML element among its parent's children. */
|
/** Gets the index of this XML element among its parent's children. */
|
||||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||||
@@ -220,10 +205,10 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
|||||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||||
|
|
||||||
/** Gets an XML attribute of this XML element. */
|
/** Gets an XML attribute of this XML element. */
|
||||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
XMLAttribute getAnAttribute() { result.getElement() = this }
|
||||||
|
|
||||||
/** Gets the attribute with the specified `name`, if any. */
|
/** Gets the attribute with the specified `name`, if any. */
|
||||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||||
|
|
||||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||||
@@ -235,9 +220,6 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
|||||||
override string toString() { result = this.getName() }
|
override string toString() { result = this.getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlElement */
|
|
||||||
deprecated class XMLElement = XmlElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An attribute that occurs inside an XML element.
|
* An attribute that occurs inside an XML element.
|
||||||
*
|
*
|
||||||
@@ -248,18 +230,18 @@ deprecated class XMLElement = XmlElement;
|
|||||||
* android:versionCode="1"
|
* android:versionCode="1"
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
class XMLAttribute extends @xmlattribute, XMLLocatable {
|
||||||
/** Gets the name of this attribute. */
|
/** Gets the name of this attribute. */
|
||||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||||
|
|
||||||
/** Gets the XML element to which this attribute belongs. */
|
/** Gets the XML element to which this attribute belongs. */
|
||||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
XMLElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||||
|
|
||||||
/** Holds if this attribute has a namespace. */
|
/** Holds if this attribute has a namespace. */
|
||||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||||
|
|
||||||
/** Gets the namespace of this attribute, if any. */
|
/** Gets the namespace of this attribute, if any. */
|
||||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
XMLNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||||
|
|
||||||
/** Gets the value of this attribute. */
|
/** Gets the value of this attribute. */
|
||||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||||
@@ -268,9 +250,6 @@ class XmlAttribute extends @xmlattribute, XmlLocatable {
|
|||||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlAttribute */
|
|
||||||
deprecated class XMLAttribute = XmlAttribute;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A namespace used in an XML file.
|
* A namespace used in an XML file.
|
||||||
*
|
*
|
||||||
@@ -280,29 +259,23 @@ deprecated class XMLAttribute = XmlAttribute;
|
|||||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
class XMLNamespace extends XMLLocatable, @xmlnamespace {
|
||||||
/** Gets the prefix of this namespace. */
|
/** Gets the prefix of this namespace. */
|
||||||
string getPrefix() { xmlNs(this, result, _, _) }
|
string getPrefix() { xmlNs(this, result, _, _) }
|
||||||
|
|
||||||
/** Gets the URI of this namespace. */
|
/** Gets the URI of this namespace. */
|
||||||
string getUri() { xmlNs(this, _, result, _) }
|
string getURI() { xmlNs(this, _, result, _) }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getUri */
|
|
||||||
deprecated string getURI() { result = this.getUri() }
|
|
||||||
|
|
||||||
/** Holds if this namespace has no prefix. */
|
/** Holds if this namespace has no prefix. */
|
||||||
predicate isDefault() { this.getPrefix() = "" }
|
predicate isDefault() { this.getPrefix() = "" }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
this.isDefault() and result = this.getUri()
|
this.isDefault() and result = this.getURI()
|
||||||
or
|
or
|
||||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlNamespace */
|
|
||||||
deprecated class XMLNamespace = XmlNamespace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A comment in an XML file.
|
* A comment in an XML file.
|
||||||
*
|
*
|
||||||
@@ -312,20 +285,17 @@ deprecated class XMLNamespace = XmlNamespace;
|
|||||||
* <!-- This is a comment. -->
|
* <!-- This is a comment. -->
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
class XMLComment extends @xmlcomment, XMLLocatable {
|
||||||
/** Gets the text content of this XML comment. */
|
/** Gets the text content of this XML comment. */
|
||||||
string getText() { xmlComments(this, result, _, _) }
|
string getText() { xmlComments(this, result, _, _) }
|
||||||
|
|
||||||
/** Gets the parent of this XML comment. */
|
/** Gets the parent of this XML comment. */
|
||||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
XMLParent getParent() { xmlComments(this, _, result, _) }
|
||||||
|
|
||||||
/** Gets a printable representation of this XML comment. */
|
/** Gets a printable representation of this XML comment. */
|
||||||
override string toString() { result = this.getText() }
|
override string toString() { result = this.getText() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlComment */
|
|
||||||
deprecated class XMLComment = XmlComment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sequence of characters that occurs between opening and
|
* A sequence of characters that occurs between opening and
|
||||||
* closing tags of an XML element, excluding other elements.
|
* closing tags of an XML element, excluding other elements.
|
||||||
@@ -336,12 +306,12 @@ deprecated class XMLComment = XmlComment;
|
|||||||
* <content>This is a sequence of characters.</content>
|
* <content>This is a sequence of characters.</content>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
class XMLCharacters extends @xmlcharacters, XMLLocatable {
|
||||||
/** Gets the content of this character sequence. */
|
/** Gets the content of this character sequence. */
|
||||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||||
|
|
||||||
/** Gets the parent of this character sequence. */
|
/** Gets the parent of this character sequence. */
|
||||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
XMLParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||||
|
|
||||||
/** Holds if this character sequence is CDATA. */
|
/** Holds if this character sequence is CDATA. */
|
||||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||||
@@ -349,6 +319,3 @@ class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
|||||||
/** Gets a printable representation of this XML character sequence. */
|
/** Gets a printable representation of this XML character sequence. */
|
||||||
override string toString() { result = this.getCharacters() }
|
override string toString() { result = this.getCharacters() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for XmlCharacters */
|
|
||||||
deprecated class XMLCharacters = XmlCharacters;
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class BasicBlock extends ControlFlowNodeBase {
|
|||||||
exists(Function f | f.getBlock() = this)
|
exists(Function f | f.getBlock() = this)
|
||||||
or
|
or
|
||||||
exists(TryStmt t, BasicBlock tryblock |
|
exists(TryStmt t, BasicBlock tryblock |
|
||||||
// a `Handler` precedes the `CatchBlock`, and is always the beginning
|
// a `Handler` preceeds the `CatchBlock`, and is always the beginning
|
||||||
// of a new `BasicBlock` (see `primitive_basic_block_entry_node`).
|
// of a new `BasicBlock` (see `primitive_basic_block_entry_node`).
|
||||||
this.(Handler).getTryStmt() = t and
|
this.(Handler).getTryStmt() = t and
|
||||||
tryblock.isReachable() and
|
tryblock.isReachable() and
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -699,7 +699,7 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
|
|||||||
call.getTarget() = f and
|
call.getTarget() = f and
|
||||||
// AST dataflow treats a reference as if it were the referred-to object, while the dataflow
|
// AST dataflow treats a reference as if it were the referred-to object, while the dataflow
|
||||||
// models treat references as pointers. If the return type of the call is a reference, then
|
// models treat references as pointers. If the return type of the call is a reference, then
|
||||||
// look for data flow to the referred-to object, rather than the reference itself.
|
// look for data flow the the referred-to object, rather than the reference itself.
|
||||||
if call.getType().getUnspecifiedType() instanceof ReferenceType
|
if call.getType().getUnspecifiedType() instanceof ReferenceType
|
||||||
then outModel.isReturnValueDeref()
|
then outModel.isReturnValueDeref()
|
||||||
else outModel.isReturnValue()
|
else outModel.isReturnValue()
|
||||||
|
|||||||
@@ -47,20 +47,6 @@ class AssignExpr extends Assignment, @assignexpr {
|
|||||||
override string toString() { result = "... = ..." }
|
override string toString() { result = "... = ..." }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A compiler generated assignment operation that may occur in a compiler generated
|
|
||||||
* copy/move constructor or assignment operator, and which functions like `memcpy`
|
|
||||||
* where the size argument is based on the type of the rvalue of the assignment.
|
|
||||||
*/
|
|
||||||
class BlockAssignExpr extends Assignment, @blockassignexpr {
|
|
||||||
override string getOperator() { result = "=" }
|
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "BlockAssignExpr" }
|
|
||||||
|
|
||||||
/** Gets a textual representation of this assignment. */
|
|
||||||
override string toString() { result = "... = ..." }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A non-overloaded binary assignment operation other than `=`.
|
* A non-overloaded binary assignment operation other than `=`.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ abstract class MustFlowConfiguration extends string {
|
|||||||
*/
|
*/
|
||||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||||
|
|
||||||
/** Holds if this configuration allows flow from arguments to parameters. */
|
|
||||||
predicate allowInterproceduralFlow() { any() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data must flow from `source` to `sink` for this configuration.
|
* Holds if data must flow from `source` to `sink` for this configuration.
|
||||||
*
|
*
|
||||||
@@ -207,25 +204,10 @@ private module Cached {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
|
||||||
* predicate ensures that joins go from `n` to the result instead of the other
|
|
||||||
* way around.
|
|
||||||
*/
|
|
||||||
pragma[inline]
|
|
||||||
private Declaration getEnclosingCallable(DataFlow::Node n) {
|
|
||||||
pragma[only_bind_into](result) = pragma[only_bind_out](n).getEnclosingCallable()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if `nodeFrom` flows to `nodeTo`. */
|
/** Holds if `nodeFrom` flows to `nodeTo`. */
|
||||||
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
|
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
|
||||||
exists(config) and
|
exists(config) and
|
||||||
Cached::step(pragma[only_bind_into](nodeFrom), pragma[only_bind_into](nodeTo)) and
|
Cached::step(nodeFrom, nodeTo)
|
||||||
(
|
|
||||||
config.allowInterproceduralFlow()
|
|
||||||
or
|
|
||||||
getEnclosingCallable(nodeFrom) = getEnclosingCallable(nodeTo)
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
config.isAdditionalFlowStep(nodeFrom, nodeTo)
|
config.isAdditionalFlowStep(nodeFrom, nodeTo)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -244,25 +244,7 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
|||||||
* calling context. For example, this would happen with flow through a
|
* calling context. For example, this would happen with flow through a
|
||||||
* global or static variable.
|
* global or static variable.
|
||||||
*/
|
*/
|
||||||
predicate jumpStep(Node n1, Node n2) {
|
predicate jumpStep(Node n1, Node n2) { none() }
|
||||||
exists(GlobalOrNamespaceVariable v |
|
|
||||||
v =
|
|
||||||
n1.asInstruction()
|
|
||||||
.(StoreInstruction)
|
|
||||||
.getResultAddress()
|
|
||||||
.(VariableAddressInstruction)
|
|
||||||
.getAstVariable() and
|
|
||||||
v = n2.asVariable()
|
|
||||||
or
|
|
||||||
v =
|
|
||||||
n2.asInstruction()
|
|
||||||
.(LoadInstruction)
|
|
||||||
.getSourceAddress()
|
|
||||||
.(VariableAddressInstruction)
|
|
||||||
.getAstVariable() and
|
|
||||||
v = n1.asVariable()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ private module Liveness {
|
|||||||
/**
|
/**
|
||||||
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
|
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
|
||||||
*/
|
*/
|
||||||
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
|
private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
|
||||||
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
|
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
|
||||||
or
|
or
|
||||||
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
|
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
|
||||||
@@ -76,10 +76,6 @@ private module Liveness {
|
|||||||
not result + 1 = refRank(bb, _, v, _)
|
not result + 1 = refRank(bb, _, v, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
|
|
||||||
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
|
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
|
||||||
* that is either a read or a certain write.
|
* that is either a read or a certain write.
|
||||||
@@ -189,29 +185,23 @@ newtype TDefinition =
|
|||||||
|
|
||||||
private module SsaDefReaches {
|
private module SsaDefReaches {
|
||||||
newtype TSsaRefKind =
|
newtype TSsaRefKind =
|
||||||
SsaActualRead() or
|
SsaRead() or
|
||||||
SsaPhiRead() or
|
|
||||||
SsaDef()
|
SsaDef()
|
||||||
|
|
||||||
class SsaRead = SsaActualRead or SsaPhiRead;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A classification of SSA variable references into reads and definitions.
|
* A classification of SSA variable references into reads and definitions.
|
||||||
*/
|
*/
|
||||||
class SsaRefKind extends TSsaRefKind {
|
class SsaRefKind extends TSsaRefKind {
|
||||||
string toString() {
|
string toString() {
|
||||||
this = SsaActualRead() and
|
this = SsaRead() and
|
||||||
result = "SsaActualRead"
|
result = "SsaRead"
|
||||||
or
|
|
||||||
this = SsaPhiRead() and
|
|
||||||
result = "SsaPhiRead"
|
|
||||||
or
|
or
|
||||||
this = SsaDef() and
|
this = SsaDef() and
|
||||||
result = "SsaDef"
|
result = "SsaDef"
|
||||||
}
|
}
|
||||||
|
|
||||||
int getOrder() {
|
int getOrder() {
|
||||||
this instanceof SsaRead and
|
this = SsaRead() and
|
||||||
result = 0
|
result = 0
|
||||||
or
|
or
|
||||||
this = SsaDef() and
|
this = SsaDef() and
|
||||||
@@ -219,80 +209,6 @@ private module SsaDefReaches {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `bb` is in the dominance frontier of a block containing a
|
|
||||||
* read of `v`.
|
|
||||||
*/
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
|
|
||||||
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
|
|
||||||
lastRefIsRead(readbb, v)
|
|
||||||
or
|
|
||||||
phiRead(readbb, v)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if a phi-read node should be inserted for variable `v` at the beginning
|
|
||||||
* of basic block `bb`.
|
|
||||||
*
|
|
||||||
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
|
|
||||||
* instead of writes, and only if the dominance-frontier block does not already
|
|
||||||
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
|
|
||||||
* an internal implementation detail that is not exposed.
|
|
||||||
*
|
|
||||||
* The motivation for adding phi-reads is to improve performance of the use-use
|
|
||||||
* calculation in cases where there is a large number of reads that can reach the
|
|
||||||
* same join-point, and from there reach a large number of basic blocks. Example:
|
|
||||||
*
|
|
||||||
* ```cs
|
|
||||||
* if (a)
|
|
||||||
* use(x);
|
|
||||||
* else if (b)
|
|
||||||
* use(x);
|
|
||||||
* else if (c)
|
|
||||||
* use(x);
|
|
||||||
* else if (d)
|
|
||||||
* use(x);
|
|
||||||
* // many more ifs ...
|
|
||||||
*
|
|
||||||
* // phi-read for `x` inserted here
|
|
||||||
*
|
|
||||||
* // program not mentioning `x`, with large basic block graph
|
|
||||||
*
|
|
||||||
* use(x);
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Without phi-reads, the analysis has to replicate reachability for each of
|
|
||||||
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
|
|
||||||
* each conditional use of `x` to reach the basic block containing the phi-read
|
|
||||||
* node for `x`, and only that basic block will have to compute reachability
|
|
||||||
* through the remainder of the large program.
|
|
||||||
*
|
|
||||||
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
|
|
||||||
* one SSA definition (without passing through another definition): Assume, for
|
|
||||||
* the sake of contradiction, that there are two reaching definitions `def1` and
|
|
||||||
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
|
|
||||||
* dominating definition will prevent the other from reaching `phi-read`. So, at
|
|
||||||
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
|
|
||||||
* Then `def1` must go through one of its dominance-frontier blocks in order to
|
|
||||||
* reach `phi-read`. However, such a block will always start with a (normal) phi
|
|
||||||
* node, which contradicts reachability.
|
|
||||||
*
|
|
||||||
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
|
|
||||||
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
|
|
||||||
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
|
|
||||||
* which contradicts reachability.
|
|
||||||
*/
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate phiRead(BasicBlock bb, SourceVariable v) {
|
|
||||||
inReadDominanceFrontier(bb, v) and
|
|
||||||
liveAtEntry(bb, v) and
|
|
||||||
// only if there are no other references to `v` inside `bb`
|
|
||||||
not ref(bb, _, v, _) and
|
|
||||||
not exists(Definition def | def.definesAt(v, bb, _))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
|
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
|
||||||
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
|
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
|
||||||
@@ -300,16 +216,11 @@ private module SsaDefReaches {
|
|||||||
*
|
*
|
||||||
* Unlike `Liveness::ref`, this includes `phi` nodes.
|
* Unlike `Liveness::ref`, this includes `phi` nodes.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
|
||||||
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
|
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
|
||||||
variableRead(bb, i, v, _) and
|
variableRead(bb, i, v, _) and
|
||||||
k = SsaActualRead()
|
k = SsaRead()
|
||||||
or
|
or
|
||||||
phiRead(bb, v) and
|
exists(Definition def | def.definesAt(v, bb, i)) and
|
||||||
i = -1 and
|
|
||||||
k = SsaPhiRead()
|
|
||||||
or
|
|
||||||
any(Definition def).definesAt(v, bb, i) and
|
|
||||||
k = SsaDef()
|
k = SsaDef()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +273,7 @@ private module SsaDefReaches {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
ssaDefReachesRank(bb, def, rnk - 1, v) and
|
ssaDefReachesRank(bb, def, rnk - 1, v) and
|
||||||
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
|
rnk = ssaRefRank(bb, _, v, SsaRead())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -372,7 +283,7 @@ private module SsaDefReaches {
|
|||||||
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
||||||
exists(int rnk |
|
exists(int rnk |
|
||||||
ssaDefReachesRank(bb, def, rnk, v) and
|
ssaDefReachesRank(bb, def, rnk, v) and
|
||||||
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
|
rnk = ssaRefRank(bb, i, v, SsaRead())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,94 +309,45 @@ private module SsaDefReaches {
|
|||||||
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
|
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
|
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) {
|
||||||
exists(ssaDefRank(def, v, bb, _, k))
|
exists(ssaDefRank(def, v, bb, _, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
|
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
|
||||||
ssaDefReachesEndOfBlock(bb, def, _) and
|
ssaDefReachesEndOfBlock(bb, def, _) and
|
||||||
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
|
not defOccursInBlock(_, bb, def.getSourceVariable())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
|
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
|
||||||
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
|
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`,
|
||||||
* predecessor of `bb2`, and the underlying variable for `def` is neither read
|
* and the underlying variable for `def` is neither read nor written in any block
|
||||||
* nor written in any block on the path between `bb1` and `bb2`.
|
* on the path between `bb1` and `bb2`.
|
||||||
*
|
|
||||||
* Phi reads are considered as normal reads for this predicate.
|
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
||||||
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
defOccursInBlock(def, bb1, _) and
|
||||||
defOccursInBlock(def, bb1, _, _) and
|
|
||||||
bb2 = getABasicBlockSuccessor(bb1)
|
bb2 = getABasicBlockSuccessor(bb1)
|
||||||
or
|
or
|
||||||
exists(BasicBlock mid |
|
exists(BasicBlock mid |
|
||||||
varBlockReachesInclPhiRead(def, bb1, mid) and
|
varBlockReaches(def, bb1, mid) and
|
||||||
ssaDefReachesThroughBlock(def, mid) and
|
ssaDefReachesThroughBlock(def, mid) and
|
||||||
bb2 = getABasicBlockSuccessor(mid)
|
bb2 = getABasicBlockSuccessor(mid)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
|
|
||||||
varBlockReachesInclPhiRead(def, bb1, bb2) and
|
|
||||||
defOccursInBlock(def, bb2, v, SsaPhiRead())
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
|
||||||
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
|
|
||||||
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
|
|
||||||
or
|
|
||||||
exists(BasicBlock mid |
|
|
||||||
varBlockReachesExclPhiRead(def, mid, bb2) and
|
|
||||||
phiReadStep(def, _, bb1, mid)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
|
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
|
||||||
* the underlying variable `v` of `def` is accessed in basic block `bb2`
|
* `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive
|
||||||
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
|
* successor block of `bb1`, and `def` is neither read nor written in any block
|
||||||
* `v` is neither read nor written in any block on the path between `bb1`
|
* on a path between `bb1` and `bb2`.
|
||||||
* and `bb2`.
|
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
|
||||||
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
|
||||||
varBlockReachesExclPhiRead(def, bb1, bb2) and
|
|
||||||
not defOccursInBlock(def, bb1, _, SsaPhiRead())
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
|
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
|
||||||
varBlockReaches(def, bb1, bb2) and
|
varBlockReaches(def, bb1, bb2) and
|
||||||
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
|
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
|
|
||||||
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
|
|
||||||
* and `v` is neither read nor written in any block on the path between `bb`
|
|
||||||
* and `bb2`.
|
|
||||||
*/
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
|
|
||||||
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
|
|
||||||
not defOccursInBlock(def, bb2, _, _) and
|
|
||||||
not ssaDefReachesEndOfBlock(bb2, def, _)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(BasicBlock mid |
|
|
||||||
varBlockReachesExit(def, mid) and
|
|
||||||
phiReadStep(def, _, bb, mid)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate phiReadExposedForTesting = phiRead/2;
|
|
||||||
|
|
||||||
private import SsaDefReaches
|
private import SsaDefReaches
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -503,8 +365,7 @@ predicate liveThrough(BasicBlock bb, SourceVariable v) {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
|
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
|
||||||
exists(int last |
|
exists(int last | last = maxSsaRefRank(bb, v) |
|
||||||
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
|
|
||||||
ssaDefReachesRank(bb, def, last, v) and
|
ssaDefReachesRank(bb, def, last, v) and
|
||||||
liveAtExit(bb, v)
|
liveAtExit(bb, v)
|
||||||
)
|
)
|
||||||
@@ -544,7 +405,7 @@ pragma[nomagic]
|
|||||||
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
||||||
ssaDefReachesReadWithinBlock(v, def, bb, i)
|
ssaDefReachesReadWithinBlock(v, def, bb, i)
|
||||||
or
|
or
|
||||||
ssaRef(bb, i, v, any(SsaRead k)) and
|
variableRead(bb, i, v, _) and
|
||||||
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
|
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
|
||||||
not ssaDefReachesReadWithinBlock(v, _, bb, i)
|
not ssaDefReachesReadWithinBlock(v, _, bb, i)
|
||||||
}
|
}
|
||||||
@@ -560,7 +421,7 @@ pragma[nomagic]
|
|||||||
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
|
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
|
||||||
exists(int rnk |
|
exists(int rnk |
|
||||||
rnk = ssaDefRank(def, _, bb1, i1, _) and
|
rnk = ssaDefRank(def, _, bb1, i1, _) and
|
||||||
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
|
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and
|
||||||
variableRead(bb1, i2, _, _) and
|
variableRead(bb1, i2, _, _) and
|
||||||
bb2 = bb1
|
bb2 = bb1
|
||||||
)
|
)
|
||||||
@@ -677,15 +538,18 @@ predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Def
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate lastRef(Definition def, BasicBlock bb, int i) {
|
predicate lastRef(Definition def, BasicBlock bb, int i) {
|
||||||
// Can reach another definition
|
|
||||||
lastRefRedef(def, bb, i, _)
|
lastRefRedef(def, bb, i, _)
|
||||||
or
|
or
|
||||||
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
|
lastSsaRef(def, _, bb, i) and
|
||||||
|
(
|
||||||
// Can reach exit directly
|
// Can reach exit directly
|
||||||
bb instanceof ExitBasicBlock
|
bb instanceof ExitBasicBlock
|
||||||
or
|
or
|
||||||
// Can reach a block using one or more steps, where `def` is no longer live
|
// Can reach a block using one or more steps, where `def` is no longer live
|
||||||
varBlockReachesExit(def, bb)
|
exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) |
|
||||||
|
not defOccursInBlock(def, bb2, _) and
|
||||||
|
not ssaDefReachesEndOfBlock(bb2, def, _)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ module InstructionConsistency {
|
|||||||
abstract Language::Location getLocation();
|
abstract Language::Location getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
private class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
||||||
private IRFunction irFunc;
|
private IRFunction irFunc;
|
||||||
|
|
||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
@@ -37,8 +37,6 @@ module InstructionConsistency {
|
|||||||
result =
|
result =
|
||||||
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
IRFunction getIRFunction() { result = irFunc }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import semmle.code.cpp.ir.internal.Overlap
|
|||||||
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||||
private import semmle.code.cpp.Print
|
private import semmle.code.cpp.Print
|
||||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
|
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
|
||||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa
|
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSSA
|
||||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
||||||
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
|
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
|
||||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||||
@@ -572,7 +572,7 @@ private Overlap getVariableMemoryLocationOverlap(
|
|||||||
* Holds if the def/use information for the result of `instr` can be reused from the previous
|
* Holds if the def/use information for the result of `instr` can be reused from the previous
|
||||||
* iteration of the IR.
|
* iteration of the IR.
|
||||||
*/
|
*/
|
||||||
predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMemoryResult(instr) }
|
predicate canReuseSsaForOldResult(Instruction instr) { OldSSA::canReuseSsaForMemoryResult(instr) }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for canReuseSsaForOldResult */
|
/** DEPRECATED: Alias for canReuseSsaForOldResult */
|
||||||
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
|
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ private import Imports::OperandTag
|
|||||||
private import Imports::Overlap
|
private import Imports::Overlap
|
||||||
private import Imports::TInstruction
|
private import Imports::TInstruction
|
||||||
private import Imports::RawIR as RawIR
|
private import Imports::RawIR as RawIR
|
||||||
private import SsaInstructions
|
private import SSAInstructions
|
||||||
private import SsaOperands
|
private import SSAOperands
|
||||||
private import NewIR
|
private import NewIR
|
||||||
|
|
||||||
private class OldBlock = Reachability::ReachableBlock;
|
private class OldBlock = Reachability::ReachableBlock;
|
||||||
|
|||||||
@@ -2,14 +2,7 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
|
|||||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
|
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
|
||||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
|
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
|
||||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
|
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
|
||||||
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SsaInstructions
|
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SSAInstructions
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SsaInstructions */
|
|
||||||
deprecated module SSAInstructions = SsaInstructions;
|
|
||||||
|
|
||||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||||
import AliasedSSA as Alias
|
import AliasedSSA as Alias
|
||||||
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SsaOperands
|
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SSAOperands
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SsaOperands */
|
|
||||||
deprecated module SSAOperands = SsaOperands;
|
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ newtype TInstruction =
|
|||||||
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
|
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
|
||||||
} or
|
} or
|
||||||
TAliasedSsaPhiInstruction(
|
TAliasedSsaPhiInstruction(
|
||||||
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
|
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||||
) {
|
) {
|
||||||
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||||
} or
|
} or
|
||||||
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
|
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
|
||||||
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
|
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
|
||||||
} or
|
} or
|
||||||
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
||||||
AliasedSsa::SSA::hasUnreachedInstruction(irFunc)
|
AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
|
|||||||
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
|
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
|
||||||
|
|
||||||
TPhiInstruction phiInstruction(
|
TPhiInstruction phiInstruction(
|
||||||
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
|
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||||
) {
|
) {
|
||||||
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
|
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
|
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
|
||||||
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSsa
|
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA
|
||||||
|
|
||||||
/** DEPRECATED: Alias for AliasedSsa */
|
|
||||||
deprecated module AliasedSSA = AliasedSsa;
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ module InstructionConsistency {
|
|||||||
abstract Language::Location getLocation();
|
abstract Language::Location getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
private class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
||||||
private IRFunction irFunc;
|
private IRFunction irFunc;
|
||||||
|
|
||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
@@ -37,8 +37,6 @@ module InstructionConsistency {
|
|||||||
result =
|
result =
|
||||||
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
IRFunction getIRFunction() { result = irFunc }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
||||||
|
|||||||
@@ -947,7 +947,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The IR translation of a root element, either a function or a global variable.
|
* Represents the IR translation of a root element, either a function or a global variable.
|
||||||
*/
|
*/
|
||||||
abstract class TranslatedRootElement extends TranslatedElement {
|
abstract class TranslatedRootElement extends TranslatedElement {
|
||||||
TranslatedRootElement() {
|
TranslatedRootElement() {
|
||||||
|
|||||||
@@ -1450,6 +1450,8 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
|
|||||||
result = this.getLeftOperand().getResult()
|
result = this.getLeftOperand().getResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract Instruction getStoredValue();
|
||||||
|
|
||||||
final TranslatedExpr getLeftOperand() {
|
final TranslatedExpr getLeftOperand() {
|
||||||
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
|
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
|
||||||
}
|
}
|
||||||
@@ -1491,75 +1493,6 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TranslatedBlockAssignExpr extends TranslatedNonConstantExpr {
|
|
||||||
override BlockAssignExpr expr;
|
|
||||||
|
|
||||||
final override TranslatedElement getChild(int id) {
|
|
||||||
id = 0 and result = this.getLeftOperand()
|
|
||||||
or
|
|
||||||
id = 1 and result = this.getRightOperand()
|
|
||||||
}
|
|
||||||
|
|
||||||
final override Instruction getFirstInstruction() {
|
|
||||||
// The operand evaluation order should not matter since block assignments behave like memcpy.
|
|
||||||
result = this.getLeftOperand().getFirstInstruction()
|
|
||||||
}
|
|
||||||
|
|
||||||
final override Instruction getResult() { result = this.getInstruction(AssignmentStoreTag()) }
|
|
||||||
|
|
||||||
final TranslatedExpr getLeftOperand() {
|
|
||||||
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
|
|
||||||
}
|
|
||||||
|
|
||||||
final TranslatedExpr getRightOperand() {
|
|
||||||
result = getTranslatedExpr(expr.getRValue().getFullyConverted())
|
|
||||||
}
|
|
||||||
|
|
||||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
|
||||||
tag = LoadTag() and
|
|
||||||
result = this.getInstruction(AssignmentStoreTag()) and
|
|
||||||
kind instanceof GotoEdge
|
|
||||||
or
|
|
||||||
tag = AssignmentStoreTag() and
|
|
||||||
result = this.getParent().getChildSuccessor(this) and
|
|
||||||
kind instanceof GotoEdge
|
|
||||||
}
|
|
||||||
|
|
||||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
|
||||||
child = this.getLeftOperand() and
|
|
||||||
result = this.getRightOperand().getFirstInstruction()
|
|
||||||
or
|
|
||||||
child = this.getRightOperand() and
|
|
||||||
result = this.getInstruction(LoadTag())
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
|
||||||
tag = LoadTag() and
|
|
||||||
opcode instanceof Opcode::Load and
|
|
||||||
resultType = getTypeForPRValue(expr.getRValue().getType())
|
|
||||||
or
|
|
||||||
tag = AssignmentStoreTag() and
|
|
||||||
opcode instanceof Opcode::Store and
|
|
||||||
// The frontend specifies that the relevant type is the one of the source.
|
|
||||||
resultType = getTypeForPRValue(expr.getRValue().getType())
|
|
||||||
}
|
|
||||||
|
|
||||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
|
||||||
tag = LoadTag() and
|
|
||||||
operandTag instanceof AddressOperandTag and
|
|
||||||
result = this.getRightOperand().getResult()
|
|
||||||
or
|
|
||||||
tag = AssignmentStoreTag() and
|
|
||||||
(
|
|
||||||
operandTag instanceof AddressOperandTag and
|
|
||||||
result = this.getLeftOperand().getResult()
|
|
||||||
or
|
|
||||||
operandTag instanceof StoreValueOperandTag and
|
|
||||||
result = this.getInstruction(LoadTag())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TranslatedAssignOperation extends TranslatedNonConstantExpr {
|
class TranslatedAssignOperation extends TranslatedNonConstantExpr {
|
||||||
override AssignOperation expr;
|
override AssignOperation expr;
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
|
|||||||
result = this.getInstruction(InitializerVariableAddressTag())
|
result = this.getInstruction(InitializerVariableAddressTag())
|
||||||
or
|
or
|
||||||
tag = InitializerVariableAddressTag() and
|
tag = InitializerVariableAddressTag() and
|
||||||
result = this.getChild(1).getFirstInstruction()
|
result = getChild(1).getFirstInstruction()
|
||||||
or
|
or
|
||||||
tag = ReturnTag() and
|
tag = ReturnTag() and
|
||||||
result = this.getInstruction(AliasedUseTag())
|
result = this.getInstruction(AliasedUseTag())
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ module InstructionConsistency {
|
|||||||
abstract Language::Location getLocation();
|
abstract Language::Location getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
private class PresentIRFunction extends OptionalIRFunction, TPresentIRFunction {
|
||||||
private IRFunction irFunc;
|
private IRFunction irFunc;
|
||||||
|
|
||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
@@ -37,8 +37,6 @@ module InstructionConsistency {
|
|||||||
result =
|
result =
|
||||||
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
min(Language::Location loc | loc = irFunc.getLocation() | loc order by loc.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
IRFunction getIRFunction() { result = irFunc }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
private class MissingIRFunction extends OptionalIRFunction, TMissingIRFunction {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ private import Imports::OperandTag
|
|||||||
private import Imports::Overlap
|
private import Imports::Overlap
|
||||||
private import Imports::TInstruction
|
private import Imports::TInstruction
|
||||||
private import Imports::RawIR as RawIR
|
private import Imports::RawIR as RawIR
|
||||||
private import SsaInstructions
|
private import SSAInstructions
|
||||||
private import SsaOperands
|
private import SSAOperands
|
||||||
private import NewIR
|
private import NewIR
|
||||||
|
|
||||||
private class OldBlock = Reachability::ReachableBlock;
|
private class OldBlock = Reachability::ReachableBlock;
|
||||||
|
|||||||
@@ -3,14 +3,7 @@ import semmle.code.cpp.ir.implementation.raw.internal.reachability.ReachableBloc
|
|||||||
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
|
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
|
||||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
|
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
|
||||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage
|
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage
|
||||||
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInstructions as SsaInstructions
|
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInstructions as SSAInstructions
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SsaInstructions */
|
|
||||||
deprecated module SSAInstructions = SsaInstructions;
|
|
||||||
|
|
||||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||||
import SimpleSSA as Alias
|
import SimpleSSA as Alias
|
||||||
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SsaOperands
|
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SSAOperands
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SsaOperands */
|
|
||||||
deprecated module SSAOperands = SsaOperands;
|
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ private class CallAllocationExpr extends AllocationExpr, FunctionCall {
|
|||||||
exists(target.getReallocPtrArg()) and
|
exists(target.getReallocPtrArg()) and
|
||||||
this.getArgument(target.getSizeArg()).getValue().toInt() = 0
|
this.getArgument(target.getSizeArg()).getValue().toInt() = 0
|
||||||
) and
|
) and
|
||||||
// these are modeled directly (and more accurately), avoid duplication
|
// these are modelled directly (and more accurately), avoid duplication
|
||||||
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
|
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ private class StdPair extends ClassTemplateInstantiation {
|
|||||||
StdPair() { this.hasQualifiedName(["std", "bsl"], "pair") }
|
StdPair() { this.hasQualifiedName(["std", "bsl"], "pair") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: This is now called `StdPair` and is a private part of the
|
||||||
|
* library implementation.
|
||||||
|
*/
|
||||||
|
deprecated class StdPairClass = StdPair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any of the single-parameter constructors of `std::pair` that takes a reference to an
|
* Any of the single-parameter constructors of `std::pair` that takes a reference to an
|
||||||
* instantiation of `std::pair`. These constructors allow conversion between pair types when the
|
* instantiation of `std::pair`. These constructors allow conversion between pair types when the
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ abstract class RemoteFlowSourceFunction extends Function {
|
|||||||
predicate hasSocketInput(FunctionInput input) { none() }
|
predicate hasSocketInput(FunctionInput input) { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: Use `RemoteFlowSourceFunction` instead.
|
||||||
|
*
|
||||||
|
* A library function that returns data that may be read from a network connection.
|
||||||
|
*/
|
||||||
|
deprecated class RemoteFlowFunction = RemoteFlowSourceFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A library function that returns data that is directly controlled by a user.
|
* A library function that returns data that is directly controlled by a user.
|
||||||
*/
|
*/
|
||||||
@@ -37,6 +44,13 @@ abstract class LocalFlowSourceFunction extends Function {
|
|||||||
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
|
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED: Use `LocalFlowSourceFunction` instead.
|
||||||
|
*
|
||||||
|
* A library function that returns data that is directly controlled by a user.
|
||||||
|
*/
|
||||||
|
deprecated class LocalFlowFunction = LocalFlowSourceFunction;
|
||||||
|
|
||||||
/** A library function that sends data over a network connection. */
|
/** A library function that sends data over a network connection. */
|
||||||
abstract class RemoteFlowSinkFunction extends Function {
|
abstract class RemoteFlowSinkFunction extends Function {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1573,7 +1573,7 @@ private module SimpleRangeAnalysisCached {
|
|||||||
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if the upper bound of `expr` may have been widened. This means the upper bound is in practice likely to be overly wide. */
|
/** Holds if the upper bound of `expr` may have been widened. This means the the upper bound is in practice likely to be overly wide. */
|
||||||
cached
|
cached
|
||||||
predicate upperBoundMayBeWidened(Expr e) {
|
predicate upperBoundMayBeWidened(Expr e) {
|
||||||
isRecursiveExpr(e) and
|
isRecursiveExpr(e) and
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ VariableAccess varUse(LocalScopeVariable v) { result = v.getAnAccess() }
|
|||||||
* Holds if `e` potentially overflows and `use` is an operand of `e` that is not guarded.
|
* Holds if `e` potentially overflows and `use` is an operand of `e` that is not guarded.
|
||||||
*/
|
*/
|
||||||
predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
||||||
// Since `e` is guaranteed to be a `BinaryArithmeticOperation`, a `UnaryArithmeticOperation` or
|
// Since `e` is guarenteed to be a `BinaryArithmeticOperation`, a `UnaryArithmeticOperation` or
|
||||||
// an `AssignArithmeticOperation` by the other constraints in this predicate, we know that
|
// an `AssignArithmeticOperation` by the other constraints in this predicate, we know that
|
||||||
// `convertedExprMightOverflowPositively` will have a result even when `e` is not analyzable
|
// `convertedExprMightOverflowPositively` will have a result even when `e` is not analyzable
|
||||||
// by `SimpleRangeAnalysis`.
|
// by `SimpleRangeAnalysis`.
|
||||||
@@ -80,7 +80,7 @@ predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
|||||||
* Holds if `e` potentially underflows and `use` is an operand of `e` that is not guarded.
|
* Holds if `e` potentially underflows and `use` is an operand of `e` that is not guarded.
|
||||||
*/
|
*/
|
||||||
predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) {
|
predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) {
|
||||||
// Since `e` is guaranteed to be a `BinaryArithmeticOperation`, a `UnaryArithmeticOperation` or
|
// Since `e` is guarenteed to be a `BinaryArithmeticOperation`, a `UnaryArithmeticOperation` or
|
||||||
// an `AssignArithmeticOperation` by the other constraints in this predicate, we know that
|
// an `AssignArithmeticOperation` by the other constraints in this predicate, we know that
|
||||||
// `convertedExprMightOverflowNegatively` will have a result even when `e` is not analyzable
|
// `convertedExprMightOverflowNegatively` will have a result even when `e` is not analyzable
|
||||||
// by `SimpleRangeAnalysis`.
|
// by `SimpleRangeAnalysis`.
|
||||||
|
|||||||
@@ -523,11 +523,6 @@ autoderivation(
|
|||||||
int derivation_type: @type ref
|
int derivation_type: @type ref
|
||||||
);
|
);
|
||||||
|
|
||||||
orphaned_variables(
|
|
||||||
int var: @localvariable ref,
|
|
||||||
int function: @function ref
|
|
||||||
)
|
|
||||||
|
|
||||||
enumconstants(
|
enumconstants(
|
||||||
unique int id: @enumconstant,
|
unique int id: @enumconstant,
|
||||||
int parent: @usertype ref,
|
int parent: @usertype ref,
|
||||||
@@ -904,7 +899,6 @@ case @attribute_arg.kind of
|
|||||||
| 1 = @attribute_arg_token
|
| 1 = @attribute_arg_token
|
||||||
| 2 = @attribute_arg_constant
|
| 2 = @attribute_arg_constant
|
||||||
| 3 = @attribute_arg_type
|
| 3 = @attribute_arg_type
|
||||||
| 4 = @attribute_arg_constant_expr
|
|
||||||
;
|
;
|
||||||
|
|
||||||
attribute_arg_value(
|
attribute_arg_value(
|
||||||
@@ -915,10 +909,6 @@ attribute_arg_type(
|
|||||||
unique int arg: @attribute_arg ref,
|
unique int arg: @attribute_arg ref,
|
||||||
int type_id: @type ref
|
int type_id: @type ref
|
||||||
);
|
);
|
||||||
attribute_arg_constant(
|
|
||||||
unique int arg: @attribute_arg ref,
|
|
||||||
int constant: @expr ref
|
|
||||||
)
|
|
||||||
attribute_arg_name(
|
attribute_arg_name(
|
||||||
unique int arg: @attribute_arg ref,
|
unique int arg: @attribute_arg ref,
|
||||||
string name: string ref
|
string name: string ref
|
||||||
@@ -1307,7 +1297,7 @@ funbind(
|
|||||||
|
|
||||||
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr
|
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr
|
||||||
|
|
||||||
@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr
|
@assign_expr = @assignexpr | @assign_op_expr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
case @allocator.form of
|
case @allocator.form of
|
||||||
@@ -1665,7 +1655,6 @@ case @expr.kind of
|
|||||||
| 332 = @hasuniqueobjectrepresentations
|
| 332 = @hasuniqueobjectrepresentations
|
||||||
| 333 = @builtinbitcast
|
| 333 = @builtinbitcast
|
||||||
| 334 = @builtinshuffle
|
| 334 = @builtinshuffle
|
||||||
| 335 = @blockassignexpr
|
|
||||||
;
|
;
|
||||||
|
|
||||||
@var_args_expr = @vastartexpr
|
@var_args_expr = @vastartexpr
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Support all constant attribute arguments
|
|
||||||
compatibility: partial
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Support block assignment
|
|
||||||
compatibility: backwards
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Add relation for orphaned local variables
|
|
||||||
compatibility: partial
|
|
||||||
@@ -1,17 +1,3 @@
|
|||||||
## 0.3.3
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
|
|
||||||
|
|
||||||
## 0.3.2
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* The query `cpp/bad-strncpy-size` now covers more `strncpy`-like functions than before, including `strxfrm`(`_l`), `wcsxfrm`(`_l`), and `stpncpy`. Users of this query may see an increase in results.
|
|
||||||
|
|
||||||
## 0.3.1
|
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class BooleanControllingAssignmentInExpr extends BooleanControllingAssignment {
|
|||||||
// if((a = b) && use_value(a)) { ... }
|
// if((a = b) && use_value(a)) { ... }
|
||||||
// ```
|
// ```
|
||||||
// where the assignment is meant to update the value of `a` before it's used in some other boolean
|
// where the assignment is meant to update the value of `a` before it's used in some other boolean
|
||||||
// subexpression that is guaranteed to be evaluate _after_ the assignment.
|
// subexpression that is guarenteed to be evaluate _after_ the assignment.
|
||||||
this.isParenthesised() and
|
this.isParenthesised() and
|
||||||
exists(LogicalAndExpr parent, Variable var, VariableAccess access |
|
exists(LogicalAndExpr parent, Variable var, VariableAccess access |
|
||||||
var = this.getLValue().(VariableAccess).getTarget() and
|
var = this.getLValue().(VariableAccess).getTarget() and
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ predicate illDefinedDecrForStmt(
|
|||||||
(
|
(
|
||||||
upperBound(initialCondition) < lowerBound(terminalCondition) and
|
upperBound(initialCondition) < lowerBound(terminalCondition) and
|
||||||
(
|
(
|
||||||
// exclude cases where the loop counter is `unsigned` (where wrapping behavior can be used deliberately)
|
// exclude cases where the loop counter is `unsigned` (where wrapping behaviour can be used deliberately)
|
||||||
v.getUnspecifiedType().(IntegralType).isSigned() or
|
v.getUnspecifiedType().(IntegralType).isSigned() or
|
||||||
initialCondition.getValue().toInt() = 0
|
initialCondition.getValue().toInt() = 0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -52,18 +52,6 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We disable flow into callables in this query as we'd otherwise get a result on this piece of code:
|
|
||||||
// ```cpp
|
|
||||||
// int* id(int* px) {
|
|
||||||
// return px; // this returns the local variable `x`, but it's fine as the local variable isn't declared in this scope.
|
|
||||||
// }
|
|
||||||
// void f() {
|
|
||||||
// int x;
|
|
||||||
// int* px = id(&x);
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
override predicate allowInterproceduralFlow() { none() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This configuration intentionally conflates addresses of fields and their object, and pointer offsets
|
* This configuration intentionally conflates addresses of fields and their object, and pointer offsets
|
||||||
* with their base pointer as this allows us to detect cases where an object's address flows to a
|
* with their base pointer as this allows us to detect cases where an object's address flows to a
|
||||||
@@ -89,6 +77,9 @@ from
|
|||||||
ReturnStackAllocatedMemoryConfig conf
|
ReturnStackAllocatedMemoryConfig conf
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
|
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
|
||||||
source.getNode().asInstruction() = var
|
source.getNode().asInstruction() = var and
|
||||||
|
// Only raise an alert if we're returning from the _same_ callable as the on that
|
||||||
|
// declared the stack variable.
|
||||||
|
var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
|
||||||
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
|
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
|
||||||
var.getAst().toString()
|
var.getAst().toString()
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import Buffer
|
import Buffer
|
||||||
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||||
private import semmle.code.cpp.models.implementations.Strcpy
|
|
||||||
|
|
||||||
predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) {
|
predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) {
|
||||||
// baseSize
|
// baseSize
|
||||||
@@ -42,6 +41,33 @@ predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate strncpyFunction(Function f, int argDest, int argSrc, int argLimit) {
|
||||||
|
exists(string name | name = f.getName() |
|
||||||
|
name =
|
||||||
|
[
|
||||||
|
"strcpy_s", // strcpy_s(dst, max_amount, src)
|
||||||
|
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
|
||||||
|
"_mbscpy_s" // _mbscpy_s(dst, max_amount, src)
|
||||||
|
] and
|
||||||
|
argDest = 0 and
|
||||||
|
argSrc = 2 and
|
||||||
|
argLimit = 1
|
||||||
|
or
|
||||||
|
name =
|
||||||
|
[
|
||||||
|
"strncpy", // strncpy(dst, src, max_amount)
|
||||||
|
"strncpy_l", // strncpy_l(dst, src, max_amount, locale)
|
||||||
|
"wcsncpy", // wcsncpy(dst, src, max_amount)
|
||||||
|
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
|
||||||
|
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
|
||||||
|
"_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale)
|
||||||
|
] and
|
||||||
|
argDest = 0 and
|
||||||
|
argSrc = 1 and
|
||||||
|
argLimit = 2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
string nthString(int num) {
|
string nthString(int num) {
|
||||||
num = 0 and
|
num = 0 and
|
||||||
result = "first"
|
result = "first"
|
||||||
@@ -70,13 +96,11 @@ int arrayExprFixedSize(Expr e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
from
|
from
|
||||||
StrcpyFunction f, FunctionCall fc, int argDest, int argSrc, int argLimit, int charSize,
|
Function f, FunctionCall fc, int argDest, int argSrc, int argLimit, int charSize, Access copyDest,
|
||||||
Access copyDest, Access copySource, string name, string nth
|
Access copySource, string name, string nth
|
||||||
where
|
where
|
||||||
f = fc.getTarget() and
|
f = fc.getTarget() and
|
||||||
argDest = f.getParamDest() and
|
strncpyFunction(f, argDest, argSrc, argLimit) and
|
||||||
argSrc = f.getParamSrc() and
|
|
||||||
argLimit = f.getParamSize() and
|
|
||||||
copyDest = fc.getArgument(argDest) and
|
copyDest = fc.getArgument(argDest) and
|
||||||
copySource = fc.getArgument(argSrc) and
|
copySource = fc.getArgument(argSrc) and
|
||||||
// Some of the functions operate on a larger char type, like `wchar_t`, so we
|
// Some of the functions operate on a larger char type, like `wchar_t`, so we
|
||||||
|
|||||||
@@ -106,26 +106,6 @@ predicate inheritanceConversionTypes(
|
|||||||
toType = convert.getResultType()
|
toType = convert.getResultType()
|
||||||
}
|
}
|
||||||
|
|
||||||
private signature class ConversionInstruction extends UnaryInstruction;
|
|
||||||
|
|
||||||
module Conversion<ConversionInstruction I> {
|
|
||||||
signature predicate hasTypes(I instr, Type fromType, Type toType);
|
|
||||||
|
|
||||||
module Using<hasTypes/3 project> {
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate hasOperandAndTypes(I convert, Instruction unary, Type fromType, Type toType) {
|
|
||||||
project(convert, fromType, toType) and
|
|
||||||
unary = convert.getUnary()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate hasObjectAndField(FieldAddressInstruction fai, Instruction object, Field f) {
|
|
||||||
fai.getObjectAddress() = object and
|
|
||||||
fai.getField() = f
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the HashCons value of an address computed by `instr`, if any. */
|
/** Gets the HashCons value of an address computed by `instr`, if any. */
|
||||||
TGlobalAddress globalAddress(Instruction instr) {
|
TGlobalAddress globalAddress(Instruction instr) {
|
||||||
result = TGlobalVariable(instr.(VariableAddressInstruction).getAstVariable())
|
result = TGlobalVariable(instr.(VariableAddressInstruction).getAstVariable())
|
||||||
@@ -137,27 +117,25 @@ TGlobalAddress globalAddress(Instruction instr) {
|
|||||||
result = TLoad(globalAddress(load.getSourceAddress()))
|
result = TLoad(globalAddress(load.getSourceAddress()))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Type fromType, Type toType, Instruction unary |
|
exists(ConvertInstruction convert, Type fromType, Type toType | instr = convert |
|
||||||
Conversion<ConvertInstruction>::Using<uncheckedConversionTypes/3>::hasOperandAndTypes(instr,
|
uncheckedConversionTypes(convert, fromType, toType) and
|
||||||
unary, fromType, toType) and
|
result = TConversion("unchecked", globalAddress(convert.getUnary()), fromType, toType)
|
||||||
result = TConversion("unchecked", globalAddress(unary), fromType, toType)
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Type fromType, Type toType, Instruction unary |
|
exists(CheckedConvertOrNullInstruction convert, Type fromType, Type toType | instr = convert |
|
||||||
Conversion<CheckedConvertOrNullInstruction>::Using<checkedConversionTypes/3>::hasOperandAndTypes(instr,
|
checkedConversionTypes(convert, fromType, toType) and
|
||||||
unary, fromType, toType) and
|
result = TConversion("checked", globalAddress(convert.getUnary()), fromType, toType)
|
||||||
result = TConversion("checked", globalAddress(unary), fromType, toType)
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Type fromType, Type toType, Instruction unary |
|
exists(InheritanceConversionInstruction convert, Type fromType, Type toType | instr = convert |
|
||||||
Conversion<InheritanceConversionInstruction>::Using<inheritanceConversionTypes/3>::hasOperandAndTypes(instr,
|
inheritanceConversionTypes(convert, fromType, toType) and
|
||||||
unary, fromType, toType) and
|
result = TConversion("inheritance", globalAddress(convert.getUnary()), fromType, toType)
|
||||||
result = TConversion("inheritance", globalAddress(unary), fromType, toType)
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(FieldAddressInstruction fai, Instruction object, Field f | instr = fai |
|
exists(FieldAddressInstruction fai | instr = fai |
|
||||||
hasObjectAndField(fai, object, f) and
|
result =
|
||||||
result = TFieldAddress(globalAddress(object), f)
|
TFieldAddress(globalAddress(pragma[only_bind_into](fai.getObjectAddress())),
|
||||||
|
pragma[only_bind_out](fai.getField()))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
|
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
|
||||||
@@ -290,11 +268,7 @@ class PathElement extends TPathElement {
|
|||||||
predicate isSink(IRBlock block) { exists(this.asSink(block)) }
|
predicate isSink(IRBlock block) { exists(this.asSink(block)) }
|
||||||
|
|
||||||
string toString() {
|
string toString() {
|
||||||
result =
|
result = [asStore().toString(), asCall(_).toString(), asMid().toString(), asSink(_).toString()]
|
||||||
[
|
|
||||||
this.asStore().toString(), this.asCall(_).toString(), this.asMid().toString(),
|
|
||||||
this.asSink(_).toString()
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate hasLocationInfo(
|
predicate hasLocationInfo(
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Make sure that all classes with virtual functions also have a virtual destructor
|
|||||||
S. Meyers. <em>Effective C++ 3d ed.</em> pp 40-44. Addison-Wesley Professional, 2005.
|
S. Meyers. <em>Effective C++ 3d ed.</em> pp 40-44. Addison-Wesley Professional, 2005.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://devblogs.microsoft.com/oldnewthing/20040507-00/?p=39443">When should your destructor be virtual?</a>
|
<a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx">When should your destructor be virtual?</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Count IR inconsistencies
|
|
||||||
* @description Counts the various IR inconsistencies that may occur.
|
|
||||||
* This query is for internal use only and may change without notice.
|
|
||||||
* @kind table
|
|
||||||
* @id cpp/count-ir-inconsistencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
import cpp
|
|
||||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
|
|
||||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IRConsistency as IRConsistency
|
|
||||||
|
|
||||||
class PresentIRFunction extends IRConsistency::PresentIRFunction {
|
|
||||||
override string toString() {
|
|
||||||
result = min(string name | name = this.getIRFunction().getFunction().getQualifiedName() | name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
select count(Instruction i | IRConsistency::missingOperand(i, _, _, _) | i) as missingOperand,
|
|
||||||
count(Instruction i | IRConsistency::unexpectedOperand(i, _, _, _) | i) as unexpectedOperand,
|
|
||||||
count(Instruction i | IRConsistency::duplicateOperand(i, _, _, _) | i) as duplicateOperand,
|
|
||||||
count(PhiInstruction i | IRConsistency::missingPhiOperand(i, _, _, _) | i) as missingPhiOperand,
|
|
||||||
count(Operand o | IRConsistency::missingOperandType(o, _, _, _) | o) as missingOperandType,
|
|
||||||
count(ChiInstruction i | IRConsistency::duplicateChiOperand(i, _, _, _) | i) as duplicateChiOperand,
|
|
||||||
count(Instruction i | IRConsistency::sideEffectWithoutPrimary(i, _, _, _) | i) as sideEffectWithoutPrimary,
|
|
||||||
count(Instruction i | IRConsistency::instructionWithoutSuccessor(i, _, _, _) | i) as instructionWithoutSuccessor,
|
|
||||||
count(Instruction i | IRConsistency::ambiguousSuccessors(i, _, _, _) | i) as ambiguousSuccessors,
|
|
||||||
count(Instruction i | IRConsistency::unexplainedLoop(i, _, _, _) | i) as unexplainedLoop,
|
|
||||||
count(PhiInstruction i | IRConsistency::unnecessaryPhiInstruction(i, _, _, _) | i) as unnecessaryPhiInstruction,
|
|
||||||
count(Instruction i | IRConsistency::memoryOperandDefinitionIsUnmodeled(i, _, _, _) | i) as memoryOperandDefinitionIsUnmodeled,
|
|
||||||
count(Operand o | IRConsistency::operandAcrossFunctions(o, _, _, _, _, _) | o) as operandAcrossFunctions,
|
|
||||||
count(IRFunction f | IRConsistency::containsLoopOfForwardEdges(f, _) | f) as containsLoopOfForwardEdges,
|
|
||||||
count(IRBlock i | IRConsistency::lostReachability(i, _, _, _) | i) as lostReachability,
|
|
||||||
count(string m | IRConsistency::backEdgeCountMismatch(_, m) | m) as backEdgeCountMismatch,
|
|
||||||
count(Operand o | IRConsistency::useNotDominatedByDefinition(o, _, _, _) | o) as useNotDominatedByDefinition,
|
|
||||||
count(SwitchInstruction i | IRConsistency::switchInstructionWithoutDefaultEdge(i, _, _, _) | i) as switchInstructionWithoutDefaultEdge,
|
|
||||||
count(Instruction i | IRConsistency::notMarkedAsConflated(i, _, _, _) | i) as notMarkedAsConflated,
|
|
||||||
count(Instruction i | IRConsistency::wronglyMarkedAsConflated(i, _, _, _) | i) as wronglyMarkedAsConflated,
|
|
||||||
count(MemoryOperand o | IRConsistency::invalidOverlap(o, _, _, _) | o) as invalidOverlap,
|
|
||||||
count(Instruction i | IRConsistency::nonUniqueEnclosingIRFunction(i, _, _, _) | i) as nonUniqueEnclosingIRFunction,
|
|
||||||
count(FieldAddressInstruction i | IRConsistency::fieldAddressOnNonPointer(i, _, _, _) | i) as fieldAddressOnNonPointer,
|
|
||||||
count(Instruction i | IRConsistency::thisArgumentIsNonPointer(i, _, _, _) | i) as thisArgumentIsNonPointer,
|
|
||||||
count(Instruction i | IRConsistency::nonUniqueIRVariable(i, _, _, _) | i) as nonUniqueIRVariable
|
|
||||||
@@ -21,9 +21,7 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
|||||||
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
||||||
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
|
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
|
||||||
|
|
||||||
/** An external API which is used with untrusted data. */
|
|
||||||
private newtype TExternalApi =
|
private newtype TExternalApi =
|
||||||
/** An untrusted API method `m` where untrusted data is passed at `index`. */
|
|
||||||
TExternalApiParameter(Function f, int index) {
|
TExternalApiParameter(Function f, int index) {
|
||||||
exists(UntrustedExternalApiDataNode n |
|
exists(UntrustedExternalApiDataNode n |
|
||||||
f = n.getExternalFunction() and
|
f = n.getExternalFunction() and
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
|||||||
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
||||||
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
|
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
|
||||||
|
|
||||||
/** An external API which is used with untrusted data. */
|
|
||||||
private newtype TExternalApi =
|
private newtype TExternalApi =
|
||||||
/** An untrusted API method `m` where untrusted data is passed at `index`. */
|
|
||||||
TExternalApiParameter(Function f, int index) {
|
TExternalApiParameter(Function f, int index) {
|
||||||
exists(UntrustedExternalApiDataNode n |
|
exists(UntrustedExternalApiDataNode n |
|
||||||
f = n.getExternalFunction() and
|
f = n.getExternalFunction() and
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import semmle.code.cpp.security.Security
|
|||||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||||
import semmle.code.cpp.ir.IR
|
import semmle.code.cpp.ir.IR
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking2
|
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import semmle.code.cpp.models.implementations.Strcat
|
import semmle.code.cpp.models.implementations.Strcat
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
@@ -84,32 +83,6 @@ class ExecState extends DataFlow::FlowState {
|
|||||||
DataFlow::Node getFstNode() { result = fst }
|
DataFlow::Node getFstNode() { result = fst }
|
||||||
|
|
||||||
DataFlow::Node getSndNode() { result = snd }
|
DataFlow::Node getSndNode() { result = snd }
|
||||||
|
|
||||||
/** Holds if this is a possible `ExecState` for `sink`. */
|
|
||||||
predicate isFeasibleForSink(DataFlow::Node sink) {
|
|
||||||
any(ExecStateConfiguration conf).hasFlow(snd, sink)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `TaintTracking` configuration that's used to find the relevant `ExecState`s for a
|
|
||||||
* given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
|
|
||||||
* `ExecTaintConfiguration::isSink`.
|
|
||||||
*/
|
|
||||||
class ExecStateConfiguration extends TaintTracking2::Configuration {
|
|
||||||
ExecStateConfiguration() { this = "ExecStateConfiguration" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(ExecState state | state.getSndNode() = source)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
shellCommand(sinkAsArgumentIndirection(sink), _)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
|
||||||
isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExecTaintConfiguration extends TaintTracking::Configuration {
|
class ExecTaintConfiguration extends TaintTracking::Configuration {
|
||||||
@@ -121,8 +94,8 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||||
any(ExecStateConfiguration conf).isSink(sink) and
|
shellCommand(sinkAsArgumentIndirection(sink), _) and
|
||||||
state.(ExecState).isFeasibleForSink(sink)
|
state instanceof ExecState
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(
|
override predicate isAdditionalTaintStep(
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import semmle.code.cpp.dataflow.DataFlow
|
|||||||
/**
|
/**
|
||||||
* A call to `SSL_get_verify_result`.
|
* A call to `SSL_get_verify_result`.
|
||||||
*/
|
*/
|
||||||
class SslGetVerifyResultCall extends FunctionCall {
|
class SSLGetVerifyResultCall extends FunctionCall {
|
||||||
SslGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
|
SSLGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +29,7 @@ class VerifyResultConfig extends DataFlow::Configuration {
|
|||||||
VerifyResultConfig() { this = "VerifyResultConfig" }
|
VerifyResultConfig() { this = "VerifyResultConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
override predicate isSource(DataFlow::Node source) {
|
||||||
source.asExpr() instanceof SslGetVerifyResultCall
|
source.asExpr() instanceof SSLGetVerifyResultCall
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
|
|||||||
@@ -17,33 +17,33 @@ import semmle.code.cpp.controlflow.IRGuards
|
|||||||
/**
|
/**
|
||||||
* A call to `SSL_get_peer_certificate`.
|
* A call to `SSL_get_peer_certificate`.
|
||||||
*/
|
*/
|
||||||
class SslGetPeerCertificateCall extends FunctionCall {
|
class SSLGetPeerCertificateCall extends FunctionCall {
|
||||||
SslGetPeerCertificateCall() {
|
SSLGetPeerCertificateCall() {
|
||||||
getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
|
getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr getSslArgument() { result = getArgument(0) }
|
Expr getSSLArgument() { result = getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A call to `SSL_get_verify_result`.
|
* A call to `SSL_get_verify_result`.
|
||||||
*/
|
*/
|
||||||
class SslGetVerifyResultCall extends FunctionCall {
|
class SSLGetVerifyResultCall extends FunctionCall {
|
||||||
SslGetVerifyResultCall() {
|
SSLGetVerifyResultCall() {
|
||||||
getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
|
getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr getSslArgument() { result = getArgument(0) }
|
Expr getSSLArgument() { result = getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
|
* Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
|
||||||
* `SSL_get_verify_result` entering `node`.
|
* `SSL_get_verify_result` entering `node`.
|
||||||
*/
|
*/
|
||||||
predicate resultIsChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
predicate resultIsChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
||||||
exists(Expr ssl, SslGetVerifyResultCall check |
|
exists(Expr ssl, SSLGetVerifyResultCall check |
|
||||||
ssl = globalValueNumber(getCertCall.getSslArgument()).getAnExpr() and
|
ssl = globalValueNumber(getCertCall.getSSLArgument()).getAnExpr() and
|
||||||
ssl = check.getSslArgument() and
|
ssl = check.getSSLArgument() and
|
||||||
node = check
|
node = check
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ predicate resultIsChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode
|
|||||||
* `0` on the edge `node1` to `node2`.
|
* `0` on the edge `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
predicate certIsZero(
|
predicate certIsZero(
|
||||||
SslGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
|
SSLGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
|
||||||
) {
|
) {
|
||||||
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
|
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
|
||||||
exists(GuardCondition guard, Expr zero |
|
exists(GuardCondition guard, Expr zero |
|
||||||
@@ -87,7 +87,7 @@ predicate certIsZero(
|
|||||||
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
|
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
|
||||||
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
|
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
|
||||||
*/
|
*/
|
||||||
predicate certNotChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
||||||
// cert is not checked at the call to `SSL_get_peer_certificate`
|
// cert is not checked at the call to `SSL_get_peer_certificate`
|
||||||
node = getCertCall
|
node = getCertCall
|
||||||
or
|
or
|
||||||
@@ -112,7 +112,7 @@ predicate certNotChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
from SslGetPeerCertificateCall getCertCall, ControlFlowNode node
|
from SSLGetPeerCertificateCall getCertCall, ControlFlowNode node
|
||||||
where
|
where
|
||||||
certNotChecked(getCertCall, node) and
|
certNotChecked(getCertCall, node) and
|
||||||
node instanceof Function // (function exit)
|
node instanceof Function // (function exit)
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ class ToBufferConfiguration extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
exists(BufferWrite::BufferWrite w | w.getASource() = sink.asExpr())
|
exists(BufferWrite::BufferWrite w | w.getASource() = sink.asExpr())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,17 +47,14 @@ class EnvData extends SystemData {
|
|||||||
/**
|
/**
|
||||||
* Data originating from a call to `mysql_get_client_info()`.
|
* Data originating from a call to `mysql_get_client_info()`.
|
||||||
*/
|
*/
|
||||||
class SqlClientInfo extends SystemData {
|
class SQLClientInfo extends SystemData {
|
||||||
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||||
|
|
||||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||||
|
|
||||||
override predicate isSensitive() { any() }
|
override predicate isSensitive() { any() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SqlClientInfo */
|
|
||||||
deprecated class SQLClientInfo = SqlClientInfo;
|
|
||||||
|
|
||||||
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
||||||
(
|
(
|
||||||
source.getTarget().hasName("mysql_connect") or
|
source.getTarget().hasName("mysql_connect") or
|
||||||
@@ -69,17 +66,14 @@ private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
|||||||
/**
|
/**
|
||||||
* Data passed into an SQL connect function.
|
* Data passed into an SQL connect function.
|
||||||
*/
|
*/
|
||||||
class SqlConnectInfo extends SystemData {
|
class SQLConnectInfo extends SystemData {
|
||||||
SqlConnectInfo() { sqlConnectInfo(this, _) }
|
SQLConnectInfo() { sqlConnectInfo(this, _) }
|
||||||
|
|
||||||
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
|
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
|
||||||
|
|
||||||
override predicate isSensitive() { any() }
|
override predicate isSensitive() { any() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for SqlConnectInfo */
|
|
||||||
deprecated class SQLConnectInfo = SqlConnectInfo;
|
|
||||||
|
|
||||||
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
|
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||||
// size_t confstr(int name, char *buf, size_t len)
|
// size_t confstr(int name, char *buf, size_t len)
|
||||||
// - various OS / system strings, such as the libc version
|
// - various OS / system strings, such as the libc version
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
## 0.3.1
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
## 0.3.2
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* The query `cpp/bad-strncpy-size` now covers more `strncpy`-like functions than before, including `strxfrm`(`_l`), `wcsxfrm`(`_l`), and `stpncpy`. Users of this query may see an increase in results.
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
## 0.3.3
|
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
|
||||||
|
|
||||||
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.3.3
|
lastReleaseVersion: 0.3.0
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user