mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge branch 'main' into deduplicate-dataflow-results-take-3
This commit is contained in:
2
.github/workflows/check-implicit-this.yml
vendored
2
.github/workflows/check-implicit-this.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check that implicit this warnings is enabled for all packs
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
2
.github/workflows/check-qldoc.yml
vendored
2
.github/workflows/check-qldoc.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
||||
2
.github/workflows/check-query-ids.yml
vendored
2
.github/workflows/check-query-ids.yml
vendored
@@ -16,6 +16,6 @@ jobs:
|
||||
name: Check query IDs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check for duplicate query IDs
|
||||
run: python3 misc/scripts/check-query-ids.py
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
dotnet-version: 7.0.102
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
2
.github/workflows/compile-queries.yml
vendored
2
.github/workflows/compile-queries.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest-xl
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
with:
|
||||
|
||||
6
.github/workflows/csharp-qltest.yml
vendored
6
.github/workflows/csharp-qltest.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check DB upgrade scripts
|
||||
run: |
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
matrix:
|
||||
slice: ["1/2", "2/2"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./csharp/actions/create-extractor-pack
|
||||
- name: Cache compilation cache
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
unit-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
|
||||
4
.github/workflows/csv-coverage-metrics.yml
vendored
4
.github/workflows/csv-coverage-metrics.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Create empty database
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Create empty database
|
||||
|
||||
@@ -31,11 +31,11 @@ jobs:
|
||||
GITHUB_CONTEXT: ${{ toJSON(github.event) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Clone self (github/codeql) - MERGE
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: merge
|
||||
- name: Clone self (github/codeql) - BASE
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
path: base
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
GITHUB_CONTEXT: ${{ toJSON(github.event) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
|
||||
@@ -9,11 +9,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: script
|
||||
- name: Clone self (github/codeql) for analysis
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: codeqlModels
|
||||
fetch-depth: 0
|
||||
|
||||
2
.github/workflows/csv-coverage-update.yml
vendored
2
.github/workflows/csv-coverage-update.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
GITHUB_CONTEXT: ${{ toJSON(github.event) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ql
|
||||
fetch-depth: 0
|
||||
|
||||
4
.github/workflows/csv-coverage.yml
vendored
4
.github/workflows/csv-coverage.yml
vendored
@@ -13,11 +13,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: script
|
||||
- name: Clone self (github/codeql) for analysis
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: codeqlModels
|
||||
ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }}
|
||||
|
||||
2
.github/workflows/fast-forward.yml
vendored
2
.github/workflows/fast-forward.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
exit 1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git config
|
||||
shell: bash
|
||||
|
||||
4
.github/workflows/go-tests-other-os.yml
vendored
4
.github/workflows/go-tests-other-os.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up CodeQL CLI
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up CodeQL CLI
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
2
.github/workflows/go-tests.yml
vendored
2
.github/workflows/go-tests.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up CodeQL CLI
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
2
.github/workflows/js-ml-tests.yml
vendored
2
.github/workflows/js-ml-tests.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
name: Test QL
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
|
||||
|
||||
4
.github/workflows/mad_modelDiff.yml
vendored
4
.github/workflows/mad_modelDiff.yml
vendored
@@ -27,12 +27,12 @@ jobs:
|
||||
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@v3
|
||||
uses: actions/checkout@v4
|
||||
if: github.event.pull_request
|
||||
with:
|
||||
path: codeql-pr
|
||||
- name: Clone github/codeql from main
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: codeql-main
|
||||
ref: main
|
||||
|
||||
4
.github/workflows/mad_regenerate-models.yml
vendored
4
.github/workflows/mad_regenerate-models.yml
vendored
@@ -27,11 +27,11 @@ jobs:
|
||||
ref: "placeholder"
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup CodeQL binaries
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Clone repositories
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: repos/${{ matrix.ref }}
|
||||
ref: ${{ matrix.ref }}
|
||||
|
||||
2
.github/workflows/qhelp-pr-preview.yml
vendored
2
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
persist-credentials: false
|
||||
|
||||
2
.github/workflows/ql-for-ql-build.yml
vendored
2
.github/workflows/ql-for-ql-build.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
### Build the queries ###
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Find codeql
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- github/codeql
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Checkout ${{ matrix.repo }}
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
path: ${{ github.workspace }}/repo
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: measure
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: measurements
|
||||
|
||||
4
.github/workflows/ql-for-ql-tests.yml
vendored
4
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@v2
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
needs: [qltest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install GNU tar
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
|
||||
2
.github/workflows/query-list.yml
vendored
2
.github/workflows/query-list.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: codeql
|
||||
- name: Set up Python 3.8
|
||||
|
||||
8
.github/workflows/ruby-build.yml
vendored
8
.github/workflows/ruby-build.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install GNU tar
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
@@ -113,7 +113,7 @@ jobs:
|
||||
compile-queries:
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Cache compilation cache
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, compile-queries]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ruby.dbscheme
|
||||
@@ -206,7 +206,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
|
||||
6
.github/workflows/ruby-dataset-measure.yml
vendored
6
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -27,14 +27,14 @@ jobs:
|
||||
repo: [rails/rails, discourse/discourse, spree/spree, ruby/ruby]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
|
||||
- name: Checkout ${{ matrix.repo }}
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
path: ${{ github.workspace }}/repo
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: measure
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: measurements
|
||||
|
||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check DB upgrade scripts
|
||||
run: |
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Cache compilation cache
|
||||
|
||||
16
.github/workflows/swift.yml
vendored
16
.github/workflows/swift.yml
vendored
@@ -39,31 +39,31 @@ jobs:
|
||||
build-and-test-macos:
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
build-and-test-linux:
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
qltests-linux:
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
qltests-macos:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
integration-tests-linux:
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
integration-tests-macos:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
@@ -71,13 +71,13 @@ jobs:
|
||||
runs-on: macos-12-xl
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
codegen:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
@@ -102,6 +102,6 @@ jobs:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./swift/actions/database-upgrade-scripts
|
||||
|
||||
2
.github/workflows/sync-files.yml
vendored
2
.github/workflows/sync-files.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check synchronized files
|
||||
run: python config/sync-files.py
|
||||
- name: Check dbscheme fragments
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Run tests
|
||||
@@ -35,12 +35,12 @@ jobs:
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check formatting
|
||||
run: cargo fmt --check
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run clippy
|
||||
run: cargo clippy -- --no-deps -D warnings -A clippy::new_without_default -A clippy::too_many_arguments
|
||||
|
||||
2
.github/workflows/validate-change-notes.yml
vendored
2
.github/workflows/validate-change-notes.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
@@ -447,9 +447,16 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
IRFunction getIRFunction() { result = f }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
exists(ExitFunctionInstruction exit |
|
||||
exit = f.getExitFunctionInstruction() and
|
||||
block.getInstruction(index) = exit
|
||||
// Similar to the `FinalParameterUse` case, we want to generate flow out of
|
||||
// globals at any exit so that we can flow out of non-returning functions.
|
||||
// Obviously this isn't correct as we can't actually flow but the global flow
|
||||
// requires this if we want to flow into children.
|
||||
exists(Instruction return |
|
||||
return instanceof ReturnInstruction or
|
||||
return instanceof UnreachedInstruction
|
||||
|
|
||||
block.getInstruction(index) = return and
|
||||
return.getEnclosingIRFunction() = f
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
edges
|
||||
| test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection |
|
||||
| test.c:14:27:14:30 | argv indirection | test.c:35:16:35:23 | userName indirection |
|
||||
| test.c:35:16:35:23 | userName indirection | test.c:40:25:40:32 | username indirection |
|
||||
| test.c:38:7:38:20 | globalUsername indirection | test.c:51:18:51:23 | query1 indirection |
|
||||
| test.c:40:25:40:32 | username indirection | test.c:38:7:38:20 | globalUsername indirection |
|
||||
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection |
|
||||
nodes
|
||||
| test.c:14:27:14:30 | argv indirection | semmle.label | argv indirection |
|
||||
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.c:35:16:35:23 | userName indirection | semmle.label | userName indirection |
|
||||
| test.c:38:7:38:20 | globalUsername indirection | semmle.label | globalUsername indirection |
|
||||
| test.c:40:25:40:32 | username indirection | semmle.label | username indirection |
|
||||
| test.c:51:18:51:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
|
||||
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
|
||||
| test.c:51:18:51:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:51:18:51:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
|
||||
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
|
||||
|
||||
@@ -8,7 +8,7 @@ int snprintf(char *s, size_t n, const char *format, ...);
|
||||
void sanitizeString(char *stringOut, size_t len, const char *strIn);
|
||||
int mysql_query(int arg1, const char *sqlArg);
|
||||
int atoi(const char *nptr);
|
||||
|
||||
void exit(int i);
|
||||
///// Test code /////
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@@ -31,4 +31,22 @@ int main(int argc, char** argv) {
|
||||
char query3[1000] = {0};
|
||||
snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber);
|
||||
mysql_query(0, query3); // GOOD
|
||||
|
||||
nonReturning(userName);
|
||||
}
|
||||
|
||||
char* globalUsername;
|
||||
|
||||
void nonReturning(char* username) {
|
||||
globalUsername = username;
|
||||
badFunc();
|
||||
// This function does not return, so we used to lose the global flow here.
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void badFunc() {
|
||||
char *userName = globalUsername;
|
||||
char query1[1000] = {0};
|
||||
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName);
|
||||
mysql_query(0, query1); // BAD
|
||||
}
|
||||
|
||||
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: Update the schemas for some tables to disallow assembly locations.
|
||||
compatibility: full
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
@@ -82,8 +84,15 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
var baseTypes = GetBaseTypeDeclarations();
|
||||
|
||||
var hasExpandingCycle = GenericsRecursionGraph.HasExpandingCycle(Symbol);
|
||||
if (hasExpandingCycle)
|
||||
{
|
||||
Context.ExtractionError("Found recursive generic inheritance hierarchy. Base class of type is not extracted", Symbol.ToDisplayString(), Context.CreateLocation(ReportingLocation), severity: Util.Logging.Severity.Warning);
|
||||
}
|
||||
|
||||
// Visit base types
|
||||
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
||||
if (!hasExpandingCycle
|
||||
&& Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
||||
{
|
||||
var bts = GetBaseTypeDeclarations(baseTypes, @base);
|
||||
|
||||
@@ -347,6 +356,197 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public override int GetHashCode() => SymbolEqualityComparer.Default.GetHashCode(Symbol);
|
||||
|
||||
/// <summary>
|
||||
/// Class to detect recursive generic inheritance hierarchies.
|
||||
///
|
||||
/// Details can be found in https://www.ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf Chapter II.9.2 Generics and recursive inheritance graphs
|
||||
/// The dotnet runtime already implements this check as a runtime validation: https://github.com/dotnet/runtime/blob/e48e88d0fe9c2e494c0e6fd0c7c1fb54e7ddbdb1/src/coreclr/vm/generics.cpp#L748
|
||||
/// </summary>
|
||||
private class GenericsRecursionGraph
|
||||
{
|
||||
private static readonly ConcurrentDictionary<INamedTypeSymbol, bool> resultCache = new(SymbolEqualityComparer.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given type has a recursive generic inheritance hierarchy. The result is cached.
|
||||
/// </summary>
|
||||
public static bool HasExpandingCycle(ITypeSymbol start)
|
||||
{
|
||||
if (start.OriginalDefinition is not INamedTypeSymbol namedTypeDefinition ||
|
||||
!namedTypeDefinition.IsGenericType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return resultCache.GetOrAdd(namedTypeDefinition, nt => new GenericsRecursionGraph(nt).HasExpandingCycle());
|
||||
}
|
||||
|
||||
private readonly INamedTypeSymbol startSymbol;
|
||||
private readonly HashSet<INamedTypeSymbol> instantiationClosure = new(SymbolEqualityComparer.Default);
|
||||
private readonly Dictionary<ITypeParameterSymbol, List<(ITypeParameterSymbol To, bool IsExpanding)>> edges = new(SymbolEqualityComparer.Default);
|
||||
|
||||
private GenericsRecursionGraph(INamedTypeSymbol startSymbol)
|
||||
{
|
||||
this.startSymbol = startSymbol;
|
||||
|
||||
ComputeInstantiationClosure();
|
||||
ComputeGraphEdges();
|
||||
}
|
||||
|
||||
private void ComputeGraphEdges()
|
||||
{
|
||||
foreach (var reference in instantiationClosure)
|
||||
{
|
||||
var definition = reference.OriginalDefinition;
|
||||
if (SymbolEqualityComparer.Default.Equals(reference, definition))
|
||||
{
|
||||
// It's a definition, so no edges
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < reference.TypeArguments.Length; i++)
|
||||
{
|
||||
var target = definition.TypeParameters[i];
|
||||
if (reference.TypeArguments[i] is ITypeParameterSymbol source)
|
||||
{
|
||||
// non-expanding
|
||||
edges.AddAnother(source, (target, false));
|
||||
}
|
||||
else if (reference.TypeArguments[i] is INamedTypeSymbol namedType)
|
||||
{
|
||||
// expanding
|
||||
var sources = GetAllNestedTypeParameters(namedType);
|
||||
foreach (var s in sources)
|
||||
{
|
||||
edges.AddAnother(s, (target, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ITypeParameterSymbol> GetAllNestedTypeParameters(INamedTypeSymbol symbol)
|
||||
{
|
||||
var res = new List<ITypeParameterSymbol>();
|
||||
|
||||
void AddTypeParameters(INamedTypeSymbol symbol)
|
||||
{
|
||||
foreach (var typeArgument in symbol.TypeArguments)
|
||||
{
|
||||
if (typeArgument is ITypeParameterSymbol typeParameter)
|
||||
{
|
||||
res.Add(typeParameter);
|
||||
}
|
||||
else if (typeArgument is INamedTypeSymbol namedType)
|
||||
{
|
||||
AddTypeParameters(namedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddTypeParameters(symbol);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private void ComputeInstantiationClosure()
|
||||
{
|
||||
var workQueue = new Queue<INamedTypeSymbol>();
|
||||
workQueue.Enqueue(startSymbol);
|
||||
|
||||
while (workQueue.Count > 0)
|
||||
{
|
||||
var current = workQueue.Dequeue();
|
||||
if (instantiationClosure.Contains(current) ||
|
||||
!current.IsGenericType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
instantiationClosure.Add(current);
|
||||
|
||||
if (SymbolEqualityComparer.Default.Equals(current, current.OriginalDefinition))
|
||||
{
|
||||
// Definition, so enqueue all base types and interfaces
|
||||
if (current.BaseType != null)
|
||||
{
|
||||
workQueue.Enqueue(current.BaseType);
|
||||
}
|
||||
|
||||
foreach (var i in current.Interfaces)
|
||||
{
|
||||
workQueue.Enqueue(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reference, so enqueue all type arguments and their original definitions:
|
||||
foreach (var namedTypeArgument in current.TypeArguments.OfType<INamedTypeSymbol>())
|
||||
{
|
||||
workQueue.Enqueue(namedTypeArgument);
|
||||
workQueue.Enqueue(namedTypeArgument.OriginalDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasExpandingCycle()
|
||||
{
|
||||
return startSymbol.TypeParameters.Any(HasExpandingCycle);
|
||||
}
|
||||
|
||||
private bool HasExpandingCycle(ITypeParameterSymbol start)
|
||||
{
|
||||
var visited = new HashSet<ITypeParameterSymbol>(SymbolEqualityComparer.Default);
|
||||
var path = new List<ITypeParameterSymbol>();
|
||||
var hasExpandingCycle = HasExpandingCycle(start, visited, path, hasSeenExpandingEdge: false);
|
||||
return hasExpandingCycle;
|
||||
}
|
||||
|
||||
private List<(ITypeParameterSymbol To, bool IsExpanding)> GetOutgoingEdges(ITypeParameterSymbol typeParameter)
|
||||
{
|
||||
return edges.TryGetValue(typeParameter, out var outgoingEdges)
|
||||
? outgoingEdges
|
||||
: new List<(ITypeParameterSymbol, bool)>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A modified cycle detection algorithm based on DFS.
|
||||
/// </summary>
|
||||
/// <param name="current">The current node that is being visited</param>
|
||||
/// <param name="visited">The nodes that have already been visited by any path.</param>
|
||||
/// <param name="currentPath">The nodes already visited on the current path.</param>
|
||||
/// <param name="hasSeenExpandingEdge">Whether an expanding edge was already seen in this path. We're looking for a cycle that has at least one expanding edge.</param>
|
||||
/// <returns></returns>
|
||||
private bool HasExpandingCycle(ITypeParameterSymbol current, HashSet<ITypeParameterSymbol> visited, List<ITypeParameterSymbol> currentPath, bool hasSeenExpandingEdge)
|
||||
{
|
||||
if (currentPath.Count > 0 && SymbolEqualityComparer.Default.Equals(current, currentPath[0]))
|
||||
{
|
||||
return hasSeenExpandingEdge;
|
||||
}
|
||||
|
||||
if (visited.Contains(current))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
visited.Add(current);
|
||||
currentPath.Add(current);
|
||||
|
||||
var outgoingEdges = GetOutgoingEdges(current);
|
||||
|
||||
foreach (var outgoingEdge in outgoingEdges)
|
||||
{
|
||||
if (HasExpandingCycle(outgoingEdge.To, visited, currentPath, hasSeenExpandingEdge: hasSeenExpandingEdge || outgoingEdge.IsExpanding))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
currentPath.RemoveAt(currentPath.Count - 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class Type<T> : Type where T : ITypeSymbol
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB<GenB<T>> |
|
||||
| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB<GenB<string>> |
|
||||
| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB<T> |
|
||||
| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB<string> |
|
||||
@@ -0,0 +1,6 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Diagnostics
|
||||
|
||||
query predicate extractorMessages(ExtractorMessage msg, int severity, string elementText) {
|
||||
msg.getSeverity() = severity and msg.getElementText() = elementText
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
| test.cs:1:14:1:20 | GenA<> | System.Object |
|
||||
| test.cs:1:14:1:20 | GenA<GenB<GenB<>>> | System.Object |
|
||||
| test.cs:1:14:1:20 | GenA<GenB<GenB<String>>> | System.Object |
|
||||
| test.cs:2:14:2:20 | GenB<> | System.Object |
|
||||
| test.cs:2:14:2:20 | GenB<GenB<>> | System.Object |
|
||||
| test.cs:2:14:2:20 | GenB<GenB<String>> | System.Object |
|
||||
| test.cs:2:14:2:20 | GenB<String> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<,>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<Int32,String>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<String,Int32>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<V,U>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<W,X>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<C<X,W>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<,>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<Int32,String>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<String,Int32>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<U,V>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<V,U>> | System.Object |
|
||||
| test.cs:4:7:4:10 | P<D<X,W>> | System.Object |
|
||||
| test.cs:5:7:5:13 | C<,> | P<D<V,U>> |
|
||||
| test.cs:5:7:5:13 | C<Int32,String> | P<D<System.String,System.Int32>> |
|
||||
| test.cs:5:7:5:13 | C<String,Int32> | P<D<System.Int32,System.String>> |
|
||||
| test.cs:5:7:5:13 | C<V,U> | P<D<U,V>> |
|
||||
| test.cs:5:7:5:13 | C<W,X> | P<D<X,W>> |
|
||||
| test.cs:5:7:5:13 | C<X,W> | P<D<,>> |
|
||||
| test.cs:6:7:6:13 | D<,> | P<C<W,X>> |
|
||||
| test.cs:6:7:6:13 | D<Int32,String> | P<C<System.Int32,System.String>> |
|
||||
| test.cs:6:7:6:13 | D<String,Int32> | P<C<System.String,System.Int32>> |
|
||||
| test.cs:6:7:6:13 | D<U,V> | P<C<,>> |
|
||||
| test.cs:6:7:6:13 | D<V,U> | P<C<V,U>> |
|
||||
| test.cs:6:7:6:13 | D<X,W> | P<C<X,W>> |
|
||||
| test.cs:8:7:8:10 | A<> | System.Object |
|
||||
| test.cs:8:7:8:10 | A<String> | System.Object |
|
||||
| test.cs:13:14:13:18 | Class | System.Object |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Class c
|
||||
where c.fromSource()
|
||||
select c, c.getBaseClass().getQualifiedName()
|
||||
@@ -0,0 +1,23 @@
|
||||
public class GenA<U> { };
|
||||
public class GenB<T> : GenA<GenB<GenB<T>>> { };
|
||||
|
||||
class P<T> { }
|
||||
class C<U, V> : P<D<V, U>> { }
|
||||
class D<W, X> : P<C<W, X>> { }
|
||||
|
||||
class A<T> : System.IEquatable<A<T>>
|
||||
{
|
||||
public bool Equals(A<T> other) { return true; }
|
||||
}
|
||||
|
||||
public class Class
|
||||
{
|
||||
public static int Main()
|
||||
{
|
||||
GenB<string> a = new GenB<string>();
|
||||
P<D<string, int>> b = new C<int, string>();
|
||||
A<string> c = new A<string>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="DeleteBinObjFolders" BeforeTargets="Clean">
|
||||
<RemoveDir Directories=".\bin" />
|
||||
<RemoveDir Directories=".\obj" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(['dotnet build'], lang="csharp", extra_args=["--extractor-option=cil=false"])
|
||||
@@ -1165,8 +1165,14 @@ private module ArgumentNodes {
|
||||
) {
|
||||
e1.(Argument).isArgumentOf(e2, _) and
|
||||
exactScope = false and
|
||||
scope = e2 and
|
||||
isSuccessor = true
|
||||
isSuccessor = true and
|
||||
if e2 instanceof PropertyWrite
|
||||
then
|
||||
exists(AssignableDefinition def |
|
||||
def.getTargetAccess() = e2 and
|
||||
scope = def.getExpr()
|
||||
)
|
||||
else scope = e2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ diagnostics(
|
||||
string error_tag: string ref,
|
||||
string error_message: string ref,
|
||||
string full_error_message: string ref,
|
||||
int location: @location_default ref
|
||||
int location: @location ref
|
||||
);
|
||||
|
||||
extractor_messages(
|
||||
@@ -145,7 +145,7 @@ extractor_messages(
|
||||
string origin : string ref,
|
||||
string text : string ref,
|
||||
string entity : string ref,
|
||||
int location: @location_default ref,
|
||||
int location: @location ref,
|
||||
string stack_trace : string ref
|
||||
);
|
||||
|
||||
|
||||
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: Update the schemas for some tables to allow assembly locations.
|
||||
compatibility: full
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added [http.Error](https://pkg.go.dev/net/http#Error) to XSS sanitzers.
|
||||
@@ -109,6 +109,18 @@ module SharedXss {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A http.Error function returns with the ContentType of text/plain, and is not a valid XSS sink
|
||||
*/
|
||||
class ErrorSanitizer extends Sanitizer {
|
||||
ErrorSanitizer() {
|
||||
exists(Function f, DataFlow::CallNode call | call = f.getACall() |
|
||||
f.hasQualifiedName("net/http", "Error") and
|
||||
call.getArgument(1) = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, or a call to an escape
|
||||
* function, viewed as a sanitizer for XSS vulnerabilities.
|
||||
|
||||
@@ -25,9 +25,9 @@ func ServeJsonDirect(w http.ResponseWriter, r http.Request) {
|
||||
|
||||
func ErrTest(w http.ResponseWriter, r http.Request) {
|
||||
cookie, err := r.Cookie("somecookie")
|
||||
w.Write([]byte(fmt.Sprintf("Cookie result: %v", cookie))) // BAD: Cookie's value is user-controlled
|
||||
w.Write([]byte(fmt.Sprintf("Cookie check error: %v", err))) // GOOD: Cookie's err return is harmless
|
||||
|
||||
w.Write([]byte(fmt.Sprintf("Cookie result: %v", cookie))) // BAD: Cookie's value is user-controlled
|
||||
w.Write([]byte(fmt.Sprintf("Cookie check error: %v", err))) // GOOD: Cookie's err return is harmless
|
||||
http.Error(w, fmt.Sprintf("Cookie result: %v", cookie), 500) // Good: only plain text is written.
|
||||
file, header, err := r.FormFile("someFile")
|
||||
content, err2 := ioutil.ReadAll(file)
|
||||
w.Write([]byte(fmt.Sprintf("File content: %v", content))) // BAD: file content is user-controlled
|
||||
|
||||
@@ -92,6 +92,7 @@ def compile_to_dir(build_dir, srcs, classpath, java_classpath, output):
|
||||
kotlin_arg_file = build_dir + '/kotlin.args'
|
||||
kotlin_args = ['-Werror',
|
||||
'-opt-in=kotlin.RequiresOptIn',
|
||||
'-opt-in=org.jetbrains.kotlin.ir.symbols.IrSymbolInternals',
|
||||
'-d', output,
|
||||
'-module-name', 'codeql-kotlin-extractor',
|
||||
'-no-reflect', '-no-stdlib',
|
||||
@@ -168,7 +169,7 @@ def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output,
|
||||
shutil.rmtree(tmp_src_dir)
|
||||
shutil.copytree('src', tmp_src_dir)
|
||||
|
||||
include_version_folder = tmp_src_dir + '/main/kotlin/utils/versions/to_include'
|
||||
include_version_folder = tmp_src_dir + '/main/kotlin/utils/this_version'
|
||||
os.makedirs(include_version_folder)
|
||||
|
||||
resource_dir = tmp_src_dir + '/main/resources/com/github/codeql'
|
||||
@@ -192,11 +193,7 @@ def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output,
|
||||
shutil.copytree(d, include_version_folder, dirs_exist_ok=True)
|
||||
|
||||
# remove all version folders:
|
||||
for version in kotlin_plugin_versions.many_versions:
|
||||
d = tmp_src_dir + '/main/kotlin/utils/versions/v_' + \
|
||||
version.replace('.', '_')
|
||||
if os.path.exists(d):
|
||||
shutil.rmtree(d)
|
||||
shutil.rmtree(tmp_src_dir + '/main/kotlin/utils/versions')
|
||||
|
||||
srcs = find_sources(tmp_src_dir)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import com.github.codeql.utils.versions.usesK2
|
||||
import com.semmle.util.files.FileUtil
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -97,6 +98,7 @@ class KotlinExtractorExtension(
|
||||
|
||||
private fun runExtractor(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
|
||||
val startTimeMs = System.currentTimeMillis()
|
||||
val usesK2 = usesK2(pluginContext)
|
||||
// This default should be kept in sync with com.semmle.extractor.java.interceptors.KotlinInterceptor.initializeExtractionContext
|
||||
val trapDir = File(System.getenv("CODEQL_EXTRACTOR_JAVA_TRAP_DIR").takeUnless { it.isNullOrEmpty() } ?: "kotlin-extractor/trap")
|
||||
val compression_env_var = "CODEQL_EXTRACTOR_JAVA_OPTION_TRAP_COMPRESSION"
|
||||
@@ -134,6 +136,7 @@ class KotlinExtractorExtension(
|
||||
tw.writeCompilation_info(compilation, "Kotlin Compiler Version", KotlinCompilerVersion.getVersion() ?: "<unknown>")
|
||||
val extractor_name = this::class.java.getResource("extractor.name")?.readText() ?: "<unknown>"
|
||||
tw.writeCompilation_info(compilation, "Kotlin Extractor Name", extractor_name)
|
||||
tw.writeCompilation_info(compilation, "Uses Kotlin 2", usesK2.toString())
|
||||
if (compilationStartTime != null) {
|
||||
tw.writeCompilation_compiler_times(compilation, -1.0, (System.currentTimeMillis()-compilationStartTime)/1000.0)
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ open class KotlinFileExtractor(
|
||||
fun extractFileContents(file: IrFile, id: Label<DbFile>) {
|
||||
with("file", file) {
|
||||
val locId = tw.getWholeFileLocation()
|
||||
val pkg = file.fqName.asString()
|
||||
val pkg = file.packageFqName.asString()
|
||||
val pkgId = extractPackage(pkg)
|
||||
tw.writeHasLocation(id, locId)
|
||||
tw.writeCupackage(id, pkgId)
|
||||
@@ -1901,8 +1901,9 @@ open class KotlinFileExtractor(
|
||||
verboseln("No match as didn't find target package")
|
||||
return false
|
||||
}
|
||||
if (targetPkg.fqName.asString() != pName) {
|
||||
verboseln("No match as package name is ${targetPkg.fqName.asString()}")
|
||||
val targetName = targetPkg.packageFqName.asString()
|
||||
if (targetName != pName) {
|
||||
verboseln("No match as package name is $targetName")
|
||||
return false
|
||||
}
|
||||
verboseln("Match")
|
||||
@@ -2556,8 +2557,9 @@ open class KotlinFileExtractor(
|
||||
verboseln("No match as didn't find target package")
|
||||
return false
|
||||
}
|
||||
if (targetPkg.fqName.asString() != pkgName) {
|
||||
verboseln("No match as package name is ${targetPkg.fqName.asString()} not $pkgName")
|
||||
val targetName = targetPkg.packageFqName.asString()
|
||||
if (targetName != pkgName) {
|
||||
verboseln("No match as package name is $targetName not $pkgName")
|
||||
return false
|
||||
}
|
||||
verboseln("Match")
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.github.codeql.utils.versions.codeQlWithHasQuestionMark
|
||||
import com.github.codeql.utils.versions.getFileClassFqName
|
||||
import com.github.codeql.utils.versions.getKotlinType
|
||||
import com.github.codeql.utils.versions.isRawType
|
||||
import com.github.codeql.utils.versions.packageFqName
|
||||
import com.semmle.extractor.java.OdasaOutput
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
@@ -83,7 +84,7 @@ open class KotlinUsesExtractor(
|
||||
)
|
||||
|
||||
fun extractFileClass(f: IrFile): Label<out DbClassorinterface> {
|
||||
val pkg = f.fqName.asString()
|
||||
val pkg = f.packageFqName.asString()
|
||||
val jvmName = getFileClassName(f)
|
||||
val id = extractFileClass(pkg, jvmName)
|
||||
if (tw.lm.fileClassLocationsExtracted.add(f)) {
|
||||
@@ -848,7 +849,7 @@ open class KotlinUsesExtractor(
|
||||
when(dp) {
|
||||
is IrFile ->
|
||||
if(canBeTopLevel) {
|
||||
usePackage(dp.fqName.asString())
|
||||
usePackage(dp.packageFqName.asString())
|
||||
} else {
|
||||
extractFileClass(dp)
|
||||
}
|
||||
|
||||
@@ -276,8 +276,8 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
||||
run { logger.warnElement("Expected property's parent class to have a receiver parameter", parentClass); return }
|
||||
val newParam = copyParameterToFunction(thisReceiever, this)
|
||||
dispatchReceiverParameter = newParam
|
||||
body = factory.createBlockBody(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||
body = factory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply({
|
||||
this.statements.add(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.nothingType,
|
||||
@@ -294,7 +294,7 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,12 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import com.github.codeql.utils.*
|
||||
import com.github.codeql.utils.versions.packageFqName
|
||||
|
||||
class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContext) {
|
||||
fun getPrimitiveInfo(s: IrSimpleType) =
|
||||
s.classOrNull?.let {
|
||||
if ((it.owner.parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
if ((it.owner.parent as? IrPackageFragment)?.packageFqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
mapping[it.owner.name]
|
||||
else
|
||||
null
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.github.codeql.comments
|
||||
import com.github.codeql.*
|
||||
import com.github.codeql.utils.IrVisitorLookup
|
||||
import com.github.codeql.utils.isLocalFunction
|
||||
import com.github.codeql.utils.Psi2IrFacade
|
||||
import com.github.codeql.utils.versions.getPsi2Ir
|
||||
import com.github.codeql.utils.versions.Psi2IrFacade
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.github.codeql
|
||||
|
||||
import com.github.codeql.utils.getJvmName
|
||||
import com.github.codeql.utils.versions.getFileClassFqName
|
||||
import com.github.codeql.utils.versions.packageFqName
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
|
||||
@@ -33,7 +34,7 @@ fun getFileClassName(f: IrFile) =
|
||||
fun getIrElementBinaryName(that: IrElement): String {
|
||||
if (that is IrFile) {
|
||||
val shortName = getFileClassName(that)
|
||||
val pkg = that.fqName.asString()
|
||||
val pkg = that.packageFqName.asString()
|
||||
return if (pkg.isEmpty()) shortName else "$pkg.$shortName"
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ fun getIrElementBinaryName(that: IrElement): String {
|
||||
.forEach {
|
||||
when (it) {
|
||||
is IrClass -> internalName.insert(0, getName(it) + "$")
|
||||
is IrPackageFragment -> it.fqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
|
||||
is IrPackageFragment -> it.packageFqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
|
||||
}
|
||||
}
|
||||
return internalName.toString()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.github.codeql.utils
|
||||
|
||||
import com.github.codeql.utils.versions.Psi2IrFacade
|
||||
import com.github.codeql.utils.Psi2IrFacade
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.github.codeql.utils.versions
|
||||
package com.github.codeql.utils
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -8,4 +8,4 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
interface Psi2IrFacade {
|
||||
fun getKtFile(irFile: IrFile): KtFile?
|
||||
fun findPsiElement(irElement: IrElement, irFile: IrFile): PsiElement?
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.jetbrains.kotlin.ir.symbols
|
||||
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||
annotation class IrSymbolInternals
|
||||
@@ -1,3 +1,5 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import com.github.codeql.utils.Psi2IrFacade
|
||||
|
||||
fun getPsi2Ir(): Psi2IrFacade? = null
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
|
||||
fun usesK2(@Suppress("UNUSED_PARAMETER") pluginContext: IrPluginContext): Boolean {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
val IrFile.packageFqName: FqName
|
||||
get() = this.fqName
|
||||
|
||||
val IrPackageFragment.packageFqName: FqName
|
||||
get() = this.fqName
|
||||
@@ -6,6 +6,7 @@ import org.jetbrains.kotlin.backend.jvm.ir.getKtFile
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import com.github.codeql.utils.Psi2IrFacade
|
||||
|
||||
fun getPsi2Ir(): Psi2IrFacade? = Psi2Ir()
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
|
||||
fun usesK2(pluginContext: IrPluginContext): Boolean {
|
||||
return pluginContext.languageVersionSettings.languageVersion.usesK2
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.github.codeql
|
||||
|
||||
// The compiler provides the annotation class, so we don't need to do
|
||||
// anything
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.github.codeql
|
||||
|
||||
// The compiler provides packageFqName, so we don't need to do anything
|
||||
@@ -0,0 +1,7 @@
|
||||
| Number of files with extension jar | 1 |
|
||||
| Number of files with extension kt | 1 |
|
||||
| Number of lines of code | 2 |
|
||||
| Number of lines of code with extension kt | 2 |
|
||||
| Total number of lines | 3 |
|
||||
| Total number of lines with extension kt | 3 |
|
||||
| Uses Kotlin 2: false | 1 |
|
||||
@@ -0,0 +1,13 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-queries
|
||||
extensible: extractorInformationSkipKey
|
||||
data:
|
||||
# These will have unstable values, as they are dependent on the
|
||||
# JDK that the test is run with, so filter them out:
|
||||
- ["Number of files"]
|
||||
- ["Number of files with extension class"]
|
||||
# These depend on the Kotlin version you have installed
|
||||
- ["Kotlin Compiler Version: %"]
|
||||
- ["Kotlin Extractor Name: %"]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Telemetry/ExtractorInformation.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
class SomeClass {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(["kotlinc SomeClass.kt"], lang="java")
|
||||
@@ -0,0 +1,3 @@
|
||||
| Number of files with extension jar | 1 |
|
||||
| Number of files with extension kt | 1 |
|
||||
| Uses Kotlin 2: true | 1 |
|
||||
@@ -0,0 +1,17 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-queries
|
||||
extensible: extractorInformationSkipKey
|
||||
data:
|
||||
# These will have unstable values, as they are dependent on the
|
||||
# JDK that the test is run with, so filter them out:
|
||||
- ["Number of files"]
|
||||
- ["Number of files with extension class"]
|
||||
# These depend on the Kotlin version you have installed
|
||||
- ["Kotlin Compiler Version: %"]
|
||||
- ["Kotlin Extractor Name: %"]
|
||||
# Currently we get some diagnostics as Kotlin 2 support isn't complete.
|
||||
# Ignore these, as the number probably isn't stable.
|
||||
- ["Number of diagnostics from CodeQL Kotlin extractor with severity %"]
|
||||
- ["Total number of diagnostics from CodeQL Kotlin extractor"]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Telemetry/ExtractorInformation.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
class SomeClass {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(["kotlinc -language-version 2.0 SomeClass.kt"], lang="java")
|
||||
@@ -87,7 +87,7 @@ predicate extractorTotalDiagnostics(string key, int value) {
|
||||
|
||||
from string key, int value
|
||||
where
|
||||
not extractorInformationSkipKey(key) and
|
||||
not exists(string pattern | extractorInformationSkipKey(pattern) and key.matches(pattern)) and
|
||||
(
|
||||
compilationInfo(key, value) or
|
||||
fileCount(key, value) or
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
ERROR: class or primitive expected in query (selectAtType.ql:5,8-15)
|
||||
@@ -1,5 +0,0 @@
|
||||
import java
|
||||
|
||||
@classorinterface clasz() { any() }
|
||||
|
||||
select clasz()
|
||||
@@ -114,7 +114,7 @@ def make_patches_from_log_file(log_file_lines) -> List[Patch]:
|
||||
while True:
|
||||
next_line = parse_log_line(next(lines))
|
||||
# it can be the case that
|
||||
if next_line[0] in (" ", "-", "+", "@"):
|
||||
if next_line and next_line[0] in (" ", "-", "+", "@"):
|
||||
lines_changed.append(next_line)
|
||||
if "FAILED" in next_line:
|
||||
break
|
||||
|
||||
@@ -16,9 +16,11 @@ private import semmle.python.dataflow.new.SensitiveDataSources
|
||||
import CleartextLoggingCustomizations::CleartextLogging
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `CleartextLoggingFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "Clear-text logging of sensitive information".
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CleartextLogging" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -31,3 +33,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
}
|
||||
|
||||
private module CleartextLoggingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "Clear-text logging of sensitive information" vulnerabilities. */
|
||||
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;
|
||||
|
||||
@@ -16,9 +16,11 @@ private import semmle.python.dataflow.new.SensitiveDataSources
|
||||
import CleartextStorageCustomizations::CleartextStorage
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `CleartextStorageFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "Clear-text storage of sensitive information".
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CleartextStorage" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -31,3 +33,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
}
|
||||
|
||||
private module CleartextStorageConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "Clear-text storage of sensitive information" vulnerabilities. */
|
||||
module CleartextStorageFlow = TaintTracking::Global<CleartextStorageConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import CodeInjectionCustomizations::CodeInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `CodeInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "code injection" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CodeInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module CodeInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "code injection" vulnerabilities. */
|
||||
module CodeInjectionFlow = TaintTracking::Global<CodeInjectionConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import CommandInjectionCustomizations::CommandInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `CommandInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "command injection" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CommandInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,17 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for detecting "command injection" vulnerabilities.
|
||||
*/
|
||||
module CommandInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "command injection" vulnerabilities. */
|
||||
module CommandInjectionFlow = TaintTracking::Global<CommandInjectionConfig>;
|
||||
|
||||
@@ -14,10 +14,12 @@ import semmle.python.dataflow.new.RemoteFlowSources
|
||||
import LdapInjectionCustomizations::LdapInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `LdapInjectionDnFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting LDAP injection vulnerabilities
|
||||
* via the distinguished name (DN) parameter of an LDAP search.
|
||||
*/
|
||||
class DnConfiguration extends TaintTracking::Configuration {
|
||||
deprecated class DnConfiguration extends TaintTracking::Configuration {
|
||||
DnConfiguration() { this = "LdapDnInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -31,11 +33,24 @@ class DnConfiguration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
private module LdapInjectionDnConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof DnSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof DnSanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "LDAP injection via the distinguished name (DN) parameter" vulnerabilities. */
|
||||
module LdapInjectionDnFlow = TaintTracking::Global<LdapInjectionDnConfig>;
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `LdapInjectionFilterFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting LDAP injection vulnerabilities
|
||||
* via the filter parameter of an LDAP search.
|
||||
*/
|
||||
class FilterConfiguration extends TaintTracking::Configuration {
|
||||
deprecated class FilterConfiguration extends TaintTracking::Configuration {
|
||||
FilterConfiguration() { this = "LdapFilterInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -48,3 +63,19 @@ class FilterConfiguration extends TaintTracking::Configuration {
|
||||
guard instanceof FilterSanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module LdapInjectionFilterConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof FilterSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof FilterSanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "LDAP injection via the filter parameter" vulnerabilities. */
|
||||
module LdapInjectionFilterFlow = TaintTracking::Global<LdapInjectionFilterConfig>;
|
||||
|
||||
/** Global taint-tracking for detecting "LDAP injection" vulnerabilities. */
|
||||
module LdapInjectionFlow =
|
||||
DataFlow::MergePathGraph<LdapInjectionDnFlow::PathNode, LdapInjectionFilterFlow::PathNode,
|
||||
LdapInjectionDnFlow::PathGraph, LdapInjectionFilterFlow::PathGraph>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for tracking untrusted user input used in log entries.
|
||||
* Provides a taint-tracking configuration for tracking "log injection" vulnerabilities.
|
||||
*
|
||||
* Note, for performance reasons: only import this file if
|
||||
* `LogInjection::Configuration` is needed, otherwise
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import LogInjectionCustomizations::LogInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `LogInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for tracking untrusted user input used in log entries.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "LogInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module LogInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "log injection" vulnerabilities. */
|
||||
module LogInjectionFlow = TaintTracking::Global<LogInjectionConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import PamAuthorizationCustomizations::PamAuthorizationCustomizations
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `PamAuthorizationFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "PAM Authorization" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "PamAuthorization" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { node instanceof Source }
|
||||
@@ -37,3 +39,28 @@ class Configuration extends TaintTracking::Configuration {
|
||||
exists(VulnPamAuthCall c | c.getArg(0) = node1 | node2 = c)
|
||||
}
|
||||
}
|
||||
|
||||
private module PamAuthorizationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// Models flow from a remotely supplied username field to a PAM `handle`.
|
||||
// `retval = pam_start(service, username, byref(conv), byref(handle))`
|
||||
exists(API::CallNode pamStart, DataFlow::Node handle, API::CallNode pointer |
|
||||
pointer = API::moduleImport("ctypes").getMember(["pointer", "byref"]).getACall() and
|
||||
pamStart = libPam().getMember("pam_start").getACall() and
|
||||
pointer = pamStart.getArg(3) and
|
||||
handle = pointer.getArg(0) and
|
||||
pamStart.getArg(1) = node1 and
|
||||
handle = node2
|
||||
)
|
||||
or
|
||||
// Flow from handle to the authenticate call in the final step
|
||||
exists(VulnPamAuthCall c | c.getArg(0) = node1 | node2 = c)
|
||||
}
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "PAM Authorization" vulnerabilities. */
|
||||
module PamAuthorizationFlow = TaintTracking::Global<PamAuthorizationConfig>;
|
||||
|
||||
@@ -13,6 +13,8 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import PathInjectionCustomizations::PathInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `PathInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "path injection" vulnerabilities.
|
||||
*
|
||||
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
|
||||
@@ -25,7 +27,7 @@ import PathInjectionCustomizations::PathInjection
|
||||
*
|
||||
* Such checks are ineffective in the `NotNormalized` state.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "PathInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
@@ -74,3 +76,52 @@ class NotNormalized extends DataFlow::FlowState {
|
||||
class NormalizedUnchecked extends DataFlow::FlowState {
|
||||
NormalizedUnchecked() { this = "NormalizedUnchecked" }
|
||||
}
|
||||
|
||||
/**
|
||||
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
|
||||
* to track the requirement that a file path must be first normalized and then checked
|
||||
* before it is safe to use.
|
||||
*
|
||||
* At sources, paths are assumed not normalized. At normalization points, they change
|
||||
* state to `NormalizedUnchecked` after which they can be made safe by an appropriate
|
||||
* check of the prefix.
|
||||
*
|
||||
* Such checks are ineffective in the `NotNormalized` state.
|
||||
*/
|
||||
module PathInjectionConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = DataFlow::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source instanceof Source and state instanceof NotNormalized
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof Sink and
|
||||
(
|
||||
state instanceof NotNormalized or
|
||||
state instanceof NormalizedUnchecked
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
// Block `NotNormalized` paths here, since they change state to `NormalizedUnchecked`
|
||||
node instanceof Path::PathNormalization and
|
||||
state instanceof NotNormalized
|
||||
or
|
||||
node instanceof Path::SafeAccessCheck and
|
||||
state instanceof NormalizedUnchecked
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
|
||||
) {
|
||||
nodeFrom = nodeTo.(Path::PathNormalization).getPathArg() and
|
||||
stateFrom instanceof NotNormalized and
|
||||
stateTo instanceof NormalizedUnchecked
|
||||
}
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "path injection" vulnerabilities. */
|
||||
module PathInjectionFlow = TaintTracking::GlobalWithState<PathInjectionConfig>;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.DataFlow2
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import PolynomialReDoSCustomizations::PolynomialReDoS
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `PolynomialReDoSFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "polynomial regular expression denial of service (ReDoS)" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "PolynomialReDoS" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module PolynomialReDoSConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "polynomial regular expression denial of service (ReDoS)" vulnerabilities. */
|
||||
module PolynomialReDoSFlow = TaintTracking::Global<PolynomialReDoSConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import ReflectedXSSCustomizations::ReflectedXss
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ReflectedXssFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "ReflectedXSS" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module ReflectedXssConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "reflected server-side cross-site scripting" vulnerabilities. */
|
||||
module ReflectedXssFlow = TaintTracking::Global<ReflectedXssConfig>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for detecting regular expression injection
|
||||
* Provides a taint-tracking configuration for detecting "regular expression injection"
|
||||
* vulnerabilities.
|
||||
*
|
||||
* Note, for performance reasons: only import this file if
|
||||
@@ -13,9 +13,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import RegexInjectionCustomizations::RegexInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `RegexInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "RegexInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -28,3 +30,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module RegexInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "regular expression injection" vulnerabilities. */
|
||||
module RegexInjectionFlow = TaintTracking::Global<RegexInjectionConfig>;
|
||||
|
||||
@@ -13,6 +13,8 @@ import semmle.python.Concepts
|
||||
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
|
||||
*
|
||||
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
|
||||
@@ -21,7 +23,7 @@ import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
|
||||
* You should use the `fullyControlledRequest` to only select results where all
|
||||
* URL parts are fully controlled.
|
||||
*/
|
||||
class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
|
||||
deprecated class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
|
||||
FullServerSideRequestForgeryConfiguration() { this = "FullServerSideRequestForgery" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -39,24 +41,51 @@ class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configura
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
|
||||
* See `PartialServerSideRequestForgery` for a variant without this requirement.
|
||||
*
|
||||
* You should use the `fullyControlledRequest` to only select results where all
|
||||
* URL parts are fully controlled.
|
||||
*/
|
||||
private module FullServerSideRequestForgeryConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof Sanitizer
|
||||
or
|
||||
node instanceof FullUrlControlSanitizer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global taint-tracking for detecting "Full server-side request forgery" vulnerabilities.
|
||||
*
|
||||
* You should use the `fullyControlledRequest` to only select results where all
|
||||
* URL parts are fully controlled.
|
||||
*/
|
||||
module FullServerSideRequestForgeryFlow = TaintTracking::Global<FullServerSideRequestForgeryConfig>;
|
||||
|
||||
/**
|
||||
* Holds if all URL parts of `request` is fully user controlled.
|
||||
*/
|
||||
predicate fullyControlledRequest(Http::Client::Request request) {
|
||||
exists(FullServerSideRequestForgeryConfiguration fullConfig |
|
||||
forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
|
||||
fullConfig.hasFlow(_, urlPart)
|
||||
)
|
||||
forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
|
||||
FullServerSideRequestForgeryFlow::flow(_, urlPart)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
|
||||
*
|
||||
* This configuration has results, even when the attacker does not have full control over the URL.
|
||||
* See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
|
||||
*/
|
||||
class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
|
||||
deprecated class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
|
||||
PartialServerSideRequestForgeryConfiguration() { this = "PartialServerSideRequestForgery" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -69,3 +98,21 @@ class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Config
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This configuration has results, even when the attacker does not have full control over the URL.
|
||||
* See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
|
||||
*/
|
||||
private module PartialServerSideRequestForgeryConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/**
|
||||
* Global taint-tracking for detecting "partial server-side request forgery" vulnerabilities.
|
||||
*/
|
||||
module PartialServerSideRequestForgeryFlow =
|
||||
TaintTracking::Global<PartialServerSideRequestForgeryConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import SqlInjectionCustomizations::SqlInjection
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `SqlInjectionFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "SQL injection" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "SqlInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
private module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "SQL injection" vulnerabilities. */
|
||||
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
|
||||
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import StackTraceExposureCustomizations::StackTraceExposure
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `StackTraceExposureFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "StackTraceExposure" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -36,3 +38,23 @@ class Configuration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module StackTraceExposureConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
// A stack trace is accessible as the `__traceback__` attribute of a caught exception.
|
||||
// see https://docs.python.org/3/reference/datamodel.html#traceback-objects
|
||||
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
exists(DataFlow::AttrRead attr | attr.getAttributeName() = "__traceback__" |
|
||||
nodeFrom = attr.getObject() and
|
||||
nodeTo = attr
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "stack trace exposure" vulnerabilities. */
|
||||
module StackTraceExposureFlow = TaintTracking::Global<StackTraceExposureConfig>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for detecting "command injection" vulnerabilities.
|
||||
* Provides a taint-tracking configuration for detecting "tar slip" vulnerabilities.
|
||||
*
|
||||
* Note, for performance reasons: only import this file if
|
||||
* `TarSlip::Configuration` is needed, otherwise
|
||||
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import TarSlipCustomizations::TarSlip
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for detecting "command injection" vulnerabilities.
|
||||
* DEPRECATED: Use `TarSlipFlow` module instead.
|
||||
*
|
||||
* A taint-tracking configuration for detecting "tar slip" vulnerabilities.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
deprecated class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "TarSlip" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
@@ -23,3 +25,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
private module TarSlipConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
}
|
||||
|
||||
/** Global taint-tracking for detecting "tar slip" vulnerabilities. */
|
||||
module TarSlipFlow = TaintTracking::Global<TarSlipConfig>;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user