Compare commits

..

17 Commits

Author SHA1 Message Date
Henry Mercer
2c9e3b5ea2 Remove NoSQL sinks since September 2018 2022-02-04 09:23:56 +00:00
Esben Sparre Andreasen
b2c900f75e Remove additional Xss sinks 2022-02-04 09:23:56 +00:00
Esben Sparre Andreasen
475a2b5354 Remove additional SQL sinks 2022-02-04 09:23:55 +00:00
Esben Sparre Andreasen
63a648dc41 Remove additional path-injection sinks 2022-02-04 09:23:55 +00:00
Esben Sparre Andreasen
999de74f49 Add benjamin-button.md 2022-02-04 09:23:55 +00:00
Esben Sparre Andreasen
2f6a3ac5b1 Remove 2020 sinks from SqlInjection.ql 2022-02-04 09:23:51 +00:00
Esben Sparre Andreasen
c9609085b1 Remove 2020 sinks from TaintedPath.ql 2022-02-04 09:22:48 +00:00
Max Schaefer
7e3df53c56 Revert "JS: Recognize DomSanitizer from @angular/core"
This reverts commit ff1d0cc4c7.
2022-02-04 09:22:48 +00:00
Henry Mercer
68a1c06750 Remove NoSQL sinks since September 2018 2022-02-04 09:22:48 +00:00
Esben Sparre Andreasen
55b877ec07 Remove additional Xss sinks 2022-02-04 09:22:48 +00:00
Esben Sparre Andreasen
5dad9c0ccd Remove additional SQL sinks 2022-02-04 09:22:47 +00:00
Esben Sparre Andreasen
db00d0f369 Remove additional path-injection sinks 2022-02-04 09:22:47 +00:00
Esben Sparre Andreasen
a31e51a564 Add benjamin-button.md 2022-02-04 09:22:47 +00:00
Esben Sparre Andreasen
04b93e6762 Remove pseudo-properties 2022-02-04 09:22:47 +00:00
Esben Sparre Andreasen
21677eced0 Remove 2020 sinks from SqlInjection.ql 2022-02-04 09:22:47 +00:00
Esben Sparre Andreasen
714978494f Remove 2020 sinks from Xss.ql 2022-02-04 09:22:46 +00:00
Esben Sparre Andreasen
24017151c7 Remove 2020 sinks from TaintedPath.ql 2022-02-04 09:22:46 +00:00
1505 changed files with 52586 additions and 277857 deletions

View File

@@ -4,10 +4,8 @@
"*/ql/lib/qlpack.yml",
"*/ql/test/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/ql/consistency-queries/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/lib/qlpack.yml",
"csharp/ql/campaigns/Solorigate/src/qlpack.yml",
@@ -15,6 +13,8 @@
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",
"ruby/extractor-pack/codeql-extractor.yml",
"ruby/ql/consistency-queries/qlpack.yml",
"ql/ql/consistency-queries/qlpack.yml",
"ql/extractor-pack/codeql-extractor.yml"
],
"versionPolicies": {

13
.gitattributes vendored
View File

@@ -50,15 +50,4 @@
*.pdb -text
java/ql/test/stubs/**/*.java linguist-generated=true
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
# For some languages, upgrade script testing references really old dbscheme
# files from legacy upgrades that have CRLF line endings. Since upgrade
# resolution relies on object hashes, we must suppress line ending conversion
# for those testing dbscheme files.
*/ql/lib/upgrades/initial/*.dbscheme -text
# Generated test files - these are synced from the standard JavaScript libraries using
# `javascript/ql/experimental/adaptivethreatmodeling/test/update_endpoint_test_files.py`.
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.js linguist-generated=true -merge
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.ts linguist-generated=true -merge
java/ql/test/experimental/stubs/**/*.java linguist-generated=true

View File

@@ -6,11 +6,8 @@ on:
paths:
- "*/ql/src/**/*.ql"
- "*/ql/src/**/*.qll"
- "*/ql/lib/**/*.ql"
- "*/ql/lib/**/*.qll"
- "!**/experimental/**"
- "!ql/**"
- ".github/workflows/check-change-note.yml"
jobs:
check-change-note:

View File

@@ -27,11 +27,6 @@ jobs:
pull-requests: read
steps:
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.101
- name: Checkout repository
uses: actions/checkout@v2
@@ -56,7 +51,7 @@ jobs:
# uses a compiled language
- run: |
dotnet build csharp /p:UseSharedCompilation=false
dotnet build csharp
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main

View File

@@ -1,43 +0,0 @@
name: "Publish framework coverage as metrics"
on:
schedule:
- cron: '5 0 * * *'
push:
branches:
- main
workflow_dispatch:
pull_request:
branches:
- main
paths:
- ".github/workflows/csv-coverage-metrics.yml"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
- name: Create empty database
run: |
DATABASE="${{ runner.temp }}/java-database"
PROJECT="${{ runner.temp }}/java-project"
mkdir -p "$PROJECT/src/tmp/empty"
echo "class Empty {}" >> "$PROJECT/src/tmp/empty/Empty.java"
codeql database create "$DATABASE" --language=java --source-root="$PROJECT" --command 'javac src/tmp/empty/Empty.java'
- name: Capture coverage information
run: |
DATABASE="${{ runner.temp }}/java-database"
codeql database analyze --format=sarif-latest --output=metrics.sarif -- "$DATABASE" ./java/ql/src/Metrics/Summaries/FrameworkCoverage.ql
- uses: actions/upload-artifact@v2
with:
name: metrics.sarif
path: metrics.sarif
retention-days: 20
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: metrics.sarif

View File

@@ -1,76 +0,0 @@
name: JS ML-powered queries tests
on:
push:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
branches:
- main
- "rc/*"
pull_request:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
defaults:
run:
working-directory: javascript/ql/experimental/adaptivethreatmodeling
jobs:
qlformat:
name: Check QL formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: |
find . "(" -name "*.ql" -or -name "*.qll" ")" -print0 | \
xargs -0 codeql query format --check-only
qlcompile:
name: Check QL compilation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Install pack dependencies
run: |
for pack in modelbuilding src; do
codeql pack install --mode verify -- "${pack}"
done
- name: Check QL compilation
run: |
codeql query compile \
--check-only \
--ram 5120 \
--additional-packs "${{ github.workspace }}" \
--threads=0 \
-- \
lib modelbuilding src
qltest:
name: Run QL tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Install pack dependencies
run: codeql pack install -- test
- name: Run QL tests
run: |
codeql test run \
--threads=0 \
--ram 5120 \
--additional-packs "${{ github.workspace }}" \
-- \
test

View File

@@ -1,103 +0,0 @@
name: Models as Data - Diff
on:
workflow_dispatch:
inputs:
projects:
description: "The projects to generate models for"
required: true
default: '["netty/netty"]'
pull_request:
branches:
- main
paths:
- "java/ql/src/utils/model-generator/**/*.*"
- ".github/workflows/mad_modelDiff.yml"
permissions:
contents: read
jobs:
model-diff:
name: Model Difference
runs-on: ubuntu-latest
if: github.repository == 'github/codeql'
strategy:
matrix:
slug: ${{fromJson(github.event.inputs.projects || '["apache/commons-codec", "apache/commons-io", "apache/commons-beanutils", "apache/commons-logging", "apache/commons-fileupload", "apache/commons-lang", "apache/commons-validator", "apache/commons-csv", "apache/dubbo"]' )}}
steps:
- name: Clone github/codeql from PR
uses: actions/checkout@v2
if: github.event.pull_request
with:
path: codeql-pr
- name: Clone github/codeql from main
uses: actions/checkout@v2
with:
path: codeql-main
ref: main
- uses: ./codeql-main/.github/actions/fetch-codeql
- name: Download database
env:
SLUG: ${{ matrix.slug }}
run: |
set -x
mkdir lib-dbs
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
projectId=`curl -s https://lgtm.com/api/v1.0/projects/g/${SLUG} | jq .id`
curl -L "https://lgtm.com/api/v1.0/snapshots/$projectId/java" -o "$SHORTNAME.zip"
unzip -q -d "${SHORTNAME}-db" "${SHORTNAME}.zip"
mkdir "lib-dbs/$SHORTNAME/"
mv "${SHORTNAME}-db/"$(ls -1 "${SHORTNAME}"-db)/* "lib-dbs/${SHORTNAME}/"
- name: Generate Models (PR and main)
run: |
set -x
mkdir tmp-models
MODELS=`pwd`/tmp-models
DATABASES=`pwd`/lib-dbs
analyzeDatabaseWithCheckout() {
QL_VARIANT=$1
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/model-generator/GenerateFlowModel.py $DATABASE $MODELS/${SHORTNAME}.qll
mv $MODELS/${SHORTNAME}.qll $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.qll
cd ..
}
for d in $DATABASES/*/ ; do
ls -1 "$d"
analyzeDatabaseWithCheckout "main" $d
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]
then
analyzeDatabaseWithCheckout "pr" $d
fi
done
- name: Install diff2html
if: github.event.pull_request
run: |
npm install -g diff2html-cli
- name: Generate Model Diff
if: github.event.pull_request
run: |
set -x
MODELS=`pwd`/tmp-models
ls -1 tmp-models/
for m in $MODELS/*_main.qll ; do
t="${m/main/"pr"}"
basename=`basename $m`
name="diff_${basename/_main.qll/""}"
(diff -w -u $m $t | diff2html -i stdin -F $MODELS/$name.html) || true
done
- uses: actions/upload-artifact@v2
with:
name: models
path: tmp-models/*.qll
retention-days: 20
- uses: actions/upload-artifact@v2
with:
name: diffs
path: tmp-models/*.html
retention-days: 20

View File

@@ -1,62 +0,0 @@
name: Regenerate framework models
on:
workflow_dispatch:
schedule:
- cron: "30 2 * * *"
pull_request:
branches:
- main
paths:
- ".github/workflows/mad_regenerate-models.yml"
jobs:
regenerate-models:
runs-on: ubuntu-latest
strategy:
matrix:
# placeholder required for each axis, excluded below, replaced by the actual combinations (see include)
slug: ["placeholder"]
ref: ["placeholder"]
include:
- slug: "apache/commons-io"
ref: "8985de8fe74f6622a419b37a6eed0dbc484dc128"
exclude:
- slug: "placeholder"
ref: "placeholder"
steps:
- name: Clone self (github/codeql)
uses: actions/checkout@v2
- name: Setup CodeQL binaries
uses: ./.github/actions/fetch-codeql
- name: Clone repositories
uses: actions/checkout@v2
with:
path: repos/${{ matrix.ref }}
ref: ${{ matrix.ref }}
repository: ${{ matrix.slug }}
- name: Build database
env:
SLUG: ${{ matrix.slug }}
REF: ${{ matrix.ref }}
run: |
mkdir dbs
cd repos/${REF}
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
codeql database create --language=java ../../dbs/${SHORTNAME}
- name: Regenerate models in-place
env:
SLUG: ${{ matrix.slug }}
run: |
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
java/ql/src/utils/model-generator/RegenerateModels.py "${SLUG}" dbs/${SHORTNAME}
- name: Stage changes
run: |
find java -name "*.qll" -print0 | xargs -0 git add
git status
git diff --cached > models.patch
- uses: actions/upload-artifact@v2
with:
name: patch
path: models.patch
retention-days: 7

View File

@@ -31,13 +31,13 @@ jobs:
uses: actions/cache@v2
with:
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 }}
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}
- name: Build query pack
if: steps.cache-queries.outputs.cache-hit != 'true'
run: |
cd ql/ql/src
"${CODEQL}" pack create
cd .codeql/pack/codeql/ql/0.0.0
cd .codeql/pack/codeql/ql-all/0.0.0
zip "${PACKZIP}" -r .
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
@@ -189,11 +189,4 @@ jobs:
uses: github/codeql-action/analyze@erik-krogh/ql
with:
category: "ql-for-ql-${{ matrix.folder }}"
- name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./${{ matrix.folder }}.sarif
- name: Sarif as artifact
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.folder }}.sarif
path: ${{ matrix.folder }}.sarif

View File

@@ -17,7 +17,7 @@ jobs:
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
strategy:
matrix:
repo:
repo:
- github/codeql
- github/codeql-go
runs-on: ubuntu-latest
@@ -35,7 +35,7 @@ jobs:
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
env:

View File

@@ -29,24 +29,24 @@ jobs:
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build extractor
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh
- name: Run QL tests
run: |
run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL formatting
run: |
run: |
find ql/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL compilation
run: |
run: |
"${CODEQL}" query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ql/extractor-pack" "ql/ql/src" "ql/ql/examples"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}

View File

@@ -50,7 +50,7 @@ jobs:
~/.cargo/registry
~/.cargo/git
ruby/target
key: ${{ runner.os }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Build

View File

@@ -24,53 +24,27 @@ defaults:
working-directory: ruby
jobs:
qlformat:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
qlcompile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=0 --ram 5000 --warnings=error "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
qlupgrade:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme
- name: Check DB downgrade scripts
run: |
echo >empty.trap
rm -rf testdb; codeql dataset import -S ql/lib/ruby.dbscheme testdb empty.trap
codeql resolve upgrades --format=lines --allow-downgrades --additional-packs downgrades \
--dbscheme=ql/lib/ruby.dbscheme --target-dbscheme=downgrades/initial/ruby.dbscheme |
xargs codeql execute upgrades testdb
diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme
qltest:
runs-on: ubuntu-latest
strategy:
matrix:
slice: ["1/2", "2/2"]
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- uses: ./ruby/actions/create-extractor-pack
- name: Run QL tests
run: |
codeql test run --threads=0 --ram 5000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
codeql test run --threads=0 --ram 5000 --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=0 --ram 5000 --warnings=error "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme

View File

@@ -1,29 +0,0 @@
name: Validate change notes
on:
push:
paths:
- "*/ql/*/change-notes/**/*"
- ".github/workflows/validate-change-notes.yml"
branches:
- main
- "rc/*"
pull_request:
paths:
- "*/ql/*/change-notes/**/*"
- ".github/workflows/validate-change-notes.yml"
jobs:
check-change-note:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
- name: Fail if there are any errors with existing change notes
run: |
codeql pack release --groups cpp,csharp,java,javascript,python,ruby,-examples,-test,-experimental

