mirror of
https://github.com/github/codeql.git
synced 2026-05-29 18:41:27 +02:00
Compare commits
247 Commits
nickrolfe/
...
annarailto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b9e567919 | ||
|
|
eee33dfdda | ||
|
|
644274adfd | ||
|
|
86ee0e7789 | ||
|
|
af02c1ed5b | ||
|
|
c5ce60c872 | ||
|
|
39aabc6427 | ||
|
|
b308ab5130 | ||
|
|
df224b1e6e | ||
|
|
164b7deb96 | ||
|
|
6c3daf49f9 | ||
|
|
bb1e89d261 | ||
|
|
22ef35e13a | ||
|
|
be5e8dae05 | ||
|
|
e57a0e0e2f | ||
|
|
b38335a6c2 | ||
|
|
182c62f5c3 | ||
|
|
567768134f | ||
|
|
67be20f368 | ||
|
|
eee03ebe3b | ||
|
|
6487b546dc | ||
|
|
f365477996 | ||
|
|
bc5753cb20 | ||
|
|
e9b496ba73 | ||
|
|
2e2913b921 | ||
|
|
fcaead4004 | ||
|
|
b747391c74 | ||
|
|
d08c0f7852 | ||
|
|
bc17df55ee | ||
|
|
72b5edc144 | ||
|
|
ab7fd89653 | ||
|
|
e328c6222a | ||
|
|
22aa4c9379 | ||
|
|
8544cff1c4 | ||
|
|
c8bc5cfa75 | ||
|
|
32756cd442 | ||
|
|
55cbff7614 | ||
|
|
912842623d | ||
|
|
836c47abb3 | ||
|
|
8031c3f699 | ||
|
|
02b1774d7f | ||
|
|
ef227a4721 | ||
|
|
3cfd1b5052 | ||
|
|
8386b36217 | ||
|
|
3b844f701e | ||
|
|
cf68148316 | ||
|
|
e2de0e61ca | ||
|
|
e93c46ad31 | ||
|
|
58993e2dc6 | ||
|
|
5284bbb6b3 | ||
|
|
224d7a7ce0 | ||
|
|
dca03d7b5d | ||
|
|
d5ab119039 | ||
|
|
3c9b332ce0 | ||
|
|
6bb71f051b | ||
|
|
2a9f98cce0 | ||
|
|
704b58519f | ||
|
|
df91ee6616 | ||
|
|
7ef051456a | ||
|
|
7b5699d058 | ||
|
|
2fe65128a0 | ||
|
|
c4ad237a5c | ||
|
|
516bd9f77f | ||
|
|
09c5212ccc | ||
|
|
d7eeb1fec8 | ||
|
|
2c17437092 | ||
|
|
a586be956e | ||
|
|
708da8cd62 | ||
|
|
4048ba0a1c | ||
|
|
39a2ffd438 | ||
|
|
6acf49d4da | ||
|
|
cc20969bdd | ||
|
|
4f13bf8941 | ||
|
|
54e8ea56e8 | ||
|
|
1aa32b09be | ||
|
|
7018f6ad40 | ||
|
|
e6745dc63a | ||
|
|
422919b9d0 | ||
|
|
fbcb8d6857 | ||
|
|
3b05cb621c | ||
|
|
33b97f3e0c | ||
|
|
fdcef6225b | ||
|
|
7bb11b837c | ||
|
|
712418e5f8 | ||
|
|
d4c4e75bac | ||
|
|
860ded2806 | ||
|
|
62d987f31f | ||
|
|
e622e517d9 | ||
|
|
ce0354acb3 | ||
|
|
9c32ab7122 | ||
|
|
613ecbb418 | ||
|
|
d864af3622 | ||
|
|
fb00a6c61b | ||
|
|
14601316a5 | ||
|
|
e06f6529f1 | ||
|
|
368839edfc | ||
|
|
ea901adb3c | ||
|
|
db0b4fc463 | ||
|
|
73d60550ce | ||
|
|
0f85a52f09 | ||
|
|
6451a71a78 | ||
|
|
3597d80340 | ||
|
|
5828a61fec | ||
|
|
a51f892a99 | ||
|
|
2c6e35f55e | ||
|
|
31a70a17a4 | ||
|
|
8ee27be908 | ||
|
|
7d1d2e792c | ||
|
|
5a6667efc5 | ||
|
|
c94cdfa79a | ||
|
|
e86ac73628 | ||
|
|
e6c90670e6 | ||
|
|
f7a0b17ed6 | ||
|
|
a59a9ba82b | ||
|
|
8df04c58e9 | ||
|
|
e5b7478028 | ||
|
|
990e07b986 | ||
|
|
46c1744204 | ||
|
|
4a29095e3b | ||
|
|
56941dba6b | ||
|
|
ca2ff6f9fb | ||
|
|
5503abc73d | ||
|
|
f2352d8272 | ||
|
|
83ecc065ab | ||
|
|
56ac99039f | ||
|
|
8dcec2e037 | ||
|
|
ec1a8cc826 | ||
|
|
2354281721 | ||
|
|
32e58add7b | ||
|
|
211345c010 | ||
|
|
7cbeffc8a7 | ||
|
|
cac3862659 | ||
|
|
0c3bce1415 | ||
|
|
d7313f3a82 | ||
|
|
bb2feda8fb | ||
|
|
8a1b49f816 | ||
|
|
0f239e315c | ||
|
|
0396a84c3c | ||
|
|
af09dd8af1 | ||
|
|
036e1495b8 | ||
|
|
aceeb7324c | ||
|
|
a695f02af4 | ||
|
|
82cceb0a29 | ||
|
|
682163962a | ||
|
|
4bf07825a1 | ||
|
|
b73dc98191 | ||
|
|
864b61a804 | ||
|
|
28702dff82 | ||
|
|
7b925604df | ||
|
|
588e60e230 | ||
|
|
7aa59ca233 | ||
|
|
47a57e0c0a | ||
|
|
74d57bbb1a | ||
|
|
b5198bdaca | ||
|
|
bf9bcc9600 | ||
|
|
179c26da9a | ||
|
|
f3e034b2be | ||
|
|
0428b8ee20 | ||
|
|
ee52774e90 | ||
|
|
ee5495ce65 | ||
|
|
b01f81aab3 | ||
|
|
a1b0f02e6e | ||
|
|
c6130ea2d4 | ||
|
|
cca74e925f | ||
|
|
c60df7d69c | ||
|
|
4632c14280 | ||
|
|
cd5010fe11 | ||
|
|
b7fb9e8b95 | ||
|
|
17656fc12b | ||
|
|
b93c04bb79 | ||
|
|
cdfe239016 | ||
|
|
6f06263d49 | ||
|
|
516bed391a | ||
|
|
5c9c83d331 | ||
|
|
47528dd8c0 | ||
|
|
39a853b5e4 | ||
|
|
1cfb088634 | ||
|
|
e5acc6b54b | ||
|
|
3646ae0995 | ||
|
|
10aa7a7982 | ||
|
|
b9c3e6a052 | ||
|
|
66b9974dd4 | ||
|
|
4aa0002e97 | ||
|
|
e2ae327a74 | ||
|
|
cb52ab669e | ||
|
|
c1b5565e4d | ||
|
|
e28669e487 | ||
|
|
f4195219f4 | ||
|
|
a7f755cf12 | ||
|
|
e75dc2116f | ||
|
|
47af3a69a5 | ||
|
|
abd87615ff | ||
|
|
de633940fe | ||
|
|
f1d5d3af9d | ||
|
|
44cc044a3d | ||
|
|
833e8e4f1d | ||
|
|
83e7fae578 | ||
|
|
c5904b7410 | ||
|
|
517f2d0823 | ||
|
|
d0a274c1e8 | ||
|
|
5e7a29a979 | ||
|
|
4f4f531dfc | ||
|
|
588447d596 | ||
|
|
8419daad03 | ||
|
|
4326e6f706 | ||
|
|
79735f5ac5 | ||
|
|
4df0f399cd | ||
|
|
c6dd7ddf7a | ||
|
|
4f253590f1 | ||
|
|
652a1d2dc2 | ||
|
|
5cf664411b | ||
|
|
baa1f71a53 | ||
|
|
4e4f619ae4 | ||
|
|
c5ed5fcaac | ||
|
|
ee84dae164 | ||
|
|
16b61f78e6 | ||
|
|
f0604e2e84 | ||
|
|
9aa4c4a6a7 | ||
|
|
41908cbf9f | ||
|
|
49d4b1480d | ||
|
|
35c9307baa | ||
|
|
debebb2b8c | ||
|
|
a5bc5373d0 | ||
|
|
5dcee6ba27 | ||
|
|
32cbeae05f | ||
|
|
d10ad3bdd4 | ||
|
|
7e9a9e3d9a | ||
|
|
a0e79c1d7a | ||
|
|
93b3cd669a | ||
|
|
db253e8939 | ||
|
|
ef9fb0873f | ||
|
|
36e18d5d80 | ||
|
|
bb210f4172 | ||
|
|
de8ecb214f | ||
|
|
b17f844f35 | ||
|
|
b7a0b8765e | ||
|
|
426f3117d6 | ||
|
|
49d2fbfb5f | ||
|
|
557cb0a09e | ||
|
|
657c576186 | ||
|
|
38debc0b64 | ||
|
|
d181ee1701 | ||
|
|
5e69eb491f | ||
|
|
734422f384 | ||
|
|
9672128699 | ||
|
|
c0a3cd07a5 | ||
|
|
881539c735 |
@@ -6,6 +6,7 @@
|
||||
"*/ql/examples/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",
|
||||
|
||||
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -50,4 +50,9 @@
|
||||
*.pdb -text
|
||||
|
||||
java/ql/test/stubs/**/*.java linguist-generated=true
|
||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||
|
||||
# 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
|
||||
|
||||
7
.github/workflows/codeql-analysis.yml
vendored
7
.github/workflows/codeql-analysis.yml
vendored
@@ -27,6 +27,11 @@ 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
|
||||
|
||||
@@ -51,7 +56,7 @@ jobs:
|
||||
# uses a compiled language
|
||||
|
||||
- run: |
|
||||
dotnet build csharp
|
||||
dotnet build csharp /p:UseSharedCompilation=false
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
|
||||
67
.github/workflows/js-ml-tests.yml
vendored
Normal file
67
.github/workflows/js-ml-tests.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
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: 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: Run QL tests
|
||||
run: |
|
||||
codeql test run \
|
||||
--threads=0 \
|
||||
--ram 5120 \
|
||||
--additional-packs "${{ github.workspace }}" \
|
||||
-- \
|
||||
test
|
||||
103
.github/workflows/mad_modelDiff.yml
vendored
Normal file
103
.github/workflows/mad_modelDiff.yml
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
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
|
||||
62
.github/workflows/mad_regenerate-models.yml
vendored
Normal file
62
.github/workflows/mad_regenerate-models.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
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
|
||||
7
.github/workflows/ql-for-ql-build.yml
vendored
7
.github/workflows/ql-for-ql-build.yml
vendored
@@ -189,4 +189,11 @@ 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
|
||||
|
||||
|
||||
@@ -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('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
||||
- name: Build Extractor
|
||||
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
|
||||
env:
|
||||
|
||||
8
.github/workflows/ql-for-ql-tests.yml
vendored
8
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -29,24 +29,24 @@ jobs:
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ql/target
|
||||
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/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 }}
|
||||
|
||||
2
.github/workflows/ruby-build.yml
vendored
2
.github/workflows/ruby-build.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ruby/target
|
||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Build
|
||||
|
||||
32
.github/workflows/ruby-qltest.yml
vendored
32
.github/workflows/ruby-qltest.yml
vendored
@@ -24,27 +24,45 @@ defaults:
|
||||
working-directory: ruby
|
||||
|
||||
jobs:
|
||||
qltest:
|
||||
qlformat:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --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
|
||||
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
|
||||
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
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
/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
|
||||
@@ -27,4 +30,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
51
benjamin-button.md
Normal 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 `"\$.*\$"`.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
|
||||
<ApplicationIcon />
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
name: codeql/cpp-examples
|
||||
version: 0.0.2
|
||||
groups:
|
||||
- cpp
|
||||
- examples
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
|
||||
@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** Content tagged with the type of a containing object. */
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
@@ -592,12 +592,14 @@ 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)) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -124,12 +124,14 @@ 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))
|
||||
}
|
||||
|
||||
@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** Content tagged with the type of a containing object. */
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
@@ -1032,12 +1032,14 @@ 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))
|
||||
}
|
||||
@@ -1046,6 +1048,7 @@ 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 =
|
||||
|
||||
@@ -121,12 +121,14 @@ 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))
|
||||
}
|
||||
@@ -135,6 +137,7 @@ 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))
|
||||
}
|
||||
|
||||
@@ -567,6 +567,13 @@ 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)
|
||||
|
||||
@@ -573,6 +573,11 @@ 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() {
|
||||
|
||||
@@ -917,3 +917,36 @@ 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
|
||||
}
|
||||
|
||||
@@ -11,15 +11,14 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
|
||||
/**
|
||||
* The standard functions `gets` and `fgets`.
|
||||
* The standard functions `fgets` and `fgetws`.
|
||||
*/
|
||||
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
|
||||
private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
|
||||
SideEffectFunction, RemoteFlowSourceFunction {
|
||||
GetsFunction() {
|
||||
// gets(str)
|
||||
FgetsFunction() {
|
||||
// fgets(str, num, stream)
|
||||
// fgetws(wstr, num, stream)
|
||||
this.hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
|
||||
this.hasGlobalOrStdOrBslName(["fgets", "fgetws"])
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -51,20 +50,61 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
|
||||
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.isParameter(2) }
|
||||
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 }
|
||||
}
|
||||
|
||||
@@ -6,122 +6,22 @@
|
||||
*/
|
||||
class Person extends string {
|
||||
Person() {
|
||||
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"
|
||||
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"
|
||||
]
|
||||
}
|
||||
|
||||
/** Gets the hair color of the person. If the person is bald, there is no result. */
|
||||
@@ -936,25 +836,12 @@ class Person extends string {
|
||||
|
||||
/** Holds if the person is deceased. */
|
||||
predicate isDeceased() {
|
||||
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"
|
||||
this =
|
||||
[
|
||||
"Ernest", "Gertrude", "Oscar", "Lilian", "Edwin", "Raymond", "Elgar", "Elmer", "Herbert",
|
||||
"Maude", "Mae", "Otto", "Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel",
|
||||
"King Basil"
|
||||
]
|
||||
}
|
||||
|
||||
/** Gets a parent of the person (alive or deceased). */
|
||||
@@ -1195,12 +1082,7 @@ 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" or
|
||||
region = "south" or
|
||||
region = "east" or
|
||||
region = "west"
|
||||
}
|
||||
predicate isAllowedIn(string region) { region = ["north", "south", "east", "west"] }
|
||||
}
|
||||
|
||||
/** Returns a parent of the person. */
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ 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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @precision high
|
||||
* @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,6 +27,7 @@ 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
|
||||
@@ -58,7 +59,10 @@ class Send extends SendRecv instanceof RemoteFlowSinkFunction {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionInput input, int arg |
|
||||
super.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
(
|
||||
input.isParameter(arg) or
|
||||
input.isParameterDeref(arg)
|
||||
) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
@@ -81,7 +85,10 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionInput input, int arg |
|
||||
super.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
(
|
||||
input.isParameter(arg) or
|
||||
input.isParameterDeref(arg)
|
||||
) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
@@ -114,24 +121,32 @@ abstract class NetworkSendRecv extends FunctionCall {
|
||||
NetworkSendRecv() {
|
||||
this.getTarget() = target and
|
||||
// exclude calls based on the socket...
|
||||
not exists(GVN g |
|
||||
g = globalValueNumber(target.getSocketExpr(this)) and
|
||||
not exists(DataFlow::Node src, DataFlow::Node dest |
|
||||
DataFlow::localFlow(src, dest) and
|
||||
dest.asExpr() = target.getSocketExpr(this) and
|
||||
(
|
||||
// literal constant
|
||||
globalValueNumber(any(Literal l)) = g
|
||||
src.asExpr() instanceof Literal
|
||||
or
|
||||
// variable (such as a global) initialized to a literal constant
|
||||
exists(Variable v |
|
||||
v.getInitializer().getExpr() instanceof Literal and
|
||||
g = globalValueNumber(v.getAnAccess())
|
||||
src.asExpr() = 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 |
|
||||
forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and
|
||||
g = globalValueNumber(fc)
|
||||
fopenCall(fc) and
|
||||
fc.getAnArgument().getValue() = "/dev/tty" and
|
||||
src.asExpr() = fc
|
||||
)
|
||||
// (this is far from exhaustive)
|
||||
// (this is not exhaustive)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/cleartext-storage-file` query has been improved, removing false positives where data is written to a standard output stream.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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.
|
||||
9
cpp/ql/src/experimental/Best Practices/UselessTest.cpp
Normal file
9
cpp/ql/src/experimental/Best Practices/UselessTest.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
void test(){
|
||||
int a = 8;
|
||||
int b = 9;
|
||||
|
||||
//Useless NonEquals
|
||||
if(a==8 && a != 7) {}
|
||||
|
||||
while(a==8 && a!=7){}
|
||||
}
|
||||
18
cpp/ql/src/experimental/Best Practices/UselessTest.qhelp
Normal file
18
cpp/ql/src/experimental/Best Practices/UselessTest.qhelp
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Comparison operations like <code>a==8 && 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>
|
||||
43
cpp/ql/src/experimental/Best Practices/UselessTest.ql
Normal file
43
cpp/ql/src/experimental/Best Practices/UselessTest.ql
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @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
|
||||
nearestParent(eq) = nearestParent(ne) and
|
||||
sameExpr(eq.getLeftOperand(), ne.getLeftOperand())
|
||||
select ne, "Useless Test"
|
||||
@@ -1,6 +1,8 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.8-dev
|
||||
groups: cpp
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
private import InlineExpectationsTestPrivate
|
||||
|
||||
/**
|
||||
* Base class for tests with inline expectations. The test extends this class to provide the actual
|
||||
* The 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,6 +123,15 @@ 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
|
||||
@@ -134,7 +143,8 @@ abstract class InlineExpectationsTest extends string {
|
||||
)
|
||||
or
|
||||
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
|
||||
message = "Unexpected result: " + actualResult.getExpectationText()
|
||||
message = "Unexpected result: " + actualResult.getExpectationText() and
|
||||
not actualResult.isOptional()
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -243,9 +253,13 @@ private string expectationPattern() {
|
||||
|
||||
private newtype TFailureLocatable =
|
||||
TActualResult(
|
||||
InlineExpectationsTest test, Location location, string element, string tag, string value
|
||||
InlineExpectationsTest test, Location location, string element, string tag, string value,
|
||||
boolean optional
|
||||
) {
|
||||
test.hasActualResult(location, element, tag, value)
|
||||
test.hasActualResult(location, element, tag, value) and
|
||||
optional = false
|
||||
or
|
||||
test.hasOptionalResult(location, element, tag, value) and optional = true
|
||||
} or
|
||||
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
|
||||
exists(TColumn column, string tags |
|
||||
@@ -277,8 +291,9 @@ class ActualResult extends FailureLocatable, TActualResult {
|
||||
string element;
|
||||
string tag;
|
||||
string value;
|
||||
boolean optional;
|
||||
|
||||
ActualResult() { this = TActualResult(test, location, element, tag, value) }
|
||||
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
|
||||
|
||||
override string toString() { result = element }
|
||||
|
||||
@@ -289,6 +304,8 @@ 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 {
|
||||
|
||||
@@ -11332,6 +11332,64 @@ 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 ...
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
|
||||
@@ -1447,4 +1447,15 @@ void temporary_hierarchy() {
|
||||
float f = (returnValue<POD_Derived>()).f();
|
||||
}
|
||||
|
||||
struct Inheritance_Test_B {
|
||||
~Inheritance_Test_B() {}
|
||||
};
|
||||
|
||||
struct Inheritance_Test_A : public Inheritance_Test_B {
|
||||
int x;
|
||||
int y;
|
||||
Inheritance_Test_A() : x(42) {
|
||||
y = 3;
|
||||
}
|
||||
};
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -6626,6 +6626,36 @@
|
||||
| ir.cpp:1447:44:1447:44 | ChiTotal | total:m1447_5 |
|
||||
| ir.cpp:1447:44:1447:44 | SideEffect | ~m1447_5 |
|
||||
| ir.cpp:1447:44:1447:44 | StoreValue | r1447_8 |
|
||||
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
|
||||
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
|
||||
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
|
||||
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
|
||||
| ir.cpp:1451:3:1451:21 | ChiPartial | partial:m1451_3 |
|
||||
| ir.cpp:1451:3:1451:21 | ChiTotal | total:m1451_2 |
|
||||
| ir.cpp:1451:3:1451:21 | Load | m1451_6 |
|
||||
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_3 |
|
||||
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_8 |
|
||||
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
|
||||
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
|
||||
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
|
||||
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
|
||||
| ir.cpp:1457:3:1457:20 | ChiPartial | partial:m1457_3 |
|
||||
| ir.cpp:1457:3:1457:20 | ChiTotal | total:m1457_2 |
|
||||
| ir.cpp:1457:3:1457:20 | Load | m1457_6 |
|
||||
| ir.cpp:1457:3:1457:20 | SideEffect | m1457_3 |
|
||||
| ir.cpp:1457:3:1457:20 | SideEffect | m1458_6 |
|
||||
| ir.cpp:1457:3:1457:20 | Unary | m1457_6 |
|
||||
| ir.cpp:1457:26:1457:30 | Address | &:r1457_9 |
|
||||
| ir.cpp:1457:26:1457:30 | ChiPartial | partial:m1457_11 |
|
||||
| ir.cpp:1457:26:1457:30 | ChiTotal | total:m1457_8 |
|
||||
| ir.cpp:1457:26:1457:30 | StoreValue | r1457_10 |
|
||||
| ir.cpp:1458:5:1458:5 | Address | &:r1458_2 |
|
||||
| ir.cpp:1458:5:1458:5 | Address | &:r1458_4 |
|
||||
| ir.cpp:1458:5:1458:5 | Load | m1457_6 |
|
||||
| ir.cpp:1458:5:1458:5 | Unary | r1458_3 |
|
||||
| ir.cpp:1458:5:1458:9 | ChiPartial | partial:m1458_5 |
|
||||
| ir.cpp:1458:5:1458:9 | ChiTotal | total:m1457_12 |
|
||||
| ir.cpp:1458:9:1458:9 | StoreValue | r1458_1 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -7858,6 +7858,44 @@ ir.cpp:
|
||||
# 1443| v1443_5(void) = AliasedUse : ~m?
|
||||
# 1443| v1443_6(void) = ExitFunction :
|
||||
|
||||
# 1451| void Inheritance_Test_B::~Inheritance_Test_B()
|
||||
# 1451| Block 0
|
||||
# 1451| v1451_1(void) = EnterFunction :
|
||||
# 1451| mu1451_2(unknown) = AliasedDefinition :
|
||||
# 1451| mu1451_3(unknown) = InitializeNonLocal :
|
||||
# 1451| r1451_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1451| mu1451_5(glval<Inheritance_Test_B>) = InitializeParameter[#this] : &:r1451_4
|
||||
# 1451| r1451_6(glval<Inheritance_Test_B>) = Load[#this] : &:r1451_4, ~m?
|
||||
# 1451| mu1451_7(Inheritance_Test_B) = InitializeIndirection[#this] : &:r1451_6
|
||||
# 1451| v1451_8(void) = NoOp :
|
||||
# 1451| v1451_9(void) = ReturnIndirection[#this] : &:r1451_6, ~m?
|
||||
# 1451| v1451_10(void) = ReturnVoid :
|
||||
# 1451| v1451_11(void) = AliasedUse : ~m?
|
||||
# 1451| v1451_12(void) = ExitFunction :
|
||||
|
||||
# 1457| void Inheritance_Test_A::Inheritance_Test_A()
|
||||
# 1457| Block 0
|
||||
# 1457| v1457_1(void) = EnterFunction :
|
||||
# 1457| mu1457_2(unknown) = AliasedDefinition :
|
||||
# 1457| mu1457_3(unknown) = InitializeNonLocal :
|
||||
# 1457| r1457_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1457| mu1457_5(glval<Inheritance_Test_A>) = InitializeParameter[#this] : &:r1457_4
|
||||
# 1457| r1457_6(glval<Inheritance_Test_A>) = Load[#this] : &:r1457_4, ~m?
|
||||
# 1457| mu1457_7(Inheritance_Test_A) = InitializeIndirection[#this] : &:r1457_6
|
||||
# 1457| r1457_8(glval<int>) = FieldAddress[x] : mu1457_5
|
||||
# 1457| r1457_9(int) = Constant[42] :
|
||||
# 1457| mu1457_10(int) = Store[?] : &:r1457_8, r1457_9
|
||||
# 1458| r1458_1(int) = Constant[3] :
|
||||
# 1458| r1458_2(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1458| r1458_3(Inheritance_Test_A *) = Load[#this] : &:r1458_2, ~m?
|
||||
# 1458| r1458_4(glval<int>) = FieldAddress[y] : r1458_3
|
||||
# 1458| mu1458_5(int) = Store[?] : &:r1458_4, r1458_1
|
||||
# 1459| v1459_1(void) = NoOp :
|
||||
# 1457| v1457_11(void) = ReturnIndirection[#this] : &:r1457_6, ~m?
|
||||
# 1457| v1457_12(void) = ReturnVoid :
|
||||
# 1457| v1457_13(void) = AliasedUse : ~m?
|
||||
# 1457| v1457_14(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
edges
|
||||
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input |
|
||||
nodes
|
||||
| test2.cpp:110:3:110:6 | call to gets | semmle.label | call to gets |
|
||||
| test.cpp:54:17:54:20 | argv | semmle.label | argv |
|
||||
| test.cpp:58:25:58:29 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@ | test2.cpp:110:3:110:6 | call to gets | user input (String read by gets) |
|
||||
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (a command-line argument) |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
edges
|
||||
| test2.cpp:63:24:63:31 | password | test2.cpp:63:16:63:20 | call to crypt |
|
||||
| test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 |
|
||||
| test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 |
|
||||
| test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password |
|
||||
@@ -89,11 +90,16 @@ edges
|
||||
| test3.cpp:398:18:398:25 | password | test3.cpp:400:15:400:23 | & ... |
|
||||
| test3.cpp:398:18:398:25 | password | test3.cpp:400:16:400:23 | password |
|
||||
| test3.cpp:398:18:398:25 | password | test3.cpp:400:33:400:40 | password |
|
||||
| test3.cpp:421:21:421:28 | password | test3.cpp:421:3:421:17 | call to decrypt_inplace |
|
||||
| test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
|
||||
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
|
||||
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:29:76:39 | thePassword |
|
||||
nodes
|
||||
| test2.cpp:63:16:63:20 | call to crypt | semmle.label | call to crypt |
|
||||
| test2.cpp:63:24:63:31 | password | semmle.label | password |
|
||||
| test2.cpp:63:24:63:31 | password | semmle.label | password |
|
||||
| test3.cpp:17:28:17:36 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:17:51:17:59 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:22:15:22:23 | password1 | semmle.label | password1 |
|
||||
@@ -208,6 +214,13 @@ nodes
|
||||
| test3.cpp:400:15:400:23 | & ... | semmle.label | & ... |
|
||||
| test3.cpp:400:16:400:23 | password | semmle.label | password |
|
||||
| test3.cpp:400:33:400:40 | password | semmle.label | password |
|
||||
| test3.cpp:414:17:414:24 | password | semmle.label | password |
|
||||
| test3.cpp:420:17:420:24 | password | semmle.label | password |
|
||||
| test3.cpp:421:3:421:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
|
||||
| test3.cpp:421:21:421:28 | password | semmle.label | password |
|
||||
| test3.cpp:421:21:421:28 | password | semmle.label | password |
|
||||
| test3.cpp:429:7:429:14 | password | semmle.label | password |
|
||||
| test3.cpp:431:8:431:15 | password | semmle.label | password |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
|
||||
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
|
||||
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
|
||||
@@ -238,3 +251,6 @@ subpaths
|
||||
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
|
||||
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
|
||||
| test3.cpp:388:3:388:6 | call to recv | test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:386:8:386:15 | password | password |
|
||||
| test3.cpp:414:3:414:6 | call to recv | test3.cpp:414:17:414:24 | password | test3.cpp:414:17:414:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:414:17:414:24 | password | password |
|
||||
| test3.cpp:420:3:420:6 | call to recv | test3.cpp:420:17:420:24 | password | test3.cpp:420:17:420:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:420:17:420:24 | password | password |
|
||||
| test3.cpp:431:2:431:6 | call to fgets | test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:429:7:429:14 | password | password |
|
||||
|
||||
@@ -99,3 +99,14 @@ void tests(FILE *log, myStruct &s)
|
||||
fprintf(log, "log: %s", buffer); // BAD
|
||||
}
|
||||
}
|
||||
|
||||
char *gets(char *s);
|
||||
|
||||
void test_gets()
|
||||
{
|
||||
{
|
||||
char password[1024];
|
||||
|
||||
gets(password); // BAD
|
||||
}
|
||||
}
|
||||
@@ -411,13 +411,66 @@ void test_member_password()
|
||||
{
|
||||
packet p;
|
||||
|
||||
recv(val(), p.password, 256, val()); // BAD: not encrypted [NOT DETECTED]
|
||||
recv(val(), p.password, 256, val()); // BAD: not encrypted
|
||||
}
|
||||
|
||||
{
|
||||
packet p;
|
||||
|
||||
recv(val(), p.password, 256, val()); // GOOD: password is encrypted
|
||||
recv(val(), p.password, 256, val()); // GOOD: password is encrypted [FALSE POSITIVE]
|
||||
decrypt_inplace(p.password); // proof that `password` was in fact encrypted
|
||||
}
|
||||
}
|
||||
|
||||
extern FILE *stdin;
|
||||
|
||||
void test_stdin_param(FILE *stream)
|
||||
{
|
||||
char password[128];
|
||||
|
||||
fgets(password, 128, stream); // GOOD: from standard input (see call below) [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test_stdin()
|
||||
{
|
||||
char password[128];
|
||||
FILE *f = stdin;
|
||||
|
||||
fgets(password, 128, stdin); // GOOD: from standard input
|
||||
fgets(password, 128, f); // GOOD: from standard input
|
||||
test_stdin_param(stdin);
|
||||
}
|
||||
|
||||
int open(const char *filename, int b);
|
||||
|
||||
void test_tty()
|
||||
{
|
||||
{
|
||||
char password[256];
|
||||
int f;
|
||||
|
||||
f = open("/dev/tty", val());
|
||||
recv(f, password, 256, val()); // GOOD: from terminal
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
int f;
|
||||
|
||||
f = STDIN_FILENO;
|
||||
recv(f, password, 256, val()); // GOOD: from stdin
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
int f;
|
||||
|
||||
f = open("/dev/tty", val());
|
||||
if (f == -1)
|
||||
{
|
||||
f = STDIN_FILENO;
|
||||
}
|
||||
|
||||
recv(f, password, 256, val()); // GOOD: from terminal or stdin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
|
||||
<ApplicationIcon/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove 'kind' from 'attributes'.
|
||||
compatability: full
|
||||
attributes.rel: reorder attributes.rel (int id, int kind, int type_id, int target) id type_id target
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Support for compiler-generated event accessors.
|
||||
compatibility: backwards
|
||||
2084
csharp/downgrades/initial/semmlecode.csharp.dbscheme
Normal file
2084
csharp/downgrades/initial/semmlecode.csharp.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CIL</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CIL</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp.Driver</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp.Driver</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Semmle.BuildAnalyser
|
||||
* loading the same assembly from different locations.
|
||||
*/
|
||||
using var pereader = new System.Reflection.PortableExecutable.PEReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read));
|
||||
using var sha1 = new SHA1CryptoServiceProvider();
|
||||
using var sha1 = SHA1.Create();
|
||||
var metadata = pereader.GetMetadata();
|
||||
unsafe
|
||||
{
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Semmle.BuildAnalyser
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(srcDir);
|
||||
|
||||
using var sha1 = new SHA1CryptoServiceProvider();
|
||||
using var sha1 = SHA1.Create();
|
||||
var sha = sha1.ComputeHash(bytes);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in sha.Take(8))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -6,11 +6,15 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class Accessor : Method
|
||||
{
|
||||
protected Accessor(Context cx, IMethodSymbol init)
|
||||
: base(cx, init) { }
|
||||
private readonly IPropertySymbol property;
|
||||
protected Accessor(Context cx, IMethodSymbol init, IPropertySymbol property)
|
||||
: base(cx, init)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property symbol associated accessor `symbol`, or `null`
|
||||
/// Gets the property symbol associated with accessor `symbol`, or `null`
|
||||
/// if there is no associated symbol.
|
||||
/// </summary>
|
||||
public static IPropertySymbol? GetPropertySymbol(IMethodSymbol symbol)
|
||||
@@ -26,39 +30,26 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return props.SingleOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property symbol associated with this accessor.
|
||||
/// </summary>
|
||||
private IPropertySymbol? PropertySymbol => GetPropertySymbol(Symbol);
|
||||
|
||||
public new Accessor OriginalDefinition => Create(Context, Symbol.OriginalDefinition);
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
PopulateMethod(trapFile);
|
||||
PopulateModifiers(trapFile);
|
||||
ContainingType!.PopulateGenerics();
|
||||
|
||||
var prop = PropertySymbol;
|
||||
if (prop is null)
|
||||
{
|
||||
var type = Symbol.AssociatedSymbol?.GetType().ToString() ?? "null";
|
||||
Context.ModelError(Symbol, $"Unhandled accessor associated symbol of type {type}");
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = Property.Create(Context, prop);
|
||||
var parent = Property.Create(Context, property);
|
||||
int kind;
|
||||
Accessor unboundAccessor;
|
||||
if (SymbolEqualityComparer.Default.Equals(Symbol, prop.GetMethod))
|
||||
if (SymbolEqualityComparer.Default.Equals(Symbol, property.GetMethod))
|
||||
{
|
||||
kind = 1;
|
||||
unboundAccessor = Create(Context, prop.OriginalDefinition.GetMethod!);
|
||||
var orig = property.OriginalDefinition;
|
||||
unboundAccessor = Create(Context, orig.GetMethod!, orig);
|
||||
}
|
||||
else if (SymbolEqualityComparer.Default.Equals(Symbol, prop.SetMethod))
|
||||
else if (SymbolEqualityComparer.Default.Equals(Symbol, property.SetMethod))
|
||||
{
|
||||
kind = 2;
|
||||
unboundAccessor = Create(Context, prop.OriginalDefinition.SetMethod!);
|
||||
var orig = property.OriginalDefinition;
|
||||
unboundAccessor = Create(Context, orig.SetMethod!, orig);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -84,14 +75,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static new Accessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
public static Accessor Create(Context cx, IMethodSymbol symbol, IPropertySymbol prop) =>
|
||||
AccessorFactory.Instance.CreateEntity(cx, symbol, (symbol, prop));
|
||||
|
||||
private class AccessorFactory : CachedEntityFactory<IMethodSymbol, Accessor>
|
||||
private class AccessorFactory : CachedEntityFactory<(IMethodSymbol, IPropertySymbol), Accessor>
|
||||
{
|
||||
public static AccessorFactory Instance { get; } = new AccessorFactory();
|
||||
|
||||
public override Accessor Create(Context cx, IMethodSymbol init) => new Accessor(cx, init);
|
||||
public override Accessor Create(Context cx, (IMethodSymbol, IPropertySymbol) init) => new(cx, init.Item1, init.Item2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
@@ -6,18 +8,28 @@ using Semmle.Extraction.Entities;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal enum AttributeKind
|
||||
{
|
||||
Default = 0,
|
||||
Return = 1,
|
||||
Assembly = 2,
|
||||
Module = 3,
|
||||
}
|
||||
|
||||
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
|
||||
{
|
||||
bool IExpressionParentEntity.IsTopLevelParent => true;
|
||||
|
||||
private readonly AttributeSyntax? attributeSyntax;
|
||||
private readonly IEntity entity;
|
||||
private readonly AttributeKind kind;
|
||||
|
||||
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
|
||||
private Attribute(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
|
||||
: base(cx, attributeData)
|
||||
{
|
||||
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
|
||||
this.entity = entity;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
@@ -48,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
var type = Type.Create(Context, Symbol.AttributeClass);
|
||||
trapFile.attributes(this, type.TypeRef, entity);
|
||||
trapFile.attributes(this, kind, type.TypeRef, entity);
|
||||
trapFile.attribute_location(this, Location);
|
||||
|
||||
if (attributeSyntax is not null)
|
||||
@@ -125,26 +137,36 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
|
||||
private static void ExtractAttributes(Context cx, IEnumerable<AttributeData> attributes, IEntity entity, AttributeKind kind)
|
||||
{
|
||||
foreach (var attribute in symbol.GetAttributes())
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
Create(cx, attribute, entity);
|
||||
Create(cx, attribute, entity, kind);
|
||||
}
|
||||
}
|
||||
|
||||
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
|
||||
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
|
||||
{
|
||||
var init = (attributeData, entity);
|
||||
ExtractAttributes(cx, symbol.GetAttributes(), entity, AttributeKind.Default);
|
||||
if (symbol is IMethodSymbol method)
|
||||
{
|
||||
ExtractAttributes(cx, method.GetReturnTypeAttributes(), entity, AttributeKind.Return);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
|
||||
{
|
||||
var init = (attributeData, entity, kind);
|
||||
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
|
||||
}
|
||||
|
||||
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>
|
||||
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver, AttributeKind kind), Attribute>
|
||||
{
|
||||
public static readonly AttributeFactory Instance = new AttributeFactory();
|
||||
|
||||
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver) init) =>
|
||||
new Attribute(cx, init.attributeData, init.receiver);
|
||||
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver, AttributeKind kind) init) =>
|
||||
new Attribute(cx, init.attributeData, init.receiver, init.kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,45 +3,46 @@ using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class EventAccessor : Accessor
|
||||
internal class EventAccessor : Method
|
||||
{
|
||||
private EventAccessor(Context cx, IMethodSymbol init)
|
||||
: base(cx, init) { }
|
||||
private readonly IEventSymbol @event;
|
||||
|
||||
private EventAccessor(Context cx, IMethodSymbol init, IEventSymbol @event)
|
||||
: base(cx, init)
|
||||
{
|
||||
this.@event = @event;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event symbol associated with this accessor.
|
||||
/// Gets the event symbol associated with accessor `symbol`, or `null`
|
||||
/// if there is no associated symbol.
|
||||
/// </summary>
|
||||
private IEventSymbol? EventSymbol => Symbol.AssociatedSymbol as IEventSymbol;
|
||||
public static IEventSymbol? GetEventSymbol(IMethodSymbol symbol) =>
|
||||
symbol.AssociatedSymbol as IEventSymbol;
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
PopulateMethod(trapFile);
|
||||
ContainingType!.PopulateGenerics();
|
||||
|
||||
var @event = EventSymbol;
|
||||
if (@event is null)
|
||||
{
|
||||
var type = Symbol.AssociatedSymbol?.GetType().ToString() ?? "null";
|
||||
Context.ModelError(Symbol, $"Unhandled event accessor associated symbol of type {type}");
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = Event.Create(Context, @event);
|
||||
int kind;
|
||||
EventAccessor unboundAccessor;
|
||||
if (SymbolEqualityComparer.Default.Equals(Symbol, @event.AddMethod))
|
||||
{
|
||||
kind = 1;
|
||||
unboundAccessor = Create(Context, @event.OriginalDefinition.AddMethod!);
|
||||
var orig = @event.OriginalDefinition;
|
||||
unboundAccessor = Create(Context, orig.AddMethod!, orig);
|
||||
}
|
||||
else if (SymbolEqualityComparer.Default.Equals(Symbol, @event.RemoveMethod))
|
||||
{
|
||||
kind = 2;
|
||||
unboundAccessor = Create(Context, @event.OriginalDefinition.RemoveMethod!);
|
||||
var orig = @event.OriginalDefinition;
|
||||
unboundAccessor = Create(Context, orig.RemoveMethod!, orig);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.ModelError(Symbol, "Undhandled event accessor kind");
|
||||
Context.ModelError(Symbol, $"Undhandled event accessor kind {Symbol.ToDisplayString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,16 +52,21 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.event_accessor_location(this, l);
|
||||
|
||||
Overrides(trapFile);
|
||||
|
||||
if (Symbol.FromSource() && Block is null)
|
||||
{
|
||||
trapFile.compiler_generated(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static new EventAccessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
public static EventAccessor Create(Context cx, IMethodSymbol symbol, IEventSymbol @event) =>
|
||||
EventAccessorFactory.Instance.CreateEntity(cx, symbol, (symbol, @event));
|
||||
|
||||
private class EventAccessorFactory : CachedEntityFactory<IMethodSymbol, EventAccessor>
|
||||
private class EventAccessorFactory : CachedEntityFactory<(IMethodSymbol, IEventSymbol), EventAccessor>
|
||||
{
|
||||
public static EventAccessorFactory Instance { get; } = new EventAccessorFactory();
|
||||
|
||||
public override EventAccessor Create(Context cx, IMethodSymbol init) => new EventAccessor(cx, init);
|
||||
public override EventAccessor Create(Context cx, (IMethodSymbol, IEventSymbol) init) => new EventAccessor(cx, init.Item1, init.Item2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using Semmle.Extraction.Entities;
|
||||
@@ -10,17 +12,69 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
base(new ExpressionInfo(cx, null, cx.CreateLocation(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
|
||||
{
|
||||
child = 0;
|
||||
var trapFile = cx.TrapWriter.Writer;
|
||||
foreach (var sub in pp.Subpatterns)
|
||||
{
|
||||
var p = Expressions.Pattern.Create(cx, sub.Pattern, this, child++);
|
||||
if (sub.NameColon is null)
|
||||
if (sub.ExpressionColon is null)
|
||||
{
|
||||
Context.ModelError(sub, "Expected to find 'Name:' in pattern.");
|
||||
Context.ModelError(sub, "Expected to find 'Expression:' in pattern.");
|
||||
continue;
|
||||
}
|
||||
trapFile.exprorstmt_name(p, sub.NameColon.Name.ToString());
|
||||
MakeExpressions(cx, this, sub, child++);
|
||||
}
|
||||
}
|
||||
|
||||
private record AccessStep(string Identifier, Microsoft.CodeAnalysis.Location Location);
|
||||
|
||||
private class AccessStepPack
|
||||
{
|
||||
public readonly List<AccessStep> Prefix = new List<AccessStep>();
|
||||
public AccessStep Last { get; private set; }
|
||||
|
||||
public AccessStepPack Add(string identifier, Microsoft.CodeAnalysis.Location location)
|
||||
{
|
||||
Prefix.Add(Last);
|
||||
Last = new AccessStep(identifier, location);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccessStepPack(string identifier, Microsoft.CodeAnalysis.Location location) =>
|
||||
Last = new AccessStep(identifier, location);
|
||||
}
|
||||
|
||||
private static AccessStepPack GetAccessStepPack(ExpressionSyntax syntax) =>
|
||||
syntax switch
|
||||
{
|
||||
MemberAccessExpressionSyntax memberAccess => GetAccessStepPack(memberAccess.Expression).Add(memberAccess.Name.Identifier.ValueText, memberAccess.Name.Identifier.GetLocation()),
|
||||
IdentifierNameSyntax identifier => new AccessStepPack(identifier.Identifier.Text, identifier.GetLocation()),
|
||||
_ => throw new InternalError(syntax, "Unexpected expression syntax in property patterns."),
|
||||
};
|
||||
|
||||
private static AccessStepPack GetAccessStepPack(BaseExpressionColonSyntax syntax) =>
|
||||
syntax switch
|
||||
{
|
||||
NameColonSyntax ncs => new AccessStepPack(ncs.Name.ToString(), ncs.Name.GetLocation()),
|
||||
ExpressionColonSyntax ecs => GetAccessStepPack(ecs.Expression),
|
||||
_ => throw new InternalError(syntax, "Unsupported expression colon in property pattern."),
|
||||
};
|
||||
|
||||
private static Expression CreateSyntheticExp(Context cx, Microsoft.CodeAnalysis.Location location, IExpressionParentEntity parent, int child) =>
|
||||
new Expression(new ExpressionInfo(cx, null, cx.CreateLocation(location), ExprKind.PROPERTY_PATTERN, parent, child, false, null));
|
||||
|
||||
private static void MakeExpressions(Context cx, IExpressionParentEntity parent, SubpatternSyntax syntax, int child)
|
||||
{
|
||||
var trapFile = cx.TrapWriter.Writer;
|
||||
var pack = GetAccessStepPack(syntax.ExpressionColon!);
|
||||
|
||||
foreach (var step in pack.Prefix)
|
||||
{
|
||||
var exp = CreateSyntheticExp(cx, step.Location, parent, child);
|
||||
trapFile.exprorstmt_name(exp, step.Identifier);
|
||||
parent = exp;
|
||||
child = 0;
|
||||
}
|
||||
|
||||
var p = Expressions.Pattern.Create(cx, syntax.Pattern, parent, child);
|
||||
trapFile.exprorstmt_name(p, pack.Last.Identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,10 +262,10 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return Destructor.Create(cx, methodDecl);
|
||||
case MethodKind.PropertyGet:
|
||||
case MethodKind.PropertySet:
|
||||
return Accessor.GetPropertySymbol(methodDecl) is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl);
|
||||
return Accessor.GetPropertySymbol(methodDecl) is IPropertySymbol prop ? Accessor.Create(cx, methodDecl, prop) : OrdinaryMethod.Create(cx, methodDecl);
|
||||
case MethodKind.EventAdd:
|
||||
case MethodKind.EventRemove:
|
||||
return EventAccessor.Create(cx, methodDecl);
|
||||
return EventAccessor.GetEventSymbol(methodDecl) is IEventSymbol @event ? EventAccessor.Create(cx, methodDecl, @event) : OrdinaryMethod.Create(cx, methodDecl);
|
||||
case MethodKind.UserDefinedOperator:
|
||||
case MethodKind.BuiltinOperator:
|
||||
return UserOperator.Create(cx, methodDecl);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -21,34 +19,10 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
var constraints = new TypeParameterConstraints(Context);
|
||||
trapFile.type_parameter_constraints(constraints, this);
|
||||
|
||||
if (Symbol.HasReferenceTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(constraints, 1);
|
||||
|
||||
if (Symbol.HasValueTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(constraints, 2);
|
||||
|
||||
if (Symbol.HasConstructorConstraint)
|
||||
trapFile.general_type_parameter_constraints(constraints, 3);
|
||||
|
||||
if (Symbol.HasUnmanagedTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(constraints, 4);
|
||||
|
||||
if (Symbol.ReferenceTypeConstraintNullableAnnotation == NullableAnnotation.Annotated)
|
||||
trapFile.general_type_parameter_constraints(constraints, 5);
|
||||
|
||||
foreach (var abase in Symbol.GetAnnotatedTypeConstraints())
|
||||
{
|
||||
var t = Create(Context, abase.Symbol);
|
||||
trapFile.specific_type_parameter_constraints(constraints, t.TypeRef);
|
||||
if (!abase.HasObliviousNullability())
|
||||
trapFile.specific_type_parameter_nullability(constraints, t.TypeRef, NullabilityEntity.Create(Context, Nullability.Create(abase)));
|
||||
}
|
||||
|
||||
trapFile.types(this, Kinds.TypeKind.TYPE_PARAMETER, Symbol.Name);
|
||||
|
||||
TypeParameterConstraints.Create(Context, this);
|
||||
|
||||
var parentNs = Namespace.Create(Context, Symbol.TypeParameterKind == TypeParameterKind.Method ? Context.Compilation.GlobalNamespace : Symbol.ContainingNamespace);
|
||||
trapFile.parent_namespace(this, parentNs);
|
||||
|
||||
|
||||
@@ -1,14 +1,65 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class TypeParameterConstraints : FreshEntity
|
||||
internal class TypeParameterConstraints : CachedEntity<ITypeParameterSymbol>
|
||||
{
|
||||
public TypeParameterConstraints(Context cx)
|
||||
: base(cx) { }
|
||||
private readonly TypeParameter parent;
|
||||
|
||||
protected override void Populate(TextWriter trapFile)
|
||||
public TypeParameterConstraints(Context cx, TypeParameter parent)
|
||||
: base(cx, parent.Symbol)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(parent);
|
||||
trapFile.Write(";typeparameterconstraints");
|
||||
}
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
trapFile.type_parameter_constraints(this, parent);
|
||||
|
||||
if (Symbol.HasReferenceTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(this, 1);
|
||||
|
||||
if (Symbol.HasValueTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(this, 2);
|
||||
|
||||
if (Symbol.HasConstructorConstraint)
|
||||
trapFile.general_type_parameter_constraints(this, 3);
|
||||
|
||||
if (Symbol.HasUnmanagedTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(this, 4);
|
||||
|
||||
if (Symbol.ReferenceTypeConstraintNullableAnnotation == NullableAnnotation.Annotated)
|
||||
trapFile.general_type_parameter_constraints(this, 5);
|
||||
|
||||
foreach (var abase in Symbol.GetAnnotatedTypeConstraints())
|
||||
{
|
||||
var t = Type.Create(Context, abase.Symbol);
|
||||
trapFile.specific_type_parameter_constraints(this, t.TypeRef);
|
||||
if (!abase.HasObliviousNullability())
|
||||
trapFile.specific_type_parameter_nullability(this, t.TypeRef, NullabilityEntity.Create(Context, Nullability.Create(abase)));
|
||||
}
|
||||
}
|
||||
|
||||
public override Location? ReportingLocation => null;
|
||||
|
||||
public static TypeParameterConstraints Create(Context cx, TypeParameter p) =>
|
||||
TypeParameterConstraintsFactory.Instance.CreateEntity(cx, (typeof(TypeParameterConstraints), p), p);
|
||||
|
||||
private class TypeParameterConstraintsFactory : CachedEntityFactory<TypeParameter, TypeParameterConstraints>
|
||||
{
|
||||
public static TypeParameterConstraintsFactory Instance { get; } = new TypeParameterConstraintsFactory();
|
||||
|
||||
public override TypeParameterConstraints Create(Context cx, TypeParameter init) => new(cx, init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,6 +178,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
/// <returns>The converted name.</returns>
|
||||
private static string OperatorSymbol(Context cx, IMethodSymbol method)
|
||||
{
|
||||
if (method.ExplicitInterfaceImplementations.Any())
|
||||
return OperatorSymbol(cx, method.ExplicitInterfaceImplementations.First());
|
||||
|
||||
var methodName = method.Name;
|
||||
if (!OperatorSymbol(methodName, out var result))
|
||||
cx.ModelError(method, $"Unhandled operator name in OperatorSymbol(): '{methodName}'");
|
||||
|
||||
@@ -86,11 +86,17 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
return;
|
||||
|
||||
var outputAssembly = Assembly.CreateOutputAssembly(Cx);
|
||||
var kind = node.Target?.Identifier.Kind() switch
|
||||
{
|
||||
SyntaxKind.AssemblyKeyword => Entities.AttributeKind.Assembly,
|
||||
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
|
||||
_ => throw new InternalError(node, "Unhandled global target")
|
||||
};
|
||||
foreach (var attribute in node.Attributes)
|
||||
{
|
||||
if (attributeLookup.Value(attribute) is AttributeData attributeData)
|
||||
{
|
||||
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly);
|
||||
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);
|
||||
Cx.BindComments(ae, attribute.GetLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Semmle.Extraction.CSharp
|
||||
internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType) =>
|
||||
trapFile.WriteTuple("array_element_type", array, dimension, rank, elementType);
|
||||
|
||||
internal static void attributes(this TextWriter trapFile, Attribute attribute, Type attributeType, IEntity entity) =>
|
||||
trapFile.WriteTuple("attributes", attribute, attributeType, entity);
|
||||
internal static void attributes(this TextWriter trapFile, Attribute attribute, AttributeKind kind, Type attributeType, IEntity entity) =>
|
||||
trapFile.WriteTuple("attributes", attribute, kind, attributeType, entity);
|
||||
|
||||
internal static void attribute_location(this TextWriter trapFile, Attribute attribute, Location location) =>
|
||||
trapFile.WriteTuple("attribute_location", attribute, location);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Semmle.Util
|
||||
public static string ComputeFileHash(string filePath)
|
||||
{
|
||||
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var shaAlg = new SHA256Managed();
|
||||
using var shaAlg = SHA256.Create();
|
||||
var sha = shaAlg.ComputeHash(fileStream);
|
||||
var hex = new StringBuilder(sha.Length * 2);
|
||||
foreach (var b in sha)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Util</AssemblyName>
|
||||
<RootNamespace>Semmle.Util</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
name: codeql/csharp-examples
|
||||
version: 0.0.2
|
||||
groups:
|
||||
- csharp
|
||||
- examples
|
||||
dependencies:
|
||||
codeql/csharp-all: "*"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Return value attributes are extracted.
|
||||
* The QL `Attribute` class now has subclasses for each kind of attribute.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added support for C# 10 [Extended property patterns](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#extended-property-patterns).
|
||||
@@ -36,6 +36,12 @@ class Attributable extends @attributable {
|
||||
}
|
||||
}
|
||||
|
||||
private string getAttributeName(Attribute a) {
|
||||
exists(string type | type = a.getType().getName() |
|
||||
if type.matches("%Attribute") then result = type.prefix(type.length() - 9) else result = type
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute, for example `[...]` on line 1 in
|
||||
*
|
||||
@@ -50,10 +56,10 @@ class Attributable extends @attributable {
|
||||
*/
|
||||
class Attribute extends TopLevelExprParent, @attribute {
|
||||
/** Gets the type of this attribute. */
|
||||
Class getType() { attributes(this, getTypeRef(result), _) }
|
||||
Class getType() { attributes(this, _, getTypeRef(result), _) }
|
||||
|
||||
/** Gets the element that this attribute is attached to. */
|
||||
Attributable getTarget() { attributes(this, _, result) }
|
||||
Attributable getTarget() { attributes(this, _, _, result) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th argument of this attribute. This includes both constructor
|
||||
@@ -88,12 +94,55 @@ class Attribute extends TopLevelExprParent, @attribute {
|
||||
|
||||
override Location getALocation() { attribute_location(this, result) }
|
||||
|
||||
override string toString() {
|
||||
exists(string type, string name | type = this.getType().getName() |
|
||||
(if type.matches("%Attribute") then name = type.prefix(type.length() - 9) else name = type) and
|
||||
result = "[" + name + "(...)]"
|
||||
)
|
||||
}
|
||||
override string toString() { result = "[" + getAttributeName(this) + "(...)]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Attribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute with default kind, for example `[...]` on line 1 in
|
||||
* ```csharp
|
||||
* [MyAttribute(0)]
|
||||
* int SomeMethod() { return 1; }
|
||||
* ```
|
||||
*/
|
||||
class DefaultAttribute extends Attribute, @attribute_default {
|
||||
override string getAPrimaryQlClass() { result = "DefaultAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute with return kind, for example `[...]` on line 1 in
|
||||
* ```csharp
|
||||
* [return: MyAttribute(0)]
|
||||
* int SomeMethod() { return 1; }
|
||||
* ```
|
||||
*/
|
||||
class ReturnAttribute extends Attribute, @attribute_return {
|
||||
override string toString() { result = "[return: " + getAttributeName(this) + "(...)]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ReturnAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute with assembly kind, for example `[...]` on line 1 in
|
||||
* ```csharp
|
||||
* [assembly: MyAttribute(0)]
|
||||
* ```
|
||||
*/
|
||||
class AssemblyAttribute extends Attribute, @attribute_assembly {
|
||||
override string toString() { result = "[assembly: " + getAttributeName(this) + "(...)]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssemblyAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute with module kind, for example `[...]` on line 1 in
|
||||
* ```csharp
|
||||
* [module: MyAttribute(0)]
|
||||
* ```
|
||||
*/
|
||||
class ModuleAttribute extends Attribute, @attribute_module {
|
||||
override string toString() { result = "[module: " + getAttributeName(this) + "(...)]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ModuleAttribute" }
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ abstract class SplitKind extends SplitKindBase {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** Provides the interface for implementing an entity to split on. */
|
||||
/** An interface for implementing an entity to split on. */
|
||||
abstract class SplitImpl extends Split {
|
||||
/** Gets the kind of this split. */
|
||||
abstract SplitKind getKind();
|
||||
@@ -894,16 +894,31 @@ module TestOutput {
|
||||
p
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn()
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), p.toString()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
|
||||
query predicate edges(RelevantNode pred, RelevantNode succ, string attr, string val) {
|
||||
attr = "semmle.label" and
|
||||
exists(SuccessorType t | succ = getASuccessor(pred, t) |
|
||||
attr = "semmle.label" and
|
||||
if successorTypeIsSimple(t) then val = "" else val = t.toString()
|
||||
)
|
||||
or
|
||||
attr = "semmle.order" and
|
||||
val =
|
||||
any(int i |
|
||||
succ =
|
||||
rank[i](RelevantNode s, SuccessorType t, Location l |
|
||||
s = getASuccessor(pred, t) and
|
||||
l = s.getLocation()
|
||||
|
|
||||
s
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), t.toString()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** Content tagged with the type of a containing object. */
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
@@ -160,6 +160,7 @@ 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)) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -90,7 +90,9 @@ module Public {
|
||||
predicate contains(SummaryComponent c) { c = this.drop(_).head() }
|
||||
|
||||
/** Gets the bottom element of this stack. */
|
||||
SummaryComponent bottom() { result = this.drop(this.length() - 1).head() }
|
||||
SummaryComponent bottom() {
|
||||
this = TSingletonSummaryComponentStack(result) or result = this.tail().bottom()
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this stack. */
|
||||
string toString() {
|
||||
|
||||
@@ -5,12 +5,14 @@ private import TaintTrackingPrivate
|
||||
* Holds if taint propagates 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))
|
||||
}
|
||||
|
||||
@@ -520,9 +520,17 @@ tuple_element(
|
||||
|
||||
attributes(
|
||||
unique int id: @attribute,
|
||||
int kind: int ref,
|
||||
int type_id: @type_or_ref ref,
|
||||
int target: @attributable ref);
|
||||
|
||||
case @attribute.kind of
|
||||
0 = @attribute_default
|
||||
| 1 = @attribute_return
|
||||
| 2 = @attribute_assembly
|
||||
| 3 = @attribute_module
|
||||
;
|
||||
|
||||
attribute_location(
|
||||
int id: @attribute ref,
|
||||
int loc: @location ref);
|
||||
@@ -648,7 +656,7 @@ has_modifiers(
|
||||
int id: @modifiable_direct ref,
|
||||
int mod_id: @modifier ref);
|
||||
|
||||
compiler_generated(unique int id: @modifiable_direct ref);
|
||||
compiler_generated(unique int id: @modifiable ref);
|
||||
|
||||
/** MEMBERS **/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,122 +6,22 @@
|
||||
*/
|
||||
class Person extends string {
|
||||
Person() {
|
||||
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"
|
||||
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"
|
||||
]
|
||||
}
|
||||
|
||||
/** Gets the hair color of the person. If the person is bald, there is no result. */
|
||||
@@ -936,25 +836,12 @@ class Person extends string {
|
||||
|
||||
/** Holds if the person is deceased. */
|
||||
predicate isDeceased() {
|
||||
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"
|
||||
this =
|
||||
[
|
||||
"Ernest", "Gertrude", "Oscar", "Lilian", "Edwin", "Raymond", "Elgar", "Elmer", "Herbert",
|
||||
"Maude", "Mae", "Otto", "Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel",
|
||||
"King Basil"
|
||||
]
|
||||
}
|
||||
|
||||
/** Gets a parent of the person (alive or deceased). */
|
||||
@@ -1195,12 +1082,7 @@ 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" or
|
||||
region = "south" or
|
||||
region = "east" or
|
||||
region = "west"
|
||||
}
|
||||
predicate isAllowedIn(string region) { region = ["north", "south", "east", "west"] }
|
||||
}
|
||||
|
||||
/** Returns a parent of the person. */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Support for compiler-generated event accessors.
|
||||
compatibility: backwards
|
||||
@@ -0,0 +1,15 @@
|
||||
class Attribute extends @attribute {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Attributable extends @attributable {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class TypeOrRef extends @type_or_ref {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Attribute id, TypeOrRef type_id, Attributable target
|
||||
where attributes(id, type_id, target)
|
||||
select id, 0, type_id, target
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Add 'kind' to 'attributes'.
|
||||
compatability: backwards
|
||||
attributes.rel: run attribute_kind.ql
|
||||
24
csharp/ql/src/Metrics/internal/ExtractorDiagnostics.ql
Normal file
24
csharp/ql/src/Metrics/internal/ExtractorDiagnostics.ql
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @name Extractor diagnostics
|
||||
* @description This query is for internal use only and may change without notice.
|
||||
* @kind table
|
||||
* @id csharp/extractor-diagnostics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
bindingset[i]
|
||||
private float getCompilationTimeSum(int i) {
|
||||
result = sum(float f | compilation_time(_, _, i, f) | f)
|
||||
}
|
||||
|
||||
select getCompilationTimeSum(0) as sum_frontend_cpu_seconds,
|
||||
getCompilationTimeSum(1) as sum_frontend_elapsed_seconds,
|
||||
getCompilationTimeSum(4) as sum_frontend_user_seconds,
|
||||
getCompilationTimeSum(2) as sum_extractor_cpu_seconds,
|
||||
getCompilationTimeSum(3) as sum_extractor_elapsed_seconds,
|
||||
getCompilationTimeSum(5) as sum_extractor_user_seconds,
|
||||
sum(float f | compilation_finished(_, f, _) | f) as sum_total_cpu_seconds,
|
||||
sum(float f | compilation_finished(_, _, f) | f) as sum_total_elapsed_seconds,
|
||||
getCompilationTimeSum(6) as sum_peak_working_set_mb,
|
||||
max(float f | compilation_time(_, _, 6, f) | f) as max_peak_working_set_mb
|
||||
@@ -8,7 +8,7 @@ import shutil
|
||||
def write_csproj_prefix(ioWrapper):
|
||||
ioWrapper.write('<Project Sdk="Microsoft.NET.Sdk">\n')
|
||||
ioWrapper.write(' <PropertyGroup>\n')
|
||||
ioWrapper.write(' <TargetFramework>net5.0</TargetFramework>\n')
|
||||
ioWrapper.write(' <TargetFramework>net6.0</TargetFramework>\n')
|
||||
ioWrapper.write(' <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n')
|
||||
ioWrapper.write(' <OutputPath>bin\</OutputPath>\n')
|
||||
ioWrapper.write(
|
||||
@@ -60,7 +60,7 @@ jsonFile = os.path.join(rawOutputDir, outputName + '.json')
|
||||
version = helpers.get_argv(2, "latest")
|
||||
|
||||
print("\n* Creating new input project")
|
||||
run_cmd(['dotnet', 'new', 'classlib', "-f", "net5.0", "--language", "C#", '--name',
|
||||
run_cmd(['dotnet', 'new', 'classlib', "-f", "net6.0", "--language", "C#", '--name',
|
||||
projectNameIn, '--output', projectDirIn])
|
||||
helpers.remove_files(projectDirIn, '.cs')
|
||||
|
||||
@@ -71,7 +71,7 @@ if (version != "latest"):
|
||||
cmd.append(version)
|
||||
run_cmd(cmd)
|
||||
|
||||
sdk_version = '5.0.402'
|
||||
sdk_version = '6.0.101'
|
||||
print("\n* Creating new global.json file and setting SDK to " + sdk_version)
|
||||
run_cmd(['dotnet', 'new', 'globaljson', '--force', '--sdk-version', sdk_version, '--output', workDir])
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.0.8-dev
|
||||
groups: csharp
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
suites: codeql-suites
|
||||
extractor: csharp
|
||||
defaultSuiteFile: codeql-suites/csharp-code-scanning.qls
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user