View File

@@ -13,9 +13,6 @@
/python/**/experimental/**/* @github/codeql-python @xcorail
/ruby/**/experimental/**/* @github/codeql-ruby @xcorail
# ML-powered queries
/javascript/ql/experimental/adaptivethreatmodeling/ @github/codeql-ml-powered-queries-reviewers
# Notify members of codeql-go about PRs to the shared data-flow library files
/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @github/codeql-java @github/codeql-go
/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @github/codeql-java @github/codeql-go
@@ -30,4 +27,4 @@
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
# QL for QL reviewers
/ql/ @github/codeql-ql-for-ql-reviewers
/ql/ @github/codeql-ql-for-ql-reviewers

51
benjamin-button.md Normal file
View File

@@ -0,0 +1,51 @@
# benjamin-buttons.md
This file describes the changes that have been applied to
the library to make it behave as if it was younger.
## TaintedPath.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+pathinjection
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+tainted-path
Sinks from the "graceful-fs" and "fs-extra" (added before the open-sourcing squash).
## Xss.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- recursive type tracking for `jQuery::dollar`, `DOM::domValueRef`.
## SqlInjection.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sql
TypeTracking in SQL.qll (added before the open-sourcing squash)
The model of `mssql` and `sequelize` (added before the open-sourcing squash)
## PseudoProperties
Pseudo-properties (`$name$`) used in type-tracking and global dataflow configurations have been disabled.
Found by searching for `"\$.*\$"`.

View File

@@ -465,8 +465,7 @@
],
"SensitiveDataHeuristics Python/JS": [
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll",
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll"
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll"
],
"ReDoS Util Python/JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
@@ -502,11 +501,5 @@
"javascript/ql/lib/tutorial.qll",
"python/ql/lib/tutorial.qll",
"ruby/ql/lib/tutorial.qll"
],
"AccessPathSyntax": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
]
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
<ApplicationIcon />

View File

@@ -31,7 +31,6 @@
+ semmlecode-cpp-queries/Critical/NewArrayDeleteMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewDeleteArrayMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewFreeMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql: /Correctness/Common Errors
# Use of Libraries
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql: /Correctness/Use of Libraries
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/SuspiciousSizeof.ql: /Correctness/Use of Libraries

View File

@@ -34,7 +34,6 @@
+ semmlecode-cpp-queries/Critical/NewArrayDeleteMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewDeleteArrayMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewFreeMismatch.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql: /Correctness/Common Errors
# Exceptions
+ semmlecode-cpp-queries/Best Practices/Exceptions/AccidentalRethrow.ql: /Correctness/Exceptions
+ semmlecode-cpp-queries/Best Practices/Exceptions/CatchingByValue.ql: /Correctness/Exceptions

View File

@@ -1,2 +0,0 @@
description: Remove unused legacy relations
compatibility: backwards

View File

@@ -1,3 +0,0 @@
description: Add relation for tracking variables from structured binding declarations
compatibility: full
is_structured_binding.rel: delete

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
name: codeql/cpp-downgrades
groups: cpp
downgrades: .
library: true

View File

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

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `codeql/cpp-upgrades` CodeQL pack has been removed. All upgrades scripts have been merged into the `codeql/cpp-all` CodeQL pack.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
more accurate length for integers formatted with `%x`

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added a `isStructuredBinding` predicate to the `Variable` class which holds when the variable is declared as part of a structured binding declaration.

View File

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

View File

@@ -1,2 +0,0 @@
## 0.0.9

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.9
lastReleaseVersion: 0.0.7

View File

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

View File

@@ -169,12 +169,6 @@ class Variable extends Declaration, @variable {
variable_instantiation(underlyingElement(this), unresolveElement(v))
}
/**
* Holds if this variable is declated as part of a structured binding
* declaration. For example, `x` in `auto [x, y] = ...`.
*/
predicate isStructuredBinding() { is_structured_binding(underlyingElement(this)) }
/**
* Holds if this is a compiler-generated variable. For example, a
* [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for)

View File

@@ -11,10 +11,10 @@ import cpp
*/
bindingset[input]
int parseOctal(string input) {
input.regexpMatch("0[0-7]+") and
input.charAt(0) = "0" and
result =
strictsum(int ix |
ix in [1 .. input.length()]
ix in [0 .. input.length()]
|
8.pow(input.length() - (ix + 1)) * input.charAt(ix).toInt()
)

View File

@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** A `Content` tagged with the type of a containing object. */
/** Content tagged with the type of a containing object. */
class TypedContent extends MkTypedContent {
private Content c;
private DataFlowType t;

View File

@@ -592,14 +592,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
* Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**

View File

@@ -353,9 +353,9 @@ module FlowVar_internal {
// indirection.
result = def.getAUse(v)
or
exists(SsaDefinition descendantDef |
this.getASuccessorSsaVar+() = TSsaVar(descendantDef, _) and
result = descendantDef.getAUse(v)
exists(SsaDefinition descendentDef |
this.getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
result = descendentDef.getAUse(v)
)
)
or

View File

@@ -124,14 +124,12 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
* Holds if taint may propagate from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}

View File

@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** A `Content` tagged with the type of a containing object. */
/** Content tagged with the type of a containing object. */
class TypedContent extends MkTypedContent {
private Content c;
private DataFlowType t;

View File

@@ -1032,14 +1032,12 @@ SideEffectInstruction getSideEffectFor(CallInstruction call, int argument) {
* Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localInstructionFlow(Instruction e1, Instruction e2) {
localFlow(instructionNode(e1), instructionNode(e2))
}
@@ -1048,7 +1046,6 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
private newtype TContent =

View File

@@ -121,14 +121,12 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst
* Holds if taint may propagate from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localInstructionTaint(Instruction i1, Instruction i2) {
localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2))
}
@@ -137,7 +135,6 @@ predicate localInstructionTaint(Instruction i1, Instruction i2) {
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}

View File

@@ -200,7 +200,7 @@ class IRBlock extends IRBlockBase {
* post-dominate block `B`, but block `A` does post-dominate an immediate successor of block `B`.
*/
pragma[noinline]
final IRBlock postDominanceFrontier() {
final IRBlock postPominanceFrontier() {
this.postDominates(result.getASuccessor()) and
not this.strictlyPostDominates(result)
}

View File

@@ -200,7 +200,7 @@ class IRBlock extends IRBlockBase {
* post-dominate block `B`, but block `A` does post-dominate an immediate successor of block `B`.
*/
pragma[noinline]
final IRBlock postDominanceFrontier() {
final IRBlock postPominanceFrontier() {
this.postDominates(result.getASuccessor()) and
not this.strictlyPostDominates(result)
}

View File

@@ -567,13 +567,6 @@ newtype TTranslatedElement =
} or
// The initialization of a base class from within a constructor.
TTranslatedConstructorBaseInit(ConstructorBaseInit init) { not ignoreExpr(init) } or
// Workaround for a case where no base constructor is generated but a targetless base
// constructor call is present.
TTranslatedConstructorBareInit(ConstructorInit init) {
not ignoreExpr(init) and
not init instanceof ConstructorBaseInit and
not init instanceof ConstructorFieldInit
} or
// The destruction of a base class from within a destructor.
TTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) {
not ignoreExpr(destruction)

View File

@@ -573,11 +573,6 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
baseInit = func.(Constructor).getInitializer(id) and
result = getTranslatedConstructorBaseInit(baseInit)
)
or
exists(ConstructorInit bareInit |
bareInit = func.(Constructor).getInitializer(id) and
result = getTranslatedConstructorBareInit(bareInit)
)
}
override Instruction getFirstInstruction() {

View File

@@ -917,36 +917,3 @@ class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall,
final override string toString() { result = "destroy base: " + call.toString() }
}
/**
* A constructor base init call where no base constructor has been generated.
*
* Workaround for an extractor issue.
*/
class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstructorBareInit {
ConstructorInit init;
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
override Locatable getAST() { result = init }
final override string toString() { result = "construct base (no constructor)" }
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
override TranslatedElement getChild(int id) { none() }
override Function getFunction() { result = getParent().getFunction() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
result.getAST() = init
}

View File

@@ -200,7 +200,7 @@ class IRBlock extends IRBlockBase {
* post-dominate block `B`, but block `A` does post-dominate an immediate successor of block `B`.
*/
pragma[noinline]
final IRBlock postDominanceFrontier() {
final IRBlock postPominanceFrontier() {
this.postDominates(result.getASuccessor()) and
not this.strictlyPostDominates(result)
}

View File

@@ -11,14 +11,15 @@ import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.FlowSource
/**
* The standard functions `fgets` and `fgetws`.
* The standard functions `gets` and `fgets`.
*/
private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
SideEffectFunction, RemoteFlowSourceFunction {
FgetsFunction() {
GetsFunction() {
// gets(str)
// fgets(str, num, stream)
// fgetws(wstr, num, stream)
this.hasGlobalOrStdOrBslName(["fgets", "fgetws"])
this.hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -50,61 +51,20 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
or
output.isReturnValue() and
description = "String read by " + this.getName()
}
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
not this.hasName("gets") and
bufParam = 0 and
countParam = 1
}
override predicate hasArrayWithUnknownSize(int bufParam) {
this.hasName("gets") and
bufParam = 0
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasSocketInput(FunctionInput input) { input.isParameterDeref(2) }
}
/**
* The standard functions `gets`.
*/
private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction,
SideEffectFunction, LocalFlowSourceFunction {
GetsFunction() {
// gets(str)
this.hasGlobalOrStdOrBslName("gets")
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isReturnValue()
}
override predicate parameterNeverEscapes(int index) { none() }
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and
buffer = true and
mustWrite = true
}
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
or
output.isReturnValue() and
description = "String read by " + this.getName()
}
override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = 0 }
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
}

View File

@@ -135,11 +135,52 @@ externalData(
string value : string ref
);
/**
* The date of the snapshot.
*/
snapshotDate(unique date snapshotDate : date ref);
/**
* The source location of the snapshot.
*/
sourceLocationPrefix(string prefix : string ref);
/**
* Data used by the 'duplicate code' detection.
*/
duplicateCode(
unique int id : @duplication,
string relativePath : string ref,
int equivClass : int ref
);
/**
* Data used by the 'similar code' detection.
*/
similarCode(
unique int id : @similarity,
string relativePath : string ref,
int equivClass : int ref
);
/**
* Data used by the 'duplicate code' and 'similar code' detection.
*/
@duplication_or_similarity = @duplication | @similarity
/**
* Data used by the 'duplicate code' and 'similar code' detection.
*/
#keyset[id, offset]
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref
);
/**
* Information about packages that provide code used during compilation.
* The `id` is just a unique identifier.
@@ -446,7 +487,6 @@ var_decl_specifiers(
int id: @var_decl ref,
string name: string ref
)
is_structured_binding(unique int id: @variable ref);
type_decls(
unique int id: @type_decl,

File diff suppressed because it is too large Load Diff

View File

@@ -6,22 +6,122 @@
*/
class Person extends string {
Person() {
this =
[
"Ronil", "Dina", "Ravi", "Bruce", "Jo", "Aida", "Esme", "Charlie", "Fred", "Meera", "Maya",
"Chad", "Tiana", "Laura", "George", "Will", "Mary", "Almira", "Susannah", "Rhoda",
"Cynthia", "Eunice", "Olive", "Virginia", "Angeline", "Helen", "Cornelia", "Harriet",
"Mahala", "Abby", "Margaret", "Deb", "Minerva", "Severus", "Lavina", "Adeline", "Cath",
"Elisa", "Lucretia", "Anne", "Eleanor", "Joanna", "Adam", "Agnes", "Rosanna", "Clara",
"Melissa", "Amy", "Isabel", "Jemima", "Cordelia", "Melinda", "Delila", "Jeremiah", "Elijah",
"Hester", "Walter", "Oliver", "Hugh", "Aaron", "Reuben", "Eli", "Amos", "Augustus",
"Theodore", "Ira", "Timothy", "Cyrus", "Horace", "Simon", "Asa", "Frank", "Nelson",
"Leonard", "Harrison", "Anthony", "Louis", "Milton", "Noah", "Cornelius", "Abdul", "Warren",
"Harvey", "Dennis", "Wesley", "Sylvester", "Gilbert", "Sullivan", "Edmund", "Wilson",
"Perry", "Matthew", "Simba", "Nala", "Rafiki", "Shenzi", "Ernest", "Gertrude", "Oscar",
"Lilian", "Raymond", "Elgar", "Elmer", "Herbert", "Maude", "Mae", "Otto", "Edwin",
"Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel", "King Basil", "Stephen"
]
this = "Ronil" or
this = "Dina" or
this = "Ravi" or
this = "Bruce" or
this = "Jo" or
this = "Aida" or
this = "Esme" or
this = "Charlie" or
this = "Fred" or
this = "Meera" or
this = "Maya" or
this = "Chad" or
this = "Tiana" or
this = "Laura" or
this = "George" or
this = "Will" or
this = "Mary" or
this = "Almira" or
this = "Susannah" or
this = "Rhoda" or
this = "Cynthia" or
this = "Eunice" or
this = "Olive" or
this = "Virginia" or
this = "Angeline" or
this = "Helen" or
this = "Cornelia" or
this = "Harriet" or
this = "Mahala" or
this = "Abby" or
this = "Margaret" or
this = "Deb" or
this = "Minerva" or
this = "Severus" or
this = "Lavina" or
this = "Adeline" or
this = "Cath" or
this = "Elisa" or
this = "Lucretia" or
this = "Anne" or
this = "Eleanor" or
this = "Joanna" or
this = "Adam" or
this = "Agnes" or
this = "Rosanna" or
this = "Clara" or
this = "Melissa" or
this = "Amy" or
this = "Isabel" or
this = "Jemima" or
this = "Cordelia" or
this = "Melinda" or
this = "Delila" or
this = "Jeremiah" or
this = "Elijah" or
this = "Hester" or
this = "Walter" or
this = "Oliver" or
this = "Hugh" or
this = "Aaron" or
this = "Reuben" or
this = "Eli" or
this = "Amos" or
this = "Augustus" or
this = "Theodore" or
this = "Ira" or
this = "Timothy" or
this = "Cyrus" or
this = "Horace" or
this = "Simon" or
this = "Asa" or
this = "Frank" or
this = "Nelson" or
this = "Leonard" or
this = "Harrison" or
this = "Anthony" or
this = "Louis" or
this = "Milton" or
this = "Noah" or
this = "Cornelius" or
this = "Abdul" or
this = "Warren" or
this = "Harvey" or
this = "Dennis" or
this = "Wesley" or
this = "Sylvester" or
this = "Gilbert" or
this = "Sullivan" or
this = "Edmund" or
this = "Wilson" or
this = "Perry" or
this = "Matthew" or
this = "Simba" or
this = "Nala" or
this = "Rafiki" or
this = "Shenzi" or
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Edwin" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil" or
this = "Stephen"
}
/** Gets the hair color of the person. If the person is bald, there is no result. */
@@ -836,12 +936,25 @@ class Person extends string {
/** Holds if the person is deceased. */
predicate isDeceased() {
this =
[
"Ernest", "Gertrude", "Oscar", "Lilian", "Edwin", "Raymond", "Elgar", "Elmer", "Herbert",
"Maude", "Mae", "Otto", "Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel",
"King Basil"
]
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Edwin" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil"
}
/** Gets a parent of the person (alive or deceased). */
@@ -1082,7 +1195,12 @@ class Person extends string {
}
/** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */
predicate isAllowedIn(string region) { region = ["north", "south", "east", "west"] }
predicate isAllowedIn(string region) {
region = "north" or
region = "south" or
region = "east" or
region = "west"
}
}
/** Returns a parent of the person. */

View File

@@ -1,6 +0,0 @@
description: Remove unused legacy relations
compatibility: full
snapshotDate.rel: delete
duplicateCode.rel: delete
similarCode.rel: delete
tokens.rel: delete

View File

@@ -1,2 +0,0 @@
description: Add relation for tracking variables from structured binding declarations
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@ where
not lv1.isCompilerGenerated() and
not lv2.isCompilerGenerated() and
not lv1.getParentScope().(BlockStmt).isInMacroExpansion() and
not lv2.getParentScope().(BlockStmt).isInMacroExpansion()
not lv2.getParentScope().(BlockStmt).isInMacroExpansion() and
not lv1.getName() = "(unnamed local variable)"
select lv1, "Variable " + lv1.getName() + " hides another variable of the same name (on $@).", lv2,
"line " + lv2.getLocation().getStartLine().toString()

View File

@@ -1,36 +1,3 @@
## 0.0.9
### New Queries
* Added a new query, `cpp/open-call-with-mode-argument`, to detect when `open` or `openat` is called with the `O_CREAT` or `O_TMPFILE` flag but when the `mode` argument is omitted.
### Minor Analysis Improvements
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been further improved to reduce false positive results, and upgraded from `medium` to `high` precision.
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query now finds more results, where a password is stored in a struct field or class member variable.
* The `cpp/cleartext-storage-file` query has been improved, removing false positives where data is written to a standard output stream.
* The `cpp/cleartext-storage-buffer` query has been updated to use the `semmle.code.cpp.dataflow.TaintTracking` library.
* The `cpp/world-writable-file-creation` query now only detects `open` and `openat` calls with the `O_CREAT` or `O_TMPFILE` flag.
## 0.0.8
### New Queries
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
### Minor Analysis Improvements
* Fix an issue with the `cpp/declaration-hides-variable` query where it would report variables that are unnamed in a database.
* The `cpp/cleartext-storage-file` query has been upgraded with non-local taint flow and has been converted to a `path-problem` query.
* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The
query has also been converted to a `path-problem` query.
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.
* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.
* Added exception for GLib's gboolean to cpp/ambiguously-signed-bit-field.
This change reduces the number of false positives in the query.
## 0.0.7
## 0.0.6

View File

@@ -14,9 +14,6 @@
*/
import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow

View File

@@ -1,25 +0,0 @@
static const int* xptr;
void localAddressEscapes() {
int x = 0;
xptr = &x;
}
void example1() {
localAddressEscapes();
const int* x = xptr; // BAD: This pointer points to expired stack allocated memory.
}
void localAddressDoesNotEscape() {
int x = 0;
xptr = &x;
// ...
// use `xptr`
// ...
xptr = nullptr;
}
void example2() {
localAddressDoesNotEscape();
const int* x = xptr; // GOOD: This pointer does not point to expired memory.
}

View File

@@ -1,49 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This rule finds uses of pointers that likely point to local variables in
expired stack frames. A pointer to a local variable is only valid
until the function returns, after which it becomes a dangling pointer.
</p>
</overview>
<recommendation>
<ol>
<li>
If it is necessary to take the address of a local variable, then make
sure that the address is only stored in memory that does not outlive
the local variable. For example, it is safe to store the address in
another local variable. Similarly, it is also safe to pass the address
of a local variable to another function provided that the other
function only uses it locally and does not store it in non-local
memory.
</li>
<li>
If it is necessary to store an address which will outlive the
current function scope, then it should be allocated on the heap. Care
should be taken to make sure that the memory is deallocated when it is
no longer needed, particularly when using low-level memory management
routines such as <tt>malloc</tt>/<tt>free</tt> or
<tt>new</tt>/<tt>delete</tt>. Modern C++ applications often use smart
pointers, such as <tt>std::shared_ptr</tt>, to reduce the chance of
a memory leak.
</li>
</ol>
</recommendation>
<example>
<sample src="UsingExpiredStackAddress.cpp" />
</example>
<references>
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Dangling_pointer">Dangling pointer</a>.</li>
</references>
</qhelp>

View File

@@ -1,247 +0,0 @@
/**
* @name Use of expired stack-address
* @description Accessing the stack-allocated memory of a function
* after it has returned can lead to memory corruption.
* @kind problem
* @problem.severity error
* @security-severity 9.3
* @precision high
* @id cpp/using-expired-stack-address
* @tags reliability
* security
* external/cwe/cwe-825
*/
import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR
predicate instructionHasVariable(VariableAddressInstruction vai, StackVariable var, Function f) {
var = vai.getASTVariable() and
f = vai.getEnclosingFunction() and
// Pointer-to-member types aren't properly handled in the dbscheme.
not vai.getResultType() instanceof PointerToMemberType and
// Rule out FPs caused by extraction errors.
not any(ErrorExpr e).getEnclosingFunction() = f
}
/**
* Holds if `source` is the base address of an address computation whose
* result is stored in `address`.
*/
predicate stackPointerFlowsToUse(Instruction address, VariableAddressInstruction source) {
address = source and
instructionHasVariable(source, _, _)
or
stackPointerFlowsToUse(address.(CopyInstruction).getSourceValue(), source)
or
stackPointerFlowsToUse(address.(ConvertInstruction).getUnary(), source)
or
stackPointerFlowsToUse(address.(CheckedConvertOrNullInstruction).getUnary(), source)
or
stackPointerFlowsToUse(address.(InheritanceConversionInstruction).getUnary(), source)
or
stackPointerFlowsToUse(address.(FieldAddressInstruction).getObjectAddress(), source)
or
stackPointerFlowsToUse(address.(PointerOffsetInstruction).getLeft(), source)
}
/**
* A HashCons-like table for comparing addresses that are
* computed relative to some global variable.
*/
newtype TGlobalAddress =
TGlobalVariable(GlobalOrNamespaceVariable v) {
// Pointer-to-member types aren't properly handled in the dbscheme.
not v.getUnspecifiedType() instanceof PointerToMemberType
} or
TLoad(TGlobalAddress address) {
address = globalAddress(any(LoadInstruction load).getSourceAddress())
} or
TConversion(string kind, TGlobalAddress address, Type fromType, Type toType) {
kind = "unchecked" and
exists(ConvertInstruction convert |
uncheckedConversionTypes(convert, fromType, toType) and
address = globalAddress(convert.getUnary())
)
or
kind = "checked" and
exists(CheckedConvertOrNullInstruction convert |
checkedConversionTypes(convert, fromType, toType) and
address = globalAddress(convert.getUnary())
)
or
kind = "inheritance" and
exists(InheritanceConversionInstruction convert |
inheritanceConversionTypes(convert, fromType, toType) and
address = globalAddress(convert.getUnary())
)
} or
TFieldAddress(TGlobalAddress address, Field f) {
exists(FieldAddressInstruction fai |
fai.getField() = f and
address = globalAddress(fai.getObjectAddress())
)
}
pragma[noinline]
predicate uncheckedConversionTypes(ConvertInstruction convert, Type fromType, Type toType) {
fromType = convert.getUnary().getResultType() and
toType = convert.getResultType()
}
pragma[noinline]
predicate checkedConversionTypes(CheckedConvertOrNullInstruction convert, Type fromType, Type toType) {
fromType = convert.getUnary().getResultType() and
toType = convert.getResultType()
}
pragma[noinline]
predicate inheritanceConversionTypes(
InheritanceConversionInstruction convert, Type fromType, Type toType
) {
fromType = convert.getUnary().getResultType() and
toType = convert.getResultType()
}
/** Gets the HashCons value of an address computed by `instr`, if any. */
TGlobalAddress globalAddress(Instruction instr) {
result = TGlobalVariable(instr.(VariableAddressInstruction).getASTVariable())
or
not instr instanceof LoadInstruction and
result = globalAddress(instr.(CopyInstruction).getSourceValue())
or
exists(LoadInstruction load | instr = load |
result = TLoad(globalAddress(load.getSourceAddress()))
)
or
exists(ConvertInstruction convert, Type fromType, Type toType | instr = convert |
uncheckedConversionTypes(convert, fromType, toType) and
result = TConversion("unchecked", globalAddress(convert.getUnary()), fromType, toType)
)
or
exists(CheckedConvertOrNullInstruction convert, Type fromType, Type toType | instr = convert |
checkedConversionTypes(convert, fromType, toType) and
result = TConversion("checked", globalAddress(convert.getUnary()), fromType, toType)
)
or
exists(InheritanceConversionInstruction convert, Type fromType, Type toType | instr = convert |
inheritanceConversionTypes(convert, fromType, toType) and
result = TConversion("inheritance", globalAddress(convert.getUnary()), fromType, toType)
)
or
exists(FieldAddressInstruction fai | instr = fai |
result = TFieldAddress(globalAddress(fai.getObjectAddress()), fai.getField())
)
or
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
}
/** Gets a `StoreInstruction` that may be executed after executing `store`. */
pragma[inline]
StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) {
exists(IRBlock block, int index1, int index2 |
block.getInstruction(index1) = store and
block.getInstruction(index2) = result and
index2 > index1
)
or
exists(IRBlock block1, IRBlock block2 |
store.getBlock() = block1 and
result.getBlock() = block2 and
block1.getASuccessor+() = block2
)
}
/**
* Holds if `store` copies the address of `f`'s local variable `var`
* into the address `globalAddress`.
*/
predicate stackAddressEscapes(
StoreInstruction store, StackVariable var, TGlobalAddress globalAddress, Function f
) {
globalAddress = globalAddress(store.getDestinationAddress()) and
exists(VariableAddressInstruction vai |
instructionHasVariable(pragma[only_bind_into](vai), var, f) and
stackPointerFlowsToUse(store.getSourceValue(), vai)
) and
// Ensure there's no subsequent store that overrides the global address.
not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress())
}
predicate blockStoresToAddress(
IRBlock block, int index, StoreInstruction store, TGlobalAddress globalAddress
) {
block.getInstruction(index) = store and
globalAddress = globalAddress(store.getDestinationAddress())
}
predicate blockLoadsFromAddress(
IRBlock block, int index, LoadInstruction load, TGlobalAddress globalAddress
) {
block.getInstruction(index) = load and
globalAddress = globalAddress(load.getSourceAddress())
}
predicate globalAddressPointsToStack(
StoreInstruction store, StackVariable var, CallInstruction call, IRBlock block,
TGlobalAddress globalAddress, boolean isCallBlock, boolean isStoreBlock
) {
(
if blockStoresToAddress(block, _, _, globalAddress)
then isStoreBlock = true
else isStoreBlock = false
) and
(
isCallBlock = true and
exists(Function f |
stackAddressEscapes(store, var, globalAddress, f) and
call.getStaticCallTarget() = f and
call.getBlock() = block
)
or
isCallBlock = false and
exists(IRBlock mid |
mid.immediatelyDominates(block) and
// Only recurse if there is no store to `globalAddress` in `mid`.
globalAddressPointsToStack(store, var, call, mid, globalAddress, _, false)
)
)
}
from
StoreInstruction store, StackVariable var, LoadInstruction load, CallInstruction call,
IRBlock block, boolean isCallBlock, TGlobalAddress address, boolean isStoreBlock
where
globalAddressPointsToStack(store, var, call, block, address, isCallBlock, isStoreBlock) and
block.getAnInstruction() = load and
globalAddress(load.getSourceAddress()) = address and
(
// We know that we have a sequence:
// (1) store to `address` -> (2) return from `f` -> (3) load from `address`.
// But if (2) and (3) happen in the sam block we need to check the
// block indices to ensure that (3) happens after (2).
if isCallBlock = true
then
// If so, the load must happen after the call.
exists(int callIndex, int loadIndex |
blockLoadsFromAddress(_, loadIndex, load, _) and
block.getInstruction(callIndex) = call and
callIndex < loadIndex
)
else any()
) and
// If there is a store to the address we need to make sure that the load we found was
// before that store (So that the load doesn't read an overwritten value).
if isStoreBlock = true
then
exists(int storeIndex, int loadIndex |
blockStoresToAddress(block, storeIndex, _, address) and
block.getInstruction(loadIndex) = load and
loadIndex < storeIndex
)
else any()
select load, "Stack variable $@ escapes $@ and is used after it has expired.", var, var.toString(),
store, "here"

View File

@@ -65,7 +65,6 @@ where
midNode.getNode().asExpr() = mid and
mid = w.getASource() and
dest = w.getDest() and
not dest.(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"] and // exclude calls with standard streams
not isFileName(globalValueNumber(source)) and // file names are not passwords
not exists(string convChar | convChar = w.getSourceConvChar(mid) | not convChar = ["s", "S"]) // ignore things written with other conversion characters
select w, sourceNode, midNode,

View File

@@ -5,7 +5,7 @@
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision high
* @precision medium
* @id cpp/cleartext-transmission
* @tags security
* external/cwe/cwe-319
@@ -14,8 +14,8 @@
import cpp
import semmle.code.cpp.security.SensitiveExprs
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.models.interfaces.FlowSource
import semmle.code.cpp.commons.File
import DataFlow::PathGraph
/**
@@ -27,7 +27,6 @@ class SensitiveNode extends DataFlow::Node {
this.asExpr() = any(SensitiveVariable sv).getInitializer().getExpr() or
this.asExpr().(VariableAccess).getTarget() =
any(SensitiveVariable sv).(GlobalOrNamespaceVariable) or
this.asExpr().(VariableAccess).getTarget() = any(SensitiveVariable v | v instanceof Field) or
this.asUninitialized() instanceof SensitiveVariable or
this.asParameter() instanceof SensitiveVariable or
this.asExpr().(FunctionCall).getTarget() instanceof SensitiveFunction
@@ -59,10 +58,7 @@ class Send extends SendRecv instanceof RemoteFlowSinkFunction {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
(
input.isParameter(arg) or
input.isParameterDeref(arg)
) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
@@ -85,10 +81,7 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
(
input.isParameter(arg) or
input.isParameterDeref(arg)
) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
@@ -121,32 +114,24 @@ abstract class NetworkSendRecv extends FunctionCall {
NetworkSendRecv() {
this.getTarget() = target and
// exclude calls based on the socket...
not exists(DataFlow::Node src, DataFlow::Node dest |
DataFlow::localFlow(src, dest) and
dest.asExpr() = target.getSocketExpr(this) and
not exists(GVN g |
g = globalValueNumber(target.getSocketExpr(this)) and
(
// literal constant
src.asExpr() instanceof Literal
globalValueNumber(any(Literal l)) = g
or
// variable (such as a global) initialized to a literal constant
exists(Variable v |
v.getInitializer().getExpr() instanceof Literal and
src.asExpr() = v.getAnAccess()
g = globalValueNumber(v.getAnAccess())
)
or
// result of a function call with literal inputs (likely constant)
forex(Expr arg | arg = src.asExpr().(FunctionCall).getAnArgument() | arg instanceof Literal)
or
// variable called `stdin`, `stdout` or `stderr`
src.asExpr().(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"]
or
// open of `"/dev/tty"`
exists(FunctionCall fc |
fopenCall(fc) and
fc.getAnArgument().getValue() = "/dev/tty" and
src.asExpr() = fc
forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and
g = globalValueNumber(fc)
)
// (this is not exhaustive)
// (this is far from exhaustive)
)
)
}
@@ -168,16 +153,6 @@ class NetworkRecv extends NetworkSendRecv {
override Recv target;
}
pragma[noinline]
predicate encryptionFunction(Function f) {
f.getName().toLowerCase().regexpMatch(".*(crypt|encode|decode|hash|securezero).*")
}
pragma[noinline]
predicate encryptionType(UserType t) {
t.getName().toLowerCase().regexpMatch(".*(crypt|encode|decode|hash|securezero).*")
}
/**
* An expression that is an argument or return value from an encryption /
* decryption call. This is quite inclusive to minimize false positives, for
@@ -187,7 +162,10 @@ predicate encryptionType(UserType t) {
class Encrypted extends Expr {
Encrypted() {
exists(FunctionCall fc |
encryptionFunction(fc.getTarget()) and
fc.getTarget()
.getName()
.toLowerCase()
.regexpMatch(".*(crypt|encode|decode|hash|securezero).*") and
(
this = fc or
this = fc.getAnArgument()
@@ -196,7 +174,7 @@ class Encrypted extends Expr {
or
exists(Type t |
this.getType().refersTo(t) and
encryptionType(t)
t.getName().toLowerCase().regexpMatch(".*(crypt|encode|decode|hash|securezero).*")
)
}
}

View File

@@ -3,7 +3,7 @@
* @description Non-HTTPS connections can be intercepted by third parties.
* @kind path-problem
* @problem.severity warning
* @precision high
* @precision medium
* @id cpp/non-https-url
* @tags security
* external/cwe/cwe-319
@@ -12,7 +12,6 @@
import cpp
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import DataFlow::PathGraph
/**
@@ -58,12 +57,7 @@ class HttpStringToUrlOpenConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node src) {
// Sources are strings containing an HTTP URL not in a private domain.
src.asExpr() instanceof HttpStringLiteral and
// block taint starting at `strstr`, which is likely testing an existing URL, rather than constructing an HTTP URL.
not exists(FunctionCall fc |
fc.getTarget().getName() = ["strstr", "strcasestr"] and
fc.getArgument(1) = globalValueNumber(src.asExpr()).getAnExpr()
)
src.asExpr() instanceof HttpStringLiteral
}
override predicate isSink(DataFlow::Node sink) {

View File

@@ -12,16 +12,17 @@
import cpp
import FilePermissions
import semmle.code.cpp.commons.unix.Constants
predicate worldWritableCreation(FileCreationExpr fc, int mode) {
mode = localUmask(fc).mask(fc.getMode()) and
setsAnyBits(mode, UnixConstants::s_iwoth())
sets(mode, s_iwoth())
}
predicate setWorldWritable(FunctionCall fc, int mode) {
fc.getTarget().getName() = ["chmod", "fchmod", "_chmod", "_wchmod"] and
mode = fc.getArgument(1).getValue().toInt() and
setsAnyBits(mode, UnixConstants::s_iwoth())
sets(mode, s_iwoth())
}
from Expr fc, int mode, string message

View File

@@ -1,49 +1,5 @@
import cpp
import semmle.code.cpp.commons.unix.Constants as UnixConstants
/**
* Gets the number corresponding to the contents of `input` in base-16.
* Note: the first two characters of `input` must be `0x`. For example:
* `parseHex("0x123abc") = 1194684`.
*/
bindingset[input]
int parseHex(string input) {
exists(string lowerCaseInput | lowerCaseInput = input.toLowerCase() |
lowerCaseInput.regexpMatch("0x[0-9a-f]+") and
result =
strictsum(int ix |
ix in [2 .. input.length()]
|
16.pow(input.length() - (ix + 1)) * "0123456789abcdef".indexOf(lowerCaseInput.charAt(ix))
)
)
}
/**
* Gets the value defined by the `O_CREAT` macro if the macro
* exists and if every definition defines the same value.
*/
int o_creat() {
result =
unique(int v |
exists(Macro m | m.getName() = "O_CREAT" |
v = parseHex(m.getBody()) or v = UnixConstants::parseOctal(m.getBody())
)
)
}
/**
* Gets the value defined by the `O_TMPFILE` macro if the macro
* exists and if every definition defines the same value.
*/
int o_tmpfile() {
result =
unique(int v |
exists(Macro m | m.getName() = "O_TMPFILE" |
v = parseHex(m.getBody()) or v = UnixConstants::parseOctal(m.getBody())
)
)
}
import semmle.code.cpp.commons.unix.Constants
bindingset[n, digit]
private string octalDigit(int n, int digit) {
@@ -64,17 +20,11 @@ string octalFileMode(int mode) {
else result = "[non-standard mode: decimal " + mode + "]"
}
/**
* Holds if the bitmask `value` sets the bits in `flag`.
*/
bindingset[value, flag]
predicate setsFlag(int value, int flag) { value.bitAnd(flag) = flag }
/**
* Holds if the bitmask `mask` sets any of the bit fields in `fields`.
*/
bindingset[mask, fields]
predicate setsAnyBits(int mask, int fields) { mask.bitAnd(fields) != 0 }
predicate sets(int mask, int fields) { mask.bitAnd(fields) != 0 }
/**
* Gets the value that `fc` sets the umask to, if `fc` is a call to
@@ -133,24 +83,16 @@ abstract class FileCreationExpr extends FunctionCall {
abstract int getMode();
}
abstract class FileCreationWithOptionalModeExpr extends FileCreationExpr {
abstract predicate hasModeArgument();
}
class OpenCreationExpr extends FileCreationWithOptionalModeExpr {
class OpenCreationExpr extends FileCreationExpr {
OpenCreationExpr() {
this.getTarget().hasGlobalOrStdName(["open", "_open", "_wopen"]) and
exists(int flag | flag = this.getArgument(1).getValue().toInt() |
setsFlag(flag, o_creat()) or setsFlag(flag, o_tmpfile())
)
this.getTarget().getName() = ["open", "_open", "_wopen"] and
sets(this.getArgument(1).getValue().toInt(), o_creat())
}
override Expr getPath() { result = this.getArgument(0) }
override predicate hasModeArgument() { exists(this.getArgument(2)) }
override int getMode() {
if this.hasModeArgument()
if exists(this.getArgument(2))
then result = this.getArgument(2).getValue().toInt()
else
// assume anything is permitted
@@ -166,35 +108,20 @@ class CreatCreationExpr extends FileCreationExpr {
override int getMode() { result = this.getArgument(1).getValue().toInt() }
}
class OpenatCreationExpr extends FileCreationWithOptionalModeExpr {
class OpenatCreationExpr extends FileCreationExpr {
OpenatCreationExpr() {
this.getTarget().hasGlobalOrStdName("openat") and
exists(int flag | flag = this.getArgument(2).getValue().toInt() |
setsFlag(flag, o_creat()) or setsFlag(flag, o_tmpfile())
)
this.getTarget().getName() = "openat" and
this.getNumberOfArguments() = 4
}
override Expr getPath() { result = this.getArgument(1) }
override predicate hasModeArgument() { exists(this.getArgument(3)) }
override int getMode() {
if this.hasModeArgument()
then result = this.getArgument(3).getValue().toInt()
else
// assume anything is permitted
result = 0.bitNot()
}
override int getMode() { result = this.getArgument(3).getValue().toInt() }
}
private int fopenMode() {
result =
UnixConstants::s_irusr()
.bitOr(UnixConstants::s_irgrp())
.bitOr(UnixConstants::s_iroth())
.bitOr(UnixConstants::s_iwusr())
.bitOr(UnixConstants::s_iwgrp())
.bitOr(UnixConstants::s_iwoth())
s_irusr().bitOr(s_irgrp()).bitOr(s_iroth()).bitOr(s_iwusr()).bitOr(s_iwgrp()).bitOr(s_iwoth())
}
class FopenCreationExpr extends FileCreationExpr {
@@ -226,6 +153,6 @@ class FopensCreationExpr extends FileCreationExpr {
// fopen_s has restrictive permissions unless you have "u" in the mode
if this.getArgument(2).getValue().charAt(_) = "u"
then result = fopenMode()
else result = UnixConstants::s_irusr().bitOr(UnixConstants::s_iwusr())
else result = s_irusr().bitOr(s_iwusr())
}
}

View File

@@ -1,9 +0,0 @@
int open_file_bad() {
// BAD - this uses arbitrary bytes from the stack as mode argument
return open(FILE, O_CREAT)
}
int open_file_good() {
// GOOD - the mode argument is supplied
return open(FILE, O_CREAT, S_IRUSR | S_IWUSR)
}

View File

@@ -1,31 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When opening a file with the <code>O_CREAT</code> or <code>O_TMPFILE</code> flag, the <code>mode</code> must
be supplied. If the <code>mode</code> argument is omitted, some arbitrary bytes from the stack will be used
as the file mode. This leaks some bits from the stack into the permissions of the file.
</p>
</overview>
<recommendation>
<p>
The <code>mode</code> must be supplied when <code>O_CREAT</code> or <code>O_TMPFILE</code> is specified.
</p>
</recommendation>
<example>
<p>
The first example opens a file with the <code>O_CREAT</code> flag without supplying the <code>mode</code>
argument. In this case arbitrary bytes from the stack will be used as <code>mode</code> argument. The
second example correctly supplies the <code>mode</code> argument and creates a file that is user readable
and writable.
</p>
<sample src="OpenCallMissingModeArgument.c" />
</example>
</qhelp>

View File

@@ -1,19 +0,0 @@
/**
* @name File opened with O_CREAT flag but without mode argument
* @description Opening a file with the O_CREAT flag but without mode argument reads arbitrary bytes from the stack.
* @kind problem
* @problem.severity error
* @security-severity 7.8
* @precision high
* @id cpp/open-call-with-mode-argument
* @tags security
* external/cwe/cwe-732
*/
import cpp
import FilePermissions
from FileCreationWithOptionalModeExpr fc
where not fc.hasModeArgument()
select fc,
"A file is created here without providing a mode argument, which may leak bits from the stack."

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added exception for GLib's gboolean to cpp/ambiguously-signed-bit-field.
This change reduces the number of false positives in the query.

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The
query has also been converted to a `path-problem` query.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/cleartext-storage-file` query has been upgraded with non-local taint flow and has been converted to a `path-problem` query.

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/cleartext-storage-buffer` query has been updated to use the `semmle.code.cpp.dataflow.TaintTracking` library.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Fix an issue with the `cpp/declaration-hides-variable` query where it would report variables that are unnamed in a database.

View File

@@ -1,4 +0,0 @@
---
category: deprecated
---
* The `CodeDuplication.Copy`, `CodeDuplication.DuplicateBlock`, and `CodeDuplication.SimilarBlock` classes have been deprecated.

View File

@@ -1,6 +0,0 @@
---
category: newQuery
---
- A new query titled "Use of expired stack-address" (`cpp/using-expired-stack-address`) has been added.
This query finds accesses to expired stack-allocated memory that escaped via a global variable.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The "Failure to use HTTPS URLs" (`cpp/non-https-url`) has been improved reducing false positive results, and its precision has been increased to 'high'.

View File

@@ -1,18 +0,0 @@
## 0.0.8
### New Queries
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
### Minor Analysis Improvements
* Fix an issue with the `cpp/declaration-hides-variable` query where it would report variables that are unnamed in a database.
* The `cpp/cleartext-storage-file` query has been upgraded with non-local taint flow and has been converted to a `path-problem` query.
* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The
query has also been converted to a `path-problem` query.
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.
* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.
* Added exception for GLib's gboolean to cpp/ambiguously-signed-bit-field.
This change reduces the number of false positives in the query.

View File

@@ -1,13 +0,0 @@
## 0.0.9
### New Queries
* Added a new query, `cpp/open-call-with-mode-argument`, to detect when `open` or `openat` is called with the `O_CREAT` or `O_TMPFILE` flag but when the `mode` argument is omitted.
### Minor Analysis Improvements
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been further improved to reduce false positive results, and upgraded from `medium` to `high` precision.
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query now finds more results, where a password is stored in a struct field or class member variable.
* The `cpp/cleartext-storage-file` query has been improved, removing false positives where data is written to a standard output stream.
* The `cpp/cleartext-storage-buffer` query has been updated to use the `semmle.code.cpp.dataflow.TaintTracking` library.
* The `cpp/world-writable-file-creation` query now only detects `open` and `openat` calls with the `O_CREAT` or `O_TMPFILE` flag.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.9
lastReleaseVersion: 0.0.7

View File

@@ -1,9 +0,0 @@
void test(){
int a = 8;
int b = 9;
//Useless NonEquals
if(a==8 && a != 7) {}
while(a==8 && a!=7){}
}

View File

@@ -1,18 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Comparison operations like <code>a==8 &amp;&amp; a!=7</code> contain a useless part : the non-equal part. This rule finds tests of this kind within an <code>if</code> or a <code>while</code> statement</p>
</overview>
<recommendation>
<p>Remove the useless comparisons</p>
</recommendation>
<example>
<sample src="UselessTest.cpp" />
</example>
</qhelp>

View File

@@ -1,45 +0,0 @@
/**
* @name Useless Test
* @description A boolean condition that is guaranteed to never be evaluated should be deleted.
* @kind problem
* @problem.severity warning
* @id cpp/uselesstest
* @tags reliability
* readability
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
predicate sameExpr(Expr e1, Expr e2) { globalValueNumber(e1).getAnExpr() = e2 }
Element nearestParent(Expr e) {
if
e.getParent().(Expr).getConversion*() instanceof ParenthesisExpr or
e.getParent() instanceof IfStmt or
e.getParent() instanceof WhileStmt
then result = e.getParent()
else result = nearestParent(e.getParent())
}
from LogicalAndExpr b, EQExpr eq, NEExpr ne
where
(
b.getAChild*() = eq and
b.getAChild*() = ne and
eq.getParent() instanceof LogicalAndExpr and
ne.getParent() instanceof LogicalAndExpr
) and
(
eq.getLeftOperand() instanceof VariableAccess and ne.getLeftOperand() instanceof VariableAccess
or
eq.getLeftOperand() instanceof PointerDereferenceExpr and
ne.getLeftOperand() instanceof PointerDereferenceExpr
) and
eq.getRightOperand() instanceof Literal and
ne.getRightOperand() instanceof Literal and
eq.getLeftOperand().getFullyConverted().getUnspecifiedType() =
ne.getLeftOperand().getFullyConverted().getUnspecifiedType() and
nearestParent(eq) = nearestParent(ne) and
sameExpr(eq.getLeftOperand(), ne.getLeftOperand())
select ne, "Useless Test"

View File

@@ -2,40 +2,59 @@
import cpp
private newtype TDuplicationOrSimilarity = MKDuplicationOrSimilarity()
private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") }
cached
private predicate tokenLocation(string path, int sl, int sc, int ec, int el, Copy copy, int index) {
path = copy.sourceFile().getAbsolutePath() and
tokens(copy, index, sl, sc, ec, el)
}
/** A token block used for detection of duplicate and similar code. */
class Copy extends @duplication_or_similarity {
/** Gets the index of the last token in this block. */
private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) }
/**
* DEPRECATED: This class is no longer used.
*
* A token block used for detection of duplicate and similar code.
*/
class Copy extends TDuplicationOrSimilarity {
/** Gets the index of the token in this block starting at the location `loc`, if any. */
int tokenStartingAt(Location loc) { none() }
int tokenStartingAt(Location loc) {
exists(string filepath, int startline, int startcol |
loc.hasLocationInfo(filepath, startline, startcol, _, _) and
tokenLocation(filepath, startline, startcol, _, _, this, result)
)
}
/** Gets the index of the token in this block ending at the location `loc`, if any. */
int tokenEndingAt(Location loc) { none() }
int tokenEndingAt(Location loc) {
exists(string filepath, int endline, int endcol |
loc.hasLocationInfo(filepath, _, _, endline, endcol) and
tokenLocation(filepath, _, _, endline, endcol, this, result)
)
}
/** Gets the line on which the first token in this block starts. */
int sourceStartLine() { none() }
int sourceStartLine() { tokens(this, 0, result, _, _, _) }
/** Gets the column on which the first token in this block starts. */
int sourceStartColumn() { none() }
int sourceStartColumn() { tokens(this, 0, _, result, _, _) }
/** Gets the line on which the last token in this block ends. */
int sourceEndLine() { none() }
int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) }
/** Gets the column on which the last token in this block ends. */
int sourceEndColumn() { none() }
int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) }
/** Gets the number of lines containing at least (part of) one token in this block. */
int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() }
/** Gets an opaque identifier for the equivalence class of this block. */
int getEquivalenceClass() { none() }
int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) }
/** Gets the source file in which this block appears. */
File sourceFile() { none() }
File sourceFile() {
exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) |
name.replaceAll("\\", "/") = relativePath(result)
)
}
/**
* Holds if this element is at the specified location.
@@ -58,23 +77,15 @@ class Copy extends TDuplicationOrSimilarity {
string toString() { none() }
}
/**
* DEPRECATED: This class is no longer used.
*
* A block of duplicated code.
*/
class DuplicateBlock extends Copy {
/** A block of duplicated code. */
class DuplicateBlock extends Copy, @duplication {
override string toString() {
result = "Duplicate code: " + this.sourceLines() + " duplicated lines."
}
}
/**
* DEPRECATED: This class is no longer used.
*
* A block of similar code.
*/
class SimilarBlock extends Copy {
/** A block of similar code. */
class SimilarBlock extends Copy, @similarity {
override string toString() {
result = "Similar code: " + this.sourceLines() + " almost duplicated lines."
}

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.0.10-dev
version: 0.0.8-dev
groups:
- cpp
- queries

View File

@@ -93,7 +93,7 @@
private import InlineExpectationsTestPrivate
/**
* The base class for tests with inline expectations. The test extends this class to provide the actual
* Base class for tests with inline expectations. The test extends this class to provide the actual
* results of the query, which are then compared with the expected results in comments to produce a
* list of failure messages that point out where the actual results differ from the expected
* results.
@@ -123,15 +123,6 @@ abstract class InlineExpectationsTest extends string {
*/
abstract predicate hasActualResult(Location location, string element, string tag, string value);
/**
* Like `hasActualResult`, but returns results that do not require a matching annotation.
* A failure will still arise if there is an annotation that does not match any results, but not vice versa.
* Override this predicate to specify optional results.
*/
predicate hasOptionalResult(Location location, string element, string tag, string value) {
none()
}
final predicate hasFailureMessage(FailureLocatable element, string message) {
exists(ActualResult actualResult |
actualResult.getTest() = this and
@@ -143,8 +134,7 @@ abstract class InlineExpectationsTest extends string {
)
or
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
message = "Unexpected result: " + actualResult.getExpectationText() and
not actualResult.isOptional()
message = "Unexpected result: " + actualResult.getExpectationText()
)
)
or
@@ -253,13 +243,9 @@ private string expectationPattern() {
private newtype TFailureLocatable =
TActualResult(
InlineExpectationsTest test, Location location, string element, string tag, string value,
boolean optional
InlineExpectationsTest test, Location location, string element, string tag, string value
) {
test.hasActualResult(location, element, tag, value) and
optional = false
or
test.hasOptionalResult(location, element, tag, value) and optional = true
test.hasActualResult(location, element, tag, value)
} or
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
exists(TColumn column, string tags |
@@ -291,9 +277,8 @@ class ActualResult extends FailureLocatable, TActualResult {
string element;
string tag;
string value;
boolean optional;
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
ActualResult() { this = TActualResult(test, location, element, tag, value) }
override string toString() { result = element }
@@ -304,8 +289,6 @@ class ActualResult extends FailureLocatable, TActualResult {
override string getTag() { result = tag }
override string getValue() { result = value }
predicate isOptional() { optional = true }
}
abstract private class Expectation extends FailureLocatable {

View File

@@ -11332,930 +11332,6 @@ ir.cpp:
# 1447| Type = [Struct] POD_Derived
# 1447| ValueCategory = prvalue
# 1448| getStmt(4): [ReturnStmt] return ...
# 1450| [CopyAssignmentOperator] Inheritance_Test_B& Inheritance_Test_B::operator=(Inheritance_Test_B const&)
# 1450| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_B &
# 1450| [Constructor] void Inheritance_Test_B::Inheritance_Test_B()
# 1450| <params>:
# 1451| [Destructor] void Inheritance_Test_B::~Inheritance_Test_B()
# 1451| <params>:
# 1451| getEntryPoint(): [BlockStmt] { ... }
# 1451| getStmt(0): [ReturnStmt] return ...
# 1451| <destructions>:
# 1454| [CopyAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A const&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
# 1454| [MoveAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A&&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
# 1454| [CopyConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A const&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
# 1454| [MoveConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A&&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
# 1454| [Destructor] void Inheritance_Test_A::~Inheritance_Test_A()
# 1454| <params>:
# 1457| [Constructor] void Inheritance_Test_A::Inheritance_Test_A()
# 1457| <params>:
# 1457| <initializations>:
# 1457| getInitializer(0): (no string representation)
# 1457| Type = [Struct] Inheritance_Test_B
# 1457| ValueCategory = prvalue
# 1457| getInitializer(1): [ConstructorFieldInit] constructor init of field x
# 1457| Type = [IntType] int
# 1457| ValueCategory = prvalue
# 1457| getExpr(): [Literal] 42
# 1457| Type = [IntType] int
# 1457| Value = [Literal] 42
# 1457| ValueCategory = prvalue
# 1457| getEntryPoint(): [BlockStmt] { ... }
# 1458| getStmt(0): [ExprStmt] ExprStmt
# 1458| getExpr(): [AssignExpr] ... = ...
# 1458| Type = [IntType] int
# 1458| ValueCategory = lvalue
# 1458| getLValue(): [PointerFieldAccess] y
# 1458| Type = [IntType] int
# 1458| ValueCategory = lvalue
# 1458| getQualifier(): [ThisExpr] this
# 1458| Type = [PointerType] Inheritance_Test_A *
# 1458| ValueCategory = prvalue(load)
# 1458| getRValue(): [Literal] 3
# 1458| Type = [IntType] int
# 1458| Value = [Literal] 3
# 1458| ValueCategory = prvalue
# 1459| getStmt(1): [ReturnStmt] return ...
# 1462| [TopLevelFunction] void array_structured_binding()
# 1462| <params>:
# 1462| getEntryPoint(): [BlockStmt] { ... }
# 1463| getStmt(0): [DeclStmt] declaration
# 1463| getDeclarationEntry(0): [VariableDeclarationEntry] definition of xs
# 1463| Type = [ArrayType] int[2]
# 1463| getVariable().getInitializer(): [Initializer] initializer for xs
# 1463| getExpr(): [ArrayAggregateLiteral] {...}
# 1463| Type = [ArrayType] int[2]
# 1463| ValueCategory = prvalue
# 1463| getElementExpr(0): [Literal] 1
# 1463| Type = [IntType] int
# 1463| Value = [Literal] 1
# 1463| ValueCategory = prvalue
# 1463| getElementExpr(1): [Literal] 2
# 1463| Type = [IntType] int
# 1463| Value = [Literal] 2
# 1463| ValueCategory = prvalue
# 1465| getStmt(1): [BlockStmt] { ... }
# 1466| getStmt(0): [DeclStmt] declaration
# 1466| getDeclarationEntry(0): (no string representation)
# 1466| Type = [LValueReferenceType] int(&)[2]
# 1466| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1466| getExpr(): [VariableAccess] xs
# 1466| Type = [ArrayType] int[2]
# 1466| ValueCategory = lvalue
# 1466| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1466| Type = [LValueReferenceType] int(&)[2]
# 1466| ValueCategory = prvalue
# 1466| getDeclarationEntry(1): [VariableDeclarationEntry] definition of x0
# 1466| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for x0
#-----| getExpr(): [ArrayExpr] access to array
#-----| Type = [IntType] int
#-----| ValueCategory = lvalue
#-----| getArrayBase(): [VariableAccess] (unnamed local variable)
#-----| Type = [LValueReferenceType] int(&)[2]
#-----| ValueCategory = prvalue(load)
#-----| getArrayOffset(): [Literal] 0
#-----| Type = [LongType] unsigned long
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue
#-----| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
#-----| Type = [IntPointerType] int *
#-----| ValueCategory = prvalue
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ArrayType] int[2]
#-----| ValueCategory = lvalue
# 1466| getDeclarationEntry(2): [VariableDeclarationEntry] definition of x1
# 1466| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for x1
#-----| getExpr(): [ArrayExpr] access to array
#-----| Type = [IntType] int
#-----| ValueCategory = lvalue
#-----| getArrayBase(): [VariableAccess] (unnamed local variable)
#-----| Type = [LValueReferenceType] int(&)[2]
#-----| ValueCategory = prvalue(load)
#-----| getArrayOffset(): [Literal] 1
#-----| Type = [LongType] unsigned long
#-----| Value = [Literal] 1
#-----| ValueCategory = prvalue
#-----| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
#-----| Type = [IntPointerType] int *
#-----| ValueCategory = prvalue
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ArrayType] int[2]
#-----| ValueCategory = lvalue
# 1467| getStmt(1): [ExprStmt] ExprStmt
# 1467| getExpr(): [AssignExpr] ... = ...
# 1467| Type = [IntType] int
# 1467| ValueCategory = lvalue
# 1467| getLValue(): [VariableAccess] x1
# 1467| Type = [IntType] int
# 1467| ValueCategory = lvalue
# 1467| getRValue(): [Literal] 3
# 1467| Type = [IntType] int
# 1467| Value = [Literal] 3
# 1467| ValueCategory = prvalue
# 1468| getStmt(2): [DeclStmt] declaration
# 1468| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rx1
# 1468| Type = [LValueReferenceType] int &
# 1468| getVariable().getInitializer(): [Initializer] initializer for rx1
# 1468| getExpr(): [VariableAccess] x1
# 1468| Type = [IntType] int
# 1468| ValueCategory = lvalue
# 1468| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1468| Type = [LValueReferenceType] int &
# 1468| ValueCategory = prvalue
# 1469| getStmt(3): [DeclStmt] declaration
# 1469| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1469| Type = [IntType] int
# 1469| getVariable().getInitializer(): [Initializer] initializer for x
# 1469| getExpr(): [VariableAccess] x1
# 1469| Type = [IntType] int
# 1469| ValueCategory = prvalue(load)
# 1472| getStmt(2): [BlockStmt] { ... }
# 1473| getStmt(0): [DeclStmt] declaration
# 1473| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1473| Type = [LValueReferenceType] int(&)[2]
# 1473| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1473| getExpr(): [VariableAccess] xs
# 1473| Type = [ArrayType] int[2]
# 1473| ValueCategory = lvalue
# 1473| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1473| Type = [LValueReferenceType] int(&)[2]
# 1473| ValueCategory = prvalue
# 1474| getStmt(1): [DeclStmt] declaration
# 1474| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x0
# 1474| Type = [LValueReferenceType] int &
# 1474| getVariable().getInitializer(): [Initializer] initializer for x0
# 1474| getExpr(): [ArrayExpr] access to array
# 1474| Type = [IntType] int
# 1474| ValueCategory = lvalue
# 1474| getArrayBase(): [VariableAccess] xs
# 1474| Type = [ArrayType] int[2]
# 1474| ValueCategory = lvalue
# 1474| getArrayOffset(): [Literal] 0
# 1474| Type = [IntType] int
# 1474| Value = [Literal] 0
# 1474| ValueCategory = prvalue
# 1474| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 1474| Type = [IntPointerType] int *
# 1474| ValueCategory = prvalue
# 1474| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1474| Type = [LValueReferenceType] int &
# 1474| ValueCategory = prvalue
# 1475| getStmt(2): [DeclStmt] declaration
# 1475| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x1
# 1475| Type = [LValueReferenceType] int &
# 1475| getVariable().getInitializer(): [Initializer] initializer for x1
# 1475| getExpr(): [ArrayExpr] access to array
# 1475| Type = [IntType] int
# 1475| ValueCategory = lvalue
# 1475| getArrayBase(): [VariableAccess] xs
# 1475| Type = [ArrayType] int[2]
# 1475| ValueCategory = lvalue
# 1475| getArrayOffset(): [Literal] 1
# 1475| Type = [IntType] int
# 1475| Value = [Literal] 1
# 1475| ValueCategory = prvalue
# 1475| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 1475| Type = [IntPointerType] int *
# 1475| ValueCategory = prvalue
# 1475| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1475| Type = [LValueReferenceType] int &
# 1475| ValueCategory = prvalue
# 1476| getStmt(3): [ExprStmt] ExprStmt
# 1476| getExpr(): [AssignExpr] ... = ...
# 1476| Type = [IntType] int
# 1476| ValueCategory = lvalue
# 1476| getLValue(): [VariableAccess] x1
# 1476| Type = [LValueReferenceType] int &
# 1476| ValueCategory = prvalue(load)
# 1476| getRValue(): [Literal] 3
# 1476| Type = [IntType] int
# 1476| Value = [Literal] 3
# 1476| ValueCategory = prvalue
# 1476| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1476| Type = [IntType] int
# 1476| ValueCategory = lvalue
# 1477| getStmt(4): [DeclStmt] declaration
# 1477| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rx1
# 1477| Type = [LValueReferenceType] int &
# 1477| getVariable().getInitializer(): [Initializer] initializer for rx1
# 1477| getExpr(): [VariableAccess] x1
# 1477| Type = [LValueReferenceType] int &
# 1477| ValueCategory = prvalue(load)
# 1477| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1477| Type = [LValueReferenceType] int &
# 1477| ValueCategory = prvalue
# 1477| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1477| Type = [IntType] int
# 1477| ValueCategory = lvalue
# 1478| getStmt(5): [DeclStmt] declaration
# 1478| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1478| Type = [IntType] int
# 1478| getVariable().getInitializer(): [Initializer] initializer for x
# 1478| getExpr(): [VariableAccess] x1
# 1478| Type = [LValueReferenceType] int &
# 1478| ValueCategory = prvalue(load)
# 1478| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1478| Type = [IntType] int
# 1478| ValueCategory = prvalue(load)
# 1480| getStmt(3): [ReturnStmt] return ...
# 1482| [CopyAssignmentOperator] StructuredBindingDataMemberStruct& StructuredBindingDataMemberStruct::operator=(StructuredBindingDataMemberStruct const&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
# 1482| [Constructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct()
# 1482| <params>:
# 1482| <initializations>:
# 1482| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getEntryPoint(): [BlockStmt] { ... }
# 1482| getStmt(0): [ReturnStmt] return ...
# 1482| [CopyConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
# 1482| <initializations>:
# 1482| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getInitializer(2): [ConstructorFieldInit] constructor init of field b
# 1482| Type = [IntType] unsigned int
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [IntType] unsigned int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(3): [ConstructorFieldInit] constructor init of field r
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getEntryPoint(): [BlockStmt] { ... }
# 1482| getStmt(0): [ReturnStmt] return ...
# 1482| [MoveConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct&&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] StructuredBindingDataMemberStruct &&
# 1489| [TopLevelFunction] void data_member_structured_binding()
# 1489| <params>:
# 1489| getEntryPoint(): [BlockStmt] { ... }
# 1490| getStmt(0): [DeclStmt] declaration
# 1490| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 1490| Type = [Struct] StructuredBindingDataMemberStruct
# 1490| getVariable().getInitializer(): [Initializer] initializer for s
# 1490| getExpr(): [ConstructorCall] call to StructuredBindingDataMemberStruct
# 1490| Type = [VoidType] void
# 1490| ValueCategory = prvalue
# 1492| getStmt(1): [BlockStmt] { ... }
# 1493| getStmt(0): [DeclStmt] declaration
# 1493| getDeclarationEntry(0): (no string representation)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1493| getExpr(): [VariableAccess] s
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = prvalue(load)
# 1493| getDeclarationEntry(1): [VariableDeclarationEntry] definition of i
# 1493| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for i
# 1493| getExpr(): [ValueFieldAccess] i
# 1493| Type = [IntType] int
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(2): [VariableDeclarationEntry] definition of d
# 1493| Type = [DoubleType] double
#-----| getVariable().getInitializer(): [Initializer] initializer for d
# 1493| getExpr(): [ValueFieldAccess] d
# 1493| Type = [DoubleType] double
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(3): [VariableDeclarationEntry] definition of b
# 1493| Type = [IntType] unsigned int
#-----| getVariable().getInitializer(): [Initializer] initializer for b
# 1493| getExpr(): [ValueFieldAccess] b
# 1493| Type = [IntType] unsigned int
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(4): [VariableDeclarationEntry] definition of r
# 1493| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for r
# 1493| getExpr(): [ValueFieldAccess] r
# 1493| Type = [LValueReferenceType] int &
# 1493| ValueCategory = prvalue(load)
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1493| Type = [IntType] int
# 1493| ValueCategory = lvalue
# 1494| getStmt(1): [ExprStmt] ExprStmt
# 1494| getExpr(): [AssignExpr] ... = ...
# 1494| Type = [DoubleType] double
# 1494| ValueCategory = lvalue
# 1494| getLValue(): [VariableAccess] d
# 1494| Type = [DoubleType] double
# 1494| ValueCategory = lvalue
# 1494| getRValue(): [Literal] 4.0
# 1494| Type = [DoubleType] double
# 1494| Value = [Literal] 4.0
# 1494| ValueCategory = prvalue
# 1495| getStmt(2): [DeclStmt] declaration
# 1495| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1495| Type = [LValueReferenceType] double &
# 1495| getVariable().getInitializer(): [Initializer] initializer for rd
# 1495| getExpr(): [VariableAccess] d
# 1495| Type = [DoubleType] double
# 1495| ValueCategory = lvalue
# 1495| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1495| Type = [LValueReferenceType] double &
# 1495| ValueCategory = prvalue
# 1496| getStmt(3): [DeclStmt] declaration
# 1496| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1496| Type = [IntType] int
# 1496| getVariable().getInitializer(): [Initializer] initializer for v
# 1496| getExpr(): [VariableAccess] i
# 1496| Type = [IntType] int
# 1496| ValueCategory = prvalue(load)
# 1497| getStmt(4): [ExprStmt] ExprStmt
# 1497| getExpr(): [AssignExpr] ... = ...
# 1497| Type = [IntType] int
# 1497| ValueCategory = lvalue
# 1497| getLValue(): [VariableAccess] r
# 1497| Type = [IntType] int
# 1497| ValueCategory = lvalue
# 1497| getRValue(): [Literal] 5
# 1497| Type = [IntType] int
# 1497| Value = [Literal] 5
# 1497| ValueCategory = prvalue
# 1498| getStmt(5): [DeclStmt] declaration
# 1498| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1498| Type = [LValueReferenceType] int &
# 1498| getVariable().getInitializer(): [Initializer] initializer for rr
# 1498| getExpr(): [VariableAccess] r
# 1498| Type = [IntType] int
# 1498| ValueCategory = lvalue
# 1498| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1498| Type = [LValueReferenceType] int &
# 1498| ValueCategory = prvalue
# 1499| getStmt(6): [DeclStmt] declaration
# 1499| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1499| Type = [IntType] int
# 1499| getVariable().getInitializer(): [Initializer] initializer for w
# 1499| getExpr(): [VariableAccess] r
# 1499| Type = [IntType] int
# 1499| ValueCategory = prvalue(load)
# 1502| getStmt(2): [BlockStmt] { ... }
# 1503| getStmt(0): [DeclStmt] declaration
# 1503| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1503| Type = [Struct] StructuredBindingDataMemberStruct
# 1503| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1503| getExpr(): [VariableAccess] s
# 1503| Type = [Struct] StructuredBindingDataMemberStruct
# 1503| ValueCategory = prvalue(load)
# 1504| getStmt(1): [DeclStmt] declaration
# 1504| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1504| Type = [LValueReferenceType] int &
# 1504| getVariable().getInitializer(): [Initializer] initializer for i
# 1504| getExpr(): [ValueFieldAccess] i
# 1504| Type = [IntType] int
# 1504| ValueCategory = lvalue
# 1504| getQualifier(): [VariableAccess] unnamed_local_variable
# 1504| Type = [Struct] StructuredBindingDataMemberStruct
# 1504| ValueCategory = lvalue
# 1504| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1504| Type = [LValueReferenceType] int &
# 1504| ValueCategory = prvalue
# 1505| getStmt(2): [DeclStmt] declaration
# 1505| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 1505| Type = [LValueReferenceType] double &
# 1505| getVariable().getInitializer(): [Initializer] initializer for d
# 1505| getExpr(): [ValueFieldAccess] d
# 1505| Type = [DoubleType] double
# 1505| ValueCategory = lvalue
# 1505| getQualifier(): [VariableAccess] unnamed_local_variable
# 1505| Type = [Struct] StructuredBindingDataMemberStruct
# 1505| ValueCategory = lvalue
# 1505| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1505| Type = [LValueReferenceType] double &
# 1505| ValueCategory = prvalue
# 1507| getStmt(3): [DeclStmt] declaration
# 1507| getDeclarationEntry(0): [VariableDeclarationEntry] definition of r
# 1507| Type = [LValueReferenceType] int &
# 1507| getVariable().getInitializer(): [Initializer] initializer for r
# 1507| getExpr(): [ValueFieldAccess] r
# 1507| Type = [LValueReferenceType] int &
# 1507| ValueCategory = prvalue(load)
# 1507| getQualifier(): [VariableAccess] unnamed_local_variable
# 1507| Type = [Struct] StructuredBindingDataMemberStruct
# 1507| ValueCategory = lvalue
# 1507| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1507| Type = [LValueReferenceType] int &
# 1507| ValueCategory = prvalue
# 1507| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1507| Type = [IntType] int
# 1507| ValueCategory = lvalue
# 1508| getStmt(4): [ExprStmt] ExprStmt
# 1508| getExpr(): [AssignExpr] ... = ...
# 1508| Type = [DoubleType] double
# 1508| ValueCategory = lvalue
# 1508| getLValue(): [VariableAccess] d
# 1508| Type = [LValueReferenceType] double &
# 1508| ValueCategory = prvalue(load)
# 1508| getRValue(): [Literal] 4.0
# 1508| Type = [DoubleType] double
# 1508| Value = [Literal] 4.0
# 1508| ValueCategory = prvalue
# 1508| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1508| Type = [DoubleType] double
# 1508| ValueCategory = lvalue
# 1509| getStmt(5): [DeclStmt] declaration
# 1509| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1509| Type = [LValueReferenceType] double &
# 1509| getVariable().getInitializer(): [Initializer] initializer for rd
# 1509| getExpr(): [VariableAccess] d
# 1509| Type = [LValueReferenceType] double &
# 1509| ValueCategory = prvalue(load)
# 1509| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1509| Type = [LValueReferenceType] double &
# 1509| ValueCategory = prvalue
# 1509| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1509| Type = [DoubleType] double
# 1509| ValueCategory = lvalue
# 1510| getStmt(6): [DeclStmt] declaration
# 1510| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1510| Type = [IntType] int
# 1510| getVariable().getInitializer(): [Initializer] initializer for v
# 1510| getExpr(): [VariableAccess] i
# 1510| Type = [LValueReferenceType] int &
# 1510| ValueCategory = prvalue(load)
# 1510| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1510| Type = [IntType] int
# 1510| ValueCategory = prvalue(load)
# 1511| getStmt(7): [ExprStmt] ExprStmt
# 1511| getExpr(): [AssignExpr] ... = ...
# 1511| Type = [IntType] int
# 1511| ValueCategory = lvalue
# 1511| getLValue(): [VariableAccess] r
# 1511| Type = [LValueReferenceType] int &
# 1511| ValueCategory = prvalue(load)
# 1511| getRValue(): [Literal] 5
# 1511| Type = [IntType] int
# 1511| Value = [Literal] 5
# 1511| ValueCategory = prvalue
# 1511| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1511| Type = [IntType] int
# 1511| ValueCategory = lvalue
# 1512| getStmt(8): [DeclStmt] declaration
# 1512| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1512| Type = [LValueReferenceType] int &
# 1512| getVariable().getInitializer(): [Initializer] initializer for rr
# 1512| getExpr(): [VariableAccess] r
# 1512| Type = [LValueReferenceType] int &
# 1512| ValueCategory = prvalue(load)
# 1512| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1512| Type = [LValueReferenceType] int &
# 1512| ValueCategory = prvalue
# 1512| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1512| Type = [IntType] int
# 1512| ValueCategory = lvalue
# 1513| getStmt(9): [DeclStmt] declaration
# 1513| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1513| Type = [IntType] int
# 1513| getVariable().getInitializer(): [Initializer] initializer for w
# 1513| getExpr(): [VariableAccess] r
# 1513| Type = [LValueReferenceType] int &
# 1513| ValueCategory = prvalue(load)
# 1513| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1513| Type = [IntType] int
# 1513| ValueCategory = prvalue(load)
# 1515| getStmt(3): [ReturnStmt] return ...
# 1522| [CopyAssignmentOperator] std::tuple_size<StructuredBindingTuple>& std::tuple_size<StructuredBindingTuple>::operator=(std::tuple_size<StructuredBindingTuple> const&)
# 1522| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_size<StructuredBindingTuple> &
# 1522| [MoveAssignmentOperator] std::tuple_size<StructuredBindingTuple>& std::tuple_size<StructuredBindingTuple>::operator=(std::tuple_size<StructuredBindingTuple>&&)
# 1522| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_size<StructuredBindingTuple> &&
# 1529| [CopyAssignmentOperator] std::tuple_element<int 0, StructuredBindingTuple>& std::tuple_element<int 0, StructuredBindingTuple>::operator=(std::tuple_element<int 0, StructuredBindingTuple> const&)
# 1529| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<0, StructuredBindingTuple> &
# 1529| [MoveAssignmentOperator] std::tuple_element<int 0, StructuredBindingTuple>& std::tuple_element<int 0, StructuredBindingTuple>::operator=(std::tuple_element<int 0, StructuredBindingTuple>&&)
# 1529| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<0, StructuredBindingTuple> &&
# 1533| [CopyAssignmentOperator] std::tuple_element<int 1, StructuredBindingTuple>& std::tuple_element<int 1, StructuredBindingTuple>::operator=(std::tuple_element<int 1, StructuredBindingTuple> const&)
# 1533| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<1, StructuredBindingTuple> &
# 1533| [MoveAssignmentOperator] std::tuple_element<int 1, StructuredBindingTuple>& std::tuple_element<int 1, StructuredBindingTuple>::operator=(std::tuple_element<int 1, StructuredBindingTuple>&&)
# 1533| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<1, StructuredBindingTuple> &&
# 1537| [CopyAssignmentOperator] std::tuple_element<int 2, StructuredBindingTuple>& std::tuple_element<int 2, StructuredBindingTuple>::operator=(std::tuple_element<int 2, StructuredBindingTuple> const&)
# 1537| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<2, StructuredBindingTuple> &
# 1537| [MoveAssignmentOperator] std::tuple_element<int 2, StructuredBindingTuple>& std::tuple_element<int 2, StructuredBindingTuple>::operator=(std::tuple_element<int 2, StructuredBindingTuple>&&)
# 1537| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<2, StructuredBindingTuple> &&
# 1542| [CopyAssignmentOperator] StructuredBindingTuple& StructuredBindingTuple::operator=(StructuredBindingTuple const&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingTuple &
# 1542| [Constructor] void StructuredBindingTuple::StructuredBindingTuple()
# 1542| <params>:
# 1542| <initializations>:
# 1542| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getEntryPoint(): [BlockStmt] { ... }
# 1542| getStmt(0): [ReturnStmt] return ...
# 1542| [CopyConstructor] void StructuredBindingTuple::StructuredBindingTuple(StructuredBindingTuple const&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingTuple &
# 1542| <initializations>:
# 1542| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getEntryPoint(): [BlockStmt] { ... }
# 1542| getStmt(0): [ReturnStmt] return ...
# 1542| [MoveConstructor] void StructuredBindingTuple::StructuredBindingTuple(StructuredBindingTuple&&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] StructuredBindingTuple &&
# 1548| [MemberFunction,TemplateFunction] type& StructuredBindingTuple::get<int i>()
# 1548| <params>:
# 1552| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 0, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 0>()
# 1552| <params>:
# 1552| getEntryPoint(): [BlockStmt] { ... }
# 1552| getStmt(0): [ReturnStmt] return ...
# 1552| getExpr(): [PointerFieldAccess] i
# 1552| Type = [IntType] int
# 1552| ValueCategory = lvalue
# 1552| getQualifier(): [ThisExpr] this
# 1552| Type = [PointerType] StructuredBindingTuple *
# 1552| ValueCategory = prvalue(load)
#-----| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] int &
#-----| ValueCategory = prvalue
# 1554| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 1, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 1>()
# 1554| <params>:
# 1554| getEntryPoint(): [BlockStmt] { ... }
# 1554| getStmt(0): [ReturnStmt] return ...
# 1554| getExpr(): [PointerFieldAccess] d
# 1554| Type = [DoubleType] double
# 1554| ValueCategory = lvalue
# 1554| getQualifier(): [ThisExpr] this
# 1554| Type = [PointerType] StructuredBindingTuple *
# 1554| ValueCategory = prvalue(load)
#-----| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] double &
#-----| ValueCategory = prvalue
# 1556| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 2, StructuredBindingTuple>::type StructuredBindingTuple::get<int 2>()
# 1556| <params>:
# 1556| getEntryPoint(): [BlockStmt] { ... }
# 1556| getStmt(0): [ReturnStmt] return ...
# 1556| getExpr(): [PointerFieldAccess] r
# 1556| Type = [LValueReferenceType] int &
# 1556| ValueCategory = prvalue(load)
# 1556| getQualifier(): [ThisExpr] this
# 1556| Type = [PointerType] StructuredBindingTuple *
# 1556| ValueCategory = prvalue(load)
# 1556| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1556| Type = [LValueReferenceType] int &
# 1556| ValueCategory = prvalue
# 1556| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1556| Type = [IntType] int
# 1556| ValueCategory = lvalue
# 1558| [TopLevelFunction] void tuple_structured_binding()
# 1558| <params>:
# 1558| getEntryPoint(): [BlockStmt] { ... }
# 1559| getStmt(0): [DeclStmt] declaration
# 1559| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t
# 1559| Type = [Struct] StructuredBindingTuple
# 1559| getVariable().getInitializer(): [Initializer] initializer for t
# 1559| getExpr(): [ConstructorCall] call to StructuredBindingTuple
# 1559| Type = [VoidType] void
# 1559| ValueCategory = prvalue
# 1561| getStmt(1): [BlockStmt] { ... }
# 1562| getStmt(0): [DeclStmt] declaration
# 1562| getDeclarationEntry(0): (no string representation)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1562| getExpr(): [VariableAccess] t
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = prvalue(load)
# 1562| getDeclarationEntry(1): [VariableDeclarationEntry] definition of i
# 1562| Type = [LValueReferenceType] type &
#-----| getVariable().getInitializer(): [Initializer] initializer for i
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = lvalue
# 1562| getDeclarationEntry(2): [VariableDeclarationEntry] definition of d
# 1562| Type = [LValueReferenceType] type &
#-----| getVariable().getInitializer(): [Initializer] initializer for d
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = lvalue
# 1562| getDeclarationEntry(3): [VariableDeclarationEntry] definition of r
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
#-----| getVariable().getInitializer(): [Initializer] initializer for r
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] int &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [IntType] int
# 1562| ValueCategory = lvalue
# 1563| getStmt(1): [ExprStmt] ExprStmt
# 1563| getExpr(): [AssignExpr] ... = ...
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| ValueCategory = lvalue
# 1563| getLValue(): [VariableAccess] d
# 1563| Type = [LValueReferenceType] type &
# 1563| ValueCategory = prvalue(load)
# 1563| getRValue(): [Literal] 4.0
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| Value = [Literal] 4.0
# 1563| ValueCategory = prvalue
# 1563| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| ValueCategory = lvalue
# 1564| getStmt(2): [DeclStmt] declaration
# 1564| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1564| Type = [LValueReferenceType] double &
# 1564| getVariable().getInitializer(): [Initializer] initializer for rd
# 1564| getExpr(): [VariableAccess] d
# 1564| Type = [LValueReferenceType] type &
# 1564| ValueCategory = prvalue(load)
# 1564| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1564| Type = [LValueReferenceType] type &
# 1564| ValueCategory = prvalue
# 1564| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1564| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1564| ValueCategory = lvalue
# 1565| getStmt(3): [DeclStmt] declaration
# 1565| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1565| Type = [IntType] int
# 1565| getVariable().getInitializer(): [Initializer] initializer for v
# 1565| getExpr(): [VariableAccess] i
# 1565| Type = [LValueReferenceType] type &
# 1565| ValueCategory = prvalue(load)
# 1565| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1565| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1565| ValueCategory = prvalue(load)
# 1566| getStmt(4): [ExprStmt] ExprStmt
# 1566| getExpr(): [AssignExpr] ... = ...
# 1566| Type = [IntType] int
# 1566| ValueCategory = lvalue
# 1566| getLValue(): [VariableAccess] r
# 1566| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1566| ValueCategory = prvalue(load)
# 1566| getRValue(): [Literal] 5
# 1566| Type = [IntType] int
# 1566| Value = [Literal] 5
# 1566| ValueCategory = prvalue
# 1566| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1566| Type = [IntType] int
# 1566| ValueCategory = lvalue
# 1567| getStmt(5): [DeclStmt] declaration
# 1567| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1567| Type = [LValueReferenceType] int &
# 1567| getVariable().getInitializer(): [Initializer] initializer for rr
# 1567| getExpr(): [VariableAccess] r
# 1567| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1567| ValueCategory = prvalue(load)
# 1567| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1567| Type = [LValueReferenceType] int &
# 1567| ValueCategory = prvalue
# 1567| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1567| Type = [IntType] int
# 1567| ValueCategory = lvalue
# 1568| getStmt(6): [DeclStmt] declaration
# 1568| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1568| Type = [IntType] int
# 1568| getVariable().getInitializer(): [Initializer] initializer for w
# 1568| getExpr(): [VariableAccess] r
# 1568| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1568| ValueCategory = prvalue(load)
# 1568| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1568| Type = [IntType] int
# 1568| ValueCategory = prvalue(load)
# 1571| getStmt(2): [BlockStmt] { ... }
# 1572| getStmt(0): [DeclStmt] declaration
# 1572| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1572| Type = [Struct] StructuredBindingTuple
# 1572| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1572| getExpr(): [VariableAccess] t
# 1572| Type = [Struct] StructuredBindingTuple
# 1572| ValueCategory = prvalue(load)
# 1573| getStmt(1): [DeclStmt] declaration
# 1573| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1573| Type = [LValueReferenceType] type &
# 1573| getVariable().getInitializer(): [Initializer] initializer for i
# 1573| getExpr(): [FunctionCall] call to get
# 1573| Type = [LValueReferenceType] type &
# 1573| ValueCategory = prvalue
# 1573| getQualifier(): [VariableAccess] unnamed_local_variable
# 1573| Type = [Struct] StructuredBindingTuple
# 1573| ValueCategory = lvalue
# 1573| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1573| Type = [LValueReferenceType] type &
# 1573| ValueCategory = prvalue
# 1573| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1573| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1573| ValueCategory = lvalue
# 1574| getStmt(2): [DeclStmt] declaration
# 1574| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 1574| Type = [LValueReferenceType] type &
# 1574| getVariable().getInitializer(): [Initializer] initializer for d
# 1574| getExpr(): [FunctionCall] call to get
# 1574| Type = [LValueReferenceType] type &
# 1574| ValueCategory = prvalue
# 1574| getQualifier(): [VariableAccess] unnamed_local_variable
# 1574| Type = [Struct] StructuredBindingTuple
# 1574| ValueCategory = lvalue
# 1574| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1574| Type = [LValueReferenceType] type &
# 1574| ValueCategory = prvalue
# 1574| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1574| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1574| ValueCategory = lvalue
# 1575| getStmt(3): [DeclStmt] declaration
# 1575| getDeclarationEntry(0): [VariableDeclarationEntry] definition of r
# 1575| Type = [LValueReferenceType] int &
# 1575| getVariable().getInitializer(): [Initializer] initializer for r
# 1575| getExpr(): [FunctionCall] call to get
# 1575| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1575| ValueCategory = prvalue
# 1575| getQualifier(): [VariableAccess] unnamed_local_variable
# 1575| Type = [Struct] StructuredBindingTuple
# 1575| ValueCategory = lvalue
# 1575| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1575| Type = [LValueReferenceType] int &
# 1575| ValueCategory = prvalue
# 1575| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1575| Type = [IntType] int
# 1575| ValueCategory = lvalue
# 1576| getStmt(4): [ExprStmt] ExprStmt
# 1576| getExpr(): [AssignExpr] ... = ...
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| ValueCategory = lvalue
# 1576| getLValue(): [VariableAccess] d
# 1576| Type = [LValueReferenceType] type &
# 1576| ValueCategory = prvalue(load)
# 1576| getRValue(): [Literal] 4.0
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| Value = [Literal] 4.0
# 1576| ValueCategory = prvalue
# 1576| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| ValueCategory = lvalue
# 1577| getStmt(5): [DeclStmt] declaration
# 1577| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1577| Type = [LValueReferenceType] double &
# 1577| getVariable().getInitializer(): [Initializer] initializer for rd
# 1577| getExpr(): [VariableAccess] d
# 1577| Type = [LValueReferenceType] type &
# 1577| ValueCategory = prvalue(load)
# 1577| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1577| Type = [LValueReferenceType] type &
# 1577| ValueCategory = prvalue
# 1577| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1577| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1577| ValueCategory = lvalue
# 1578| getStmt(6): [DeclStmt] declaration
# 1578| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1578| Type = [IntType] int
# 1578| getVariable().getInitializer(): [Initializer] initializer for v
# 1578| getExpr(): [VariableAccess] i
# 1578| Type = [LValueReferenceType] type &
# 1578| ValueCategory = prvalue(load)
# 1578| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1578| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1578| ValueCategory = prvalue(load)
# 1579| getStmt(7): [ExprStmt] ExprStmt
# 1579| getExpr(): [AssignExpr] ... = ...
# 1579| Type = [IntType] int
# 1579| ValueCategory = lvalue
# 1579| getLValue(): [VariableAccess] r
# 1579| Type = [LValueReferenceType] int &
# 1579| ValueCategory = prvalue(load)
# 1579| getRValue(): [Literal] 5
# 1579| Type = [IntType] int
# 1579| Value = [Literal] 5
# 1579| ValueCategory = prvalue
# 1579| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1579| Type = [IntType] int
# 1579| ValueCategory = lvalue
# 1580| getStmt(8): [DeclStmt] declaration
# 1580| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1580| Type = [LValueReferenceType] int &
# 1580| getVariable().getInitializer(): [Initializer] initializer for rr
# 1580| getExpr(): [VariableAccess] r
# 1580| Type = [LValueReferenceType] int &
# 1580| ValueCategory = prvalue(load)
# 1580| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1580| Type = [LValueReferenceType] int &
# 1580| ValueCategory = prvalue
# 1580| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1580| Type = [IntType] int
# 1580| ValueCategory = lvalue
# 1581| getStmt(9): [DeclStmt] declaration
# 1581| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1581| Type = [IntType] int
# 1581| getVariable().getInitializer(): [Initializer] initializer for w
# 1581| getExpr(): [VariableAccess] r
# 1581| Type = [LValueReferenceType] int &
# 1581| ValueCategory = prvalue(load)
# 1581| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1581| Type = [IntType] int
# 1581| ValueCategory = prvalue(load)
# 1583| getStmt(3): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

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