mirror of
https://github.com/github/codeql.git
synced 2026-06-19 03:41:07 +02:00
Compare commits
41 Commits
bazookamus
...
copilot/vs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
376c783f67 | ||
|
|
e781af9b0d | ||
|
|
47a8c5d9a7 | ||
|
|
f84e8b0fbc | ||
|
|
d7ff3ff472 | ||
|
|
5c91529b92 | ||
|
|
996a936f85 | ||
|
|
e56ca68821 | ||
|
|
6d3d220f71 | ||
|
|
7aa651a6c7 | ||
|
|
ee6b8394ab | ||
|
|
d8ac19e8c2 | ||
|
|
5578987d0a | ||
|
|
b6813ac20f | ||
|
|
b12f7915f9 | ||
|
|
e2516fc383 | ||
|
|
44e7f0fc6d | ||
|
|
c489f6ffa1 | ||
|
|
c620a423d5 | ||
|
|
a23b398be9 | ||
|
|
bee9ead570 | ||
|
|
481564668d | ||
|
|
d189d28f63 | ||
|
|
b411b0ecd0 | ||
|
|
2c4fe160bf | ||
|
|
0faf3c89df | ||
|
|
b01c0c524b | ||
|
|
82913576d6 | ||
|
|
c054c3e9b5 | ||
|
|
7538201824 | ||
|
|
e8310f4805 | ||
|
|
f239a8cbce | ||
|
|
13cbc84ded | ||
|
|
0c2d12b6b0 | ||
|
|
2731bce761 | ||
|
|
171ec3cd90 | ||
|
|
5eb47af3c2 | ||
|
|
367de60ca8 | ||
|
|
0e97c26da6 | ||
|
|
23675b0fae | ||
|
|
2b26022e4b |
208
.github/workflows/go-version-update.yml
vendored
208
.github/workflows/go-version-update.yml
vendored
@@ -1,208 +0,0 @@
|
||||
name: Update Go version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 3 * * 1" # Run weekly on Mondays at 3 AM UTC (1 = Monday)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-go-version:
|
||||
name: Check and update Go version
|
||||
if: github.repository == 'github/codeql'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch latest Go version
|
||||
id: fetch-version
|
||||
run: |
|
||||
LATEST_GO_VERSION=$(curl -s https://go.dev/dl/?mode=json | jq -r '.[0].version')
|
||||
|
||||
if [ -z "$LATEST_GO_VERSION" ] || [ "$LATEST_GO_VERSION" = "null" ]; then
|
||||
echo "Error: Failed to fetch latest Go version from go.dev"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Latest Go version from go.dev: $LATEST_GO_VERSION"
|
||||
echo "version=$LATEST_GO_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract version numbers (e.g., go1.26.0 -> 1.26.0)
|
||||
LATEST_VERSION_NUM=$(echo $LATEST_GO_VERSION | sed 's/^go//')
|
||||
echo "version_num=$LATEST_VERSION_NUM" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version (e.g., 1.26.0 -> 1.26)
|
||||
LATEST_MAJOR_MINOR=$(echo $LATEST_VERSION_NUM | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$LATEST_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check current Go version
|
||||
id: current-version
|
||||
run: |
|
||||
CURRENT_VERSION=$(sed -n 's/.*go_sdk\.download(version = \"\([^\"]*\)\".*/\1/p' MODULE.bazel)
|
||||
|
||||
if [ -z "$CURRENT_VERSION" ]; then
|
||||
echo "Error: Could not extract Go version from MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Current Go version in MODULE.bazel: $CURRENT_VERSION"
|
||||
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version
|
||||
CURRENT_MAJOR_MINOR=$(echo $CURRENT_VERSION | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$CURRENT_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Compare versions
|
||||
id: compare
|
||||
run: |
|
||||
LATEST="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
echo "Latest: $LATEST"
|
||||
echo "Current: $CURRENT"
|
||||
|
||||
if [ "$LATEST" = "$CURRENT" ]; then
|
||||
echo "Go version is up to date"
|
||||
echo "needs_update=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Go version needs update from $CURRENT to $LATEST"
|
||||
echo "needs_update=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Update Go version in files
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
CURRENT_MAJOR_MINOR="${{ steps.current-version.outputs.major_minor }}"
|
||||
|
||||
echo "Updating from $CURRENT_VERSION to $LATEST_VERSION_NUM"
|
||||
|
||||
# Escape dots in current version strings for use in sed patterns
|
||||
CURRENT_VERSION_ESCAPED=$(echo "$CURRENT_VERSION" | sed 's/\./\\./g')
|
||||
CURRENT_MAJOR_MINOR_ESCAPED=$(echo "$CURRENT_MAJOR_MINOR" | sed 's/\./\\./g')
|
||||
|
||||
# Update MODULE.bazel
|
||||
sed -i "s/go_sdk\.download(version = \"$CURRENT_VERSION_ESCAPED\")/go_sdk.download(version = \"$LATEST_VERSION_NUM\")/" MODULE.bazel
|
||||
if ! grep -q "go_sdk.download(version = \"$LATEST_VERSION_NUM\")" MODULE.bazel; then
|
||||
echo "Error: Failed to update MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update go/extractor/go.mod
|
||||
if ! sed -i "s/^go $CURRENT_MAJOR_MINOR_ESCAPED\$/go $LATEST_MAJOR_MINOR/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update go directive in go.mod"
|
||||
fi
|
||||
if ! sed -i "s/^toolchain go$CURRENT_VERSION_ESCAPED\$/toolchain go$LATEST_VERSION_NUM/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update toolchain in go.mod"
|
||||
fi
|
||||
|
||||
# Update go/extractor/autobuilder/build-environment.go
|
||||
if ! sed -i "s/var maxGoVersion = util\.NewSemVer(\"$CURRENT_MAJOR_MINOR_ESCAPED\")/var maxGoVersion = util.NewSemVer(\"$LATEST_MAJOR_MINOR\")/" go/extractor/autobuilder/build-environment.go; then
|
||||
echo "Warning: Failed to update build-environment.go"
|
||||
fi
|
||||
|
||||
# Update go/actions/test/action.yml
|
||||
if ! sed -i "s/default: \"~$CURRENT_VERSION_ESCAPED\"/default: \"~$LATEST_VERSION_NUM\"/" go/actions/test/action.yml; then
|
||||
echo "Warning: Failed to update action.yml"
|
||||
fi
|
||||
|
||||
# Show what changed
|
||||
git diff
|
||||
|
||||
- name: Check for changes
|
||||
id: check-changes
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "No changes detected"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Changes detected"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check for existing PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: check-pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number')
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "Existing PR found: #$PR_NUMBER"
|
||||
echo "pr_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "No existing PR found"
|
||||
echo "pr_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
|
||||
# Create or switch to branch
|
||||
git checkout -B "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add MODULE.bazel go/extractor/go.mod go/extractor/autobuilder/build-environment.go go/actions/test/action.yml
|
||||
git commit -m "Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
# Push changes
|
||||
git push --force-with-lease origin "$BRANCH_NAME"
|
||||
|
||||
- name: Create or update PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
PR_TITLE="Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
PR_BODY=$(cat <<EOF
|
||||
This PR updates Go from $CURRENT_VERSION to $LATEST_VERSION_NUM.
|
||||
|
||||
Updated files:
|
||||
- \`MODULE.bazel\` - go_sdk.download version
|
||||
- \`go/extractor/go.mod\` - go directive and toolchain
|
||||
- \`go/extractor/autobuilder/build-environment.go\` - maxGoVersion (only if MAJOR.MINOR changes)
|
||||
- \`go/actions/test/action.yml\` - default go-test-version
|
||||
|
||||
This PR was automatically created by the [Go version update workflow](https://github.com/${{ github.repository }}/blob/main/.github/workflows/go-version-update.yml).
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "${{ steps.check-pr.outputs.pr_exists }}" = "true" ]; then
|
||||
echo "Updating existing PR #${{ steps.check-pr.outputs.pr_number }}"
|
||||
gh pr edit "${{ steps.check-pr.outputs.pr_number }}" --title "$PR_TITLE" --body "$PR_BODY"
|
||||
else
|
||||
echo "Creating new PR"
|
||||
gh pr create \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY" \
|
||||
--base main \
|
||||
--head "$BRANCH_NAME" \
|
||||
--label "Go"
|
||||
fi
|
||||
@@ -2,7 +2,7 @@
|
||||
* @github/code-scanning-alert-coverage
|
||||
|
||||
# CodeQL language libraries
|
||||
/actions/ @github/code-scanning-alert-coverage
|
||||
/actions/ @github/codeql-dynamic
|
||||
/cpp/ @github/codeql-c-analysis
|
||||
/csharp/ @github/codeql-csharp
|
||||
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage
|
||||
@@ -59,5 +59,9 @@ MODULE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/rust.yml @github/codeql-rust
|
||||
/.github/workflows/swift.yml @github/codeql-swift
|
||||
|
||||
# Misc
|
||||
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||
/misc/scripts/generate-code-scanning-query-list.py @RasmusWL
|
||||
|
||||
# .devcontainer
|
||||
/.devcontainer/ @github/codeql-ci-reviewers
|
||||
|
||||
@@ -273,7 +273,7 @@ use_repo(
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.26.4")
|
||||
go_sdk.download(version = "1.26.0")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
## 0.4.36
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
@@ -1920,5 +1920,3 @@ private YamlMappingLikeNode resolveMatrixAccessPath(
|
||||
else result = resolveMatrixAccessPath(newRoot, rest)
|
||||
)
|
||||
}
|
||||
|
||||
class Comment = YamlComment;
|
||||
|
||||
@@ -52,12 +52,6 @@ private module YamlSig implements LibYaml::InputSig {
|
||||
class ParseErrorBase extends LocatableBase, @yaml_error {
|
||||
string getMessage() { yaml_errors(this, result) }
|
||||
}
|
||||
|
||||
class CommentBase extends LocatableBase, @yaml_comment {
|
||||
string getText() { yaml_comments(this, result, _) }
|
||||
|
||||
override string toString() { yaml_comments(this, _, result) }
|
||||
}
|
||||
}
|
||||
|
||||
import LibYaml::Make<YamlSig>
|
||||
|
||||
@@ -2,12 +2,10 @@ import actions
|
||||
|
||||
bindingset[runner]
|
||||
predicate isGithubHostedRunner(string runner) {
|
||||
// The list of github hosted repos:
|
||||
// https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||
// https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories
|
||||
runner.toLowerCase().regexpMatch("^ubuntu-([0-9.]+|latest|slim)(-arm)?$") or
|
||||
runner.toLowerCase().regexpMatch("^macos-([0-9]+|latest)(-x?large|-intel)?$") or
|
||||
runner.toLowerCase().regexpMatch("^windows-([0-9.]+|latest)(-vs[0-9.]+)?(-arm)?$")
|
||||
// list of github hosted repos: https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||
runner
|
||||
.toLowerCase()
|
||||
.regexpMatch("^(ubuntu-([0-9.]+|latest)|macos-([0-9]+|latest)(-x?large)?|windows-([0-9.]+|latest))$")
|
||||
}
|
||||
|
||||
bindingset[runner]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
## 0.6.28
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @name Checkout of untrusted code in a non-privileged context
|
||||
* @description Checking out and running the build script from a fork executes untrusted code. Even in a
|
||||
* non-privileged workflow, this can be abused, for example to compromise self-hosted runners
|
||||
* or to poison caches and artifacts that are later consumed by privileged workflows.
|
||||
* @name Checkout of untrusted code in a trusted context
|
||||
* @description Privileged workflows have read/write access to the base repository and access to secrets.
|
||||
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
|
||||
* that is able to push to the base repository and to access secrets.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
@@ -20,4 +20,4 @@ from PRHeadCheckoutStep checkout
|
||||
where
|
||||
// the checkout occurs in a non-privileged context
|
||||
inNonPrivilegedContext(checkout)
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on non-privileged workflow."
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-24.04-arm
|
||||
- ubuntu-22.04
|
||||
- ubuntu-22.04-arm
|
||||
- ubuntu-26.04
|
||||
- ubuntu-26.04-arm
|
||||
- ubuntu-slim
|
||||
- macos-26
|
||||
- macos-26-xlarge
|
||||
- macos-26-intel
|
||||
- macos-26-large
|
||||
- macos-latest-large
|
||||
- macos-15-large
|
||||
- macos-15
|
||||
- macos-15-intel
|
||||
- macos-latest
|
||||
- macos-15
|
||||
- macos-15-xlarge
|
||||
- macos-14-large
|
||||
- macos-14
|
||||
- macos-14-xlarge
|
||||
- windows-2025-vs2026
|
||||
- windows-latest
|
||||
- windows-2025
|
||||
- windows-2022
|
||||
- windows-11
|
||||
- windows-11-arm
|
||||
- windows-11-vs2026-arm
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: cmd
|
||||
@@ -1,10 +1,10 @@
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
|
||||
],
|
||||
"Bound Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/Bound.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll"
|
||||
],
|
||||
"ModulusAnalysis Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
|
||||
* const float fa[40];
|
||||
* ```
|
||||
*/
|
||||
class DerivedType extends Type, NameQualifyingElement, @derivedtype {
|
||||
class DerivedType extends Type, @derivedtype {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getName() { derivedtypes(underlyingElement(this), result, _, _) }
|
||||
|
||||
@@ -1430,8 +1430,7 @@ specialnamequalifyingelements(
|
||||
@namequalifyingelement = @namespace
|
||||
| @specialnamequalifyingelement
|
||||
| @usertype
|
||||
| @decltype
|
||||
| @derivedtype;
|
||||
| @decltype;
|
||||
|
||||
namequalifiers(
|
||||
unique int id: @namequalifier,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1,7 +1,3 @@
|
||||
| inconsistency2.cpp:3:3:3:5 | T:: | inconsistency2.cpp:3:3:3:6 | x | inconsistency2.cpp:2:20:2:20 | T |
|
||||
| inconsistency2.cpp:3:3:3:11 | const s:: | inconsistency2.cpp:3:3:3:6 | x | file://:0:0:0:0 | const s |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | (int)... | inconsistency.cpp:4:8:4:8 | S |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | A | inconsistency.cpp:4:8:4:8 | S |
|
||||
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
|
||||
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
|
||||
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import cpp
|
||||
|
||||
from NameQualifier nq, Location l
|
||||
where l = nq.getQualifiedElement().getLocation()
|
||||
where
|
||||
l = nq.getQualifiedElement().getLocation() and
|
||||
l.getFile().getShortName() = "name_qualifiers"
|
||||
select nq, nq.getQualifiedElement(), nq.getQualifyingElement()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
|
||||
|
||||
// As such, there is no QL part of the test.
|
||||
|
||||
struct S { enum E { A }; };
|
||||
|
||||
static void f() {
|
||||
static int f() {
|
||||
switch(0) { case S::A: break; }
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace {
|
||||
template <typename T> T f() {
|
||||
T::x;
|
||||
return {};
|
||||
}
|
||||
struct s {
|
||||
static int x;
|
||||
};
|
||||
struct t {
|
||||
s x = f<const s>();
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
@@ -9,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
internal abstract class ElementAccess : Expression<ExpressionSyntax>
|
||||
{
|
||||
protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList)
|
||||
: base(info.SetKind(GetKind(info.Context, info.Node, qualifier)))
|
||||
: base(info.SetKind(GetKind(info.Context, qualifier)))
|
||||
{
|
||||
this.qualifier = qualifier;
|
||||
this.argumentList = argumentList;
|
||||
@@ -18,125 +17,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private readonly ExpressionSyntax qualifier;
|
||||
private readonly BracketedArgumentListSyntax argumentList;
|
||||
|
||||
|
||||
private ISymbol? GetTargetSymbol()
|
||||
{
|
||||
return Context.GetSymbolInfo(base.Syntax).Symbol;
|
||||
}
|
||||
|
||||
private static void SetExprArgument(TextWriter trapFile, Expression left, Expression right)
|
||||
{
|
||||
trapFile.expr_argument(left, 0);
|
||||
trapFile.expr_argument(right, 0);
|
||||
}
|
||||
|
||||
private Expression MakeZeroFromEndExpression(IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var info = new ExpressionInfo(
|
||||
Context,
|
||||
AnnotatedTypeSymbol.CreateNotAnnotated(Context.Compilation.GetSpecialType(SpecialType.System_Int32)),
|
||||
Location,
|
||||
ExprKind.INDEX,
|
||||
parent,
|
||||
child,
|
||||
isCompilerGenerated: true,
|
||||
null);
|
||||
|
||||
var index = new Expression(info);
|
||||
|
||||
MakeZeroLiteral(index, 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
private Expression MakeZeroLiteral(IExpressionParentEntity parent, int child)
|
||||
{
|
||||
return Literal.CreateGenerated(Context, parent, child, Context.Compilation.GetSpecialType(SpecialType.System_Int32), 0, Location);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// It is assumed that either the input is
|
||||
/// 1. A normal expression that can be used as endpoint (e.g a constant like "3").
|
||||
/// 2. An index expression indicating that we should read from the end (e.g "^1").
|
||||
/// </summary>
|
||||
/// <param name="syntax">The syntax node representing the range endpoint.</param>
|
||||
/// <param name="parent">The parent expression entity.</param>
|
||||
/// <param name="child">The child index within the parent.</param>
|
||||
/// <returns>An expression representing the endpoint of a range to be used in conjunction with a slice operation.</returns>
|
||||
private Expression MakeFromRangeEndpoint(ExpressionSyntax syntax, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var info = new ExpressionNodeInfo(Context, syntax, parent, child);
|
||||
|
||||
return syntax.Kind() == SyntaxKind.IndexExpression
|
||||
? PrefixUnary.Create(info.SetKind(ExprKind.INDEX))
|
||||
: Factory.Create(info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given method is a slice method, which is defined as a method with
|
||||
/// the name "Slice" or "Substring" and two parameters.
|
||||
/// </summary>
|
||||
/// <param name="method">The method symbol to check.</param>
|
||||
/// <returns>True if the method is a slice method; false otherwise.</returns>
|
||||
private bool IsSlice(IMethodSymbol method, out RangeExpressionSyntax? range)
|
||||
{
|
||||
range = null;
|
||||
|
||||
if (argumentList.Arguments.Count == 1)
|
||||
{
|
||||
range = argumentList.Arguments[0].Expression as RangeExpressionSyntax;
|
||||
}
|
||||
|
||||
return (method.Name == "Slice" || method.Name == "Substring")
|
||||
&& method.Parameters.Length == 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates a slice method call based on the given range.
|
||||
/// Roslyn translates indexer accesses with range expressions in the following way.
|
||||
/// 1. s[a..b] -> s.Slice(a, b - a)
|
||||
/// 2. s[..b] -> s.Slice(0, b)
|
||||
/// 3. s[a..] -> s.Slice(a, s.Length - a)
|
||||
/// 4. s[..] -> s.Slice(0, s.Length)
|
||||
/// However, it is possible that both the qualifier or the index endpoints may contain method calls.
|
||||
/// If we want to translate this accurately, we would need to introduce synthetic statements for qualifier and
|
||||
/// the endpoints, which should then be used in the slice method call.
|
||||
/// To avoid this, we translate as follows.
|
||||
/// 1. s[a..b] -> s.Slice(a, b)
|
||||
/// 2. s[..b] -> s.Slice(0, b)
|
||||
/// 3. s[a..] -> s.Slice(a, ^0)
|
||||
/// 4. s[..] -> s.Slice(0, ^0)
|
||||
///
|
||||
/// Even though index expressions can't technically be used in this way, they signal that we
|
||||
/// could perceive ^b as "length - b".
|
||||
///
|
||||
/// Call arguments are only populated when a range expression is directly available in
|
||||
/// the list of arguments.
|
||||
/// This means that cases like below are not handled.
|
||||
/// System.Range x = 1..3;
|
||||
/// s[x]
|
||||
/// </summary>
|
||||
/// <param name="trapFile">The trap file to write to.</param>
|
||||
/// <param name="slice">The slice method symbol.</param>
|
||||
/// <param name="range">The range expression syntax.</param>
|
||||
private void PopulateSlice(TextWriter trapFile, IMethodSymbol slice, RangeExpressionSyntax? range)
|
||||
{
|
||||
if (range is not null)
|
||||
{
|
||||
// Populate the call arguments
|
||||
var left = range.LeftOperand is ExpressionSyntax lsyntax
|
||||
? MakeFromRangeEndpoint(lsyntax, this, 0)
|
||||
: MakeZeroLiteral(this, 0);
|
||||
|
||||
var right = range.RightOperand is ExpressionSyntax rsyntax
|
||||
? MakeFromRangeEndpoint(rsyntax, this, 1)
|
||||
: MakeZeroFromEndExpression(this, 1);
|
||||
|
||||
SetExprArgument(trapFile, left, right);
|
||||
}
|
||||
trapFile.expr_call(this, Method.Create(Context, slice));
|
||||
}
|
||||
|
||||
protected override void PopulateExpression(TextWriter trapFile)
|
||||
{
|
||||
if (Kind == ExprKind.POINTER_INDIRECTION)
|
||||
@@ -150,19 +30,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
else
|
||||
{
|
||||
Create(Context, qualifier, this, -1);
|
||||
|
||||
var target = GetTargetSymbol();
|
||||
if (target is IMethodSymbol method && IsSlice(method, out var range))
|
||||
{
|
||||
// When an indexer on a span or string is used in conjunction with a range expression, the compiler translates
|
||||
// this into a call to the "Slice" or "Substring" method.
|
||||
// In this case, we want to populate a slice/substring method call instead of an indexer access.
|
||||
PopulateSlice(trapFile, method, range);
|
||||
return;
|
||||
}
|
||||
|
||||
PopulateArguments(trapFile, argumentList, 0);
|
||||
if (target is IPropertySymbol { IsIndexer: true } indexer)
|
||||
|
||||
var symbolInfo = Context.GetSymbolInfo(base.Syntax);
|
||||
|
||||
if (symbolInfo.Symbol is IPropertySymbol indexer)
|
||||
{
|
||||
trapFile.expr_access(this, Indexer.Create(Context, indexer));
|
||||
}
|
||||
@@ -174,11 +46,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private static bool IsArray(ITypeSymbol symbol) =>
|
||||
symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array || symbol.IsInlineArray();
|
||||
|
||||
private static ExprKind GetKind(Context cx, ExpressionSyntax syntax, ExpressionSyntax qualifier)
|
||||
private static ExprKind GetKind(Context cx, ExpressionSyntax qualifier)
|
||||
{
|
||||
if (cx.GetSymbolInfo(syntax).Symbol is IMethodSymbol)
|
||||
return ExprKind.METHOD_INVOCATION;
|
||||
|
||||
var qualifierType = cx.GetType(qualifier);
|
||||
|
||||
// This is a compilation error, so make a guess and continue.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
||||
@@ -50,15 +50,15 @@ private predicate maybeUsedInElfHashFunction(Variable v, Operation xor, Operatio
|
||||
|
|
||||
add instanceof AddOperation and
|
||||
e1.getAChild*() = add.getAnOperand() and
|
||||
e1 instanceof BinaryBitwiseExpr and
|
||||
e2 = e1.(BinaryBitwiseExpr).getLeftOperand() and
|
||||
e1 instanceof BinaryBitwiseOperation and
|
||||
e2 = e1.(BinaryBitwiseOperation).getLeftOperand() and
|
||||
v = addAssign.getTargetVariable() and
|
||||
addAssign.getAChild*() = add and
|
||||
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
|
||||
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
|
||||
xorAssign.getAChild*() = xor and
|
||||
v = xorAssign.getTargetVariable() and
|
||||
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseExpr) and
|
||||
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseOperation) and
|
||||
xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and
|
||||
notAssign.getAChild*() = notOp and
|
||||
v = notAssign.getTargetVariable() and
|
||||
|
||||
@@ -9,7 +9,6 @@ dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
codeql/rangeanalysis: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/threat-models: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
|
||||
@@ -290,7 +290,7 @@ module AssignableInternal {
|
||||
newtype TAssignableDefinition =
|
||||
TAssignmentDefinition(Assignment a) {
|
||||
not a.getLeftOperand() instanceof TupleExpr and
|
||||
not a instanceof AssignCallExpr and
|
||||
not a instanceof AssignCallOperation and
|
||||
not a instanceof AssignCoalesceExpr
|
||||
} or
|
||||
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
|
||||
@@ -324,7 +324,7 @@ module AssignableInternal {
|
||||
TAddressOfDefinition(AddressOfExpr aoe) or
|
||||
TPatternDefinition(TopLevelPatternDecl tlpd) or
|
||||
TAssignOperationDefinition(AssignOperation ao) {
|
||||
ao instanceof AssignCallExpr and not ao instanceof CompoundAssignmentOperatorCall
|
||||
ao instanceof AssignCallOperation and not ao instanceof CompoundAssignmentOperatorCall
|
||||
or
|
||||
ao instanceof AssignCoalesceExpr
|
||||
}
|
||||
|
||||
@@ -57,28 +57,6 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE
|
||||
/** Gets the `set` accessor of this declaration, if any. */
|
||||
Setter getSetter() { result = this.getAnAccessor() }
|
||||
|
||||
/** Gets the target accessor of this declaration when used in a read context, if any. */
|
||||
Accessor getReadTarget() {
|
||||
result = this.getGetter()
|
||||
or
|
||||
not exists(this.getGetter()) and
|
||||
result = this.getOverridee().getReadTarget()
|
||||
}
|
||||
|
||||
/** Gets the target accessor of this declaration when used in a write context, if any. */
|
||||
Accessor getWriteTarget() {
|
||||
result = this.getSetter()
|
||||
or
|
||||
not exists(this.getSetter()) and
|
||||
result = this.getOverridee().getWriteTarget()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = this.getReadTarget() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
}
|
||||
|
||||
override DeclarationWithGetSetAccessors getOverridee() {
|
||||
result = DeclarationWithAccessors.super.getOverridee()
|
||||
}
|
||||
|
||||
@@ -912,17 +912,18 @@ module Internal {
|
||||
)
|
||||
or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
result =
|
||||
any(BinaryArithmeticOperation bao |
|
||||
exists(Expr o |
|
||||
bao.getAnOperand() = e and
|
||||
bao.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
)
|
||||
exists(BinaryOperation bo, Expr o |
|
||||
bo instanceof BinaryArithmeticOperation or
|
||||
bo instanceof AssignArithmeticOperation
|
||||
|
|
||||
result = bo and
|
||||
bo.getAnOperand() = e and
|
||||
bo.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -933,10 +934,10 @@ module Internal {
|
||||
any(QualifiableExpr qe |
|
||||
qe.isConditional() and
|
||||
result = qe.getQualifier()
|
||||
)
|
||||
or
|
||||
) or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand())
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) or
|
||||
e = any(AssignArithmeticOperation aao | result = aao.getAnOperand())
|
||||
}
|
||||
|
||||
deprecated predicate isGuard(Expr e, GuardValue val) {
|
||||
|
||||
@@ -172,10 +172,6 @@ module Ast implements AstSig<Location> {
|
||||
|
||||
class DoStmt = CS::DoStmt;
|
||||
|
||||
class UntilStmt extends LoopStmt {
|
||||
UntilStmt() { none() }
|
||||
}
|
||||
|
||||
final private class FinalForStmt = CS::ForStmt;
|
||||
|
||||
class ForStmt extends FinalForStmt {
|
||||
@@ -207,7 +203,7 @@ module Ast implements AstSig<Location> {
|
||||
final private class FinalTryStmt = CS::TryStmt;
|
||||
|
||||
class TryStmt extends FinalTryStmt {
|
||||
AstNode getBody(int index) { index = 0 and result = this.getBlock() }
|
||||
Stmt getBody() { result = this.getBlock() }
|
||||
|
||||
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
||||
|
||||
|
||||
@@ -4,31 +4,67 @@
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
private import codeql.rangeanalysis.Bound as SharedBound
|
||||
private import internal.rangeanalysis.BoundSpecific
|
||||
|
||||
/** Provides C#-specific definitions for bounds. */
|
||||
private module BoundDefs implements SharedBound::BoundDefinitions<CS::Location> {
|
||||
class Type = CS::Type;
|
||||
private newtype TBound =
|
||||
TBoundZero() or
|
||||
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
|
||||
TBoundExpr(Expr e) {
|
||||
interestingExprBound(e) and
|
||||
not exists(SsaVariable v | e = v.getAUse())
|
||||
}
|
||||
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
/**
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
abstract class Bound extends TBound {
|
||||
/** Gets a textual representation of this bound. */
|
||||
abstract string toString();
|
||||
|
||||
class SsaSourceVariable = SourceVariable;
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
abstract Expr getExpr(int delta);
|
||||
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = this.getExpr(0) }
|
||||
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
/** Gets the location of this bound. */
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
module BoundImpl = SharedBound::Bound<CS::Location, BoundDefs>;
|
||||
/**
|
||||
* The bound that corresponds to the integer 0. This is used to represent all
|
||||
* integer bounds as bounds are always accompanied by an added integer delta.
|
||||
*/
|
||||
class ZeroBound extends Bound, TBoundZero {
|
||||
override string toString() { result = "0" }
|
||||
|
||||
import BoundImpl
|
||||
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
|
||||
|
||||
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound corresponding to the value of an SSA variable.
|
||||
*/
|
||||
class SsaBound extends Bound, TBoundSsa {
|
||||
/** Gets the SSA variable that equals this bound. */
|
||||
SsaVariable getSsa() { this = TBoundSsa(result) }
|
||||
|
||||
override string toString() { result = this.getSsa().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getSsa().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound that corresponds to the value of a specific expression that might be
|
||||
* interesting, but isn't otherwise represented by the value of an SSA variable.
|
||||
*/
|
||||
class ExprBound extends Bound, TBoundExpr {
|
||||
override string toString() { result = this.getExpr().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Provides C#-specific definitions for bounds.
|
||||
*/
|
||||
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
|
||||
class Location = CS::Location;
|
||||
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
@@ -124,7 +124,9 @@ private module Internal {
|
||||
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
|
||||
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
|
||||
TDispatchDynamicElementAccess(DynamicElementAccess dea) or
|
||||
TDispatchDynamicEventAccess(AssignArithmeticExpr aao, DynamicMemberAccess dma, string name) {
|
||||
TDispatchDynamicEventAccess(
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
isPotentialEventCall(aao, dma, name)
|
||||
} or
|
||||
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
|
||||
@@ -228,7 +230,7 @@ private module Internal {
|
||||
* accessor.
|
||||
*/
|
||||
private predicate isPotentialEventCall(
|
||||
AssignArithmeticExpr aao, DynamicMemberAccess dma, string name
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
aao instanceof DynamicOperatorCall and
|
||||
dma = aao.getLeftOperand() and
|
||||
@@ -1395,7 +1397,9 @@ private module Internal {
|
||||
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
|
||||
TDispatchDynamicEventAccess
|
||||
{
|
||||
override AssignArithmeticExpr getCall() { this = TDispatchDynamicEventAccess(result, _, _) }
|
||||
override AssignArithmeticOperation getCall() {
|
||||
this = TDispatchDynamicEventAccess(result, _, _)
|
||||
}
|
||||
|
||||
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }
|
||||
|
||||
|
||||
@@ -11,27 +11,19 @@ import Expr
|
||||
* (`UnaryArithmeticOperation`) or a binary arithmetic operation
|
||||
* (`BinaryArithmeticOperation`).
|
||||
*/
|
||||
class ArithmeticOperation extends Operation, @arith_operation {
|
||||
class ArithmeticOperation extends Operation, @arith_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary arithmetic operation. Either a binary arithmetic expression (`BinaryArithmeticExpr`) or
|
||||
* an arithmetic assignment expression (`AssignArithmeticExpr`).
|
||||
*/
|
||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_operation {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary arithmetic operation. Either a unary minus expression
|
||||
* (`UnaryMinusExpr`), a unary plus expression (`UnaryPlusExpr`),
|
||||
* A unary arithmetic operation. Either a unary minus operation
|
||||
* (`UnaryMinusExpr`), a unary plus operation (`UnaryPlusExpr`),
|
||||
* or a mutator operation (`MutatorOperation`).
|
||||
*/
|
||||
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_operation { }
|
||||
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_op_expr { }
|
||||
|
||||
/**
|
||||
* A unary minus expression, for example `-x`.
|
||||
* A unary minus operation, for example `-x`.
|
||||
*/
|
||||
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
||||
override string getOperator() { result = "-" }
|
||||
@@ -40,7 +32,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary plus expression, for example `+x`.
|
||||
* A unary plus operation, for example `+x`.
|
||||
*/
|
||||
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||
override string getOperator() { result = "+" }
|
||||
@@ -52,40 +44,40 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||
* A mutator operation. Either an increment operation (`IncrementOperation`)
|
||||
* or a decrement operation (`DecrementOperation`).
|
||||
*/
|
||||
class MutatorOperation extends UnaryArithmeticOperation, @mut_operation { }
|
||||
class MutatorOperation extends UnaryArithmeticOperation, @mut_op_expr { }
|
||||
|
||||
/**
|
||||
* An increment operation. Either a postfix increment expression
|
||||
* (`PostIncrExpr`) or a prefix increment expression (`PreIncrExpr`).
|
||||
* An increment operation. Either a postfix increment operation
|
||||
* (`PostIncrExpr`) or a prefix increment operation (`PreIncrExpr`).
|
||||
*/
|
||||
class IncrementOperation extends MutatorOperation, @incr_operation {
|
||||
class IncrementOperation extends MutatorOperation, @incr_op_expr {
|
||||
override string getOperator() { result = "++" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A decrement operation. Either a postfix decrement expression
|
||||
* (`PostDecrExpr`) or a prefix decrement expression (`PreDecrExpr`).
|
||||
* A decrement operation. Either a postfix decrement operation
|
||||
* (`PostDecrExpr`) or a prefix decrement operation (`PreDecrExpr`).
|
||||
*/
|
||||
class DecrementOperation extends MutatorOperation, @decr_operation {
|
||||
class DecrementOperation extends MutatorOperation, @decr_op_expr {
|
||||
override string getOperator() { result = "--" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix increment expression, for example `++x`.
|
||||
* A prefix increment operation, for example `++x`.
|
||||
*/
|
||||
class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
|
||||
override string getAPrimaryQlClass() { result = "PreIncrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix decrement expression, for example `--x`.
|
||||
* A prefix decrement operation, for example `--x`.
|
||||
*/
|
||||
class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
|
||||
override string getAPrimaryQlClass() { result = "PreDecrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A postfix increment expression, for example `x++`.
|
||||
* A postfix increment operation, for example `x++`.
|
||||
*/
|
||||
class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
||||
override string toString() { result = "..." + this.getOperator() }
|
||||
@@ -94,7 +86,7 @@ class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A postfix decrement expression, for example `x--`.
|
||||
* A postfix decrement operation, for example `x--`.
|
||||
*/
|
||||
class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
||||
override string toString() { result = "..." + this.getOperator() }
|
||||
@@ -103,84 +95,55 @@ class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* An addition operation, either `x + y` or `x += y`.
|
||||
* A binary arithmetic operation. Either an addition operation
|
||||
* (`AddExpr`), a subtraction operation (`SubExpr`), a multiplication
|
||||
* operation (`MulExpr`), a division operation (`DivExpr`), or a
|
||||
* remainder operation (`RemExpr`).
|
||||
*/
|
||||
class AddOperation extends BinaryArithmeticOperation, @add_operation { }
|
||||
|
||||
/**
|
||||
* A subtraction operation, either `x - y` or `x -= y`.
|
||||
*/
|
||||
class SubOperation extends BinaryArithmeticOperation, @sub_operation { }
|
||||
|
||||
/**
|
||||
* A multiplication operation, either `x * y` or `x *= y`.
|
||||
*/
|
||||
class MulOperation extends BinaryArithmeticOperation, @mul_operation { }
|
||||
|
||||
/**
|
||||
* A division operation, either `x / y` or `x /= y`.
|
||||
*/
|
||||
class DivOperation extends BinaryArithmeticOperation, @div_operation {
|
||||
/** Gets the numerator of this division operation. */
|
||||
Expr getNumerator() { result = this.getLeftOperand() }
|
||||
|
||||
/** Gets the denominator of this division operation. */
|
||||
Expr getDenominator() { result = this.getRightOperand() }
|
||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder operation, either `x % y` or `x %= y`.
|
||||
* An addition operation, for example `x + y`.
|
||||
*/
|
||||
class RemOperation extends BinaryArithmeticOperation, @rem_operation { }
|
||||
|
||||
/**
|
||||
* A binary arithmetic expression. Either an addition expression
|
||||
* (`AddExpr`), a subtraction expression (`SubExpr`), a multiplication
|
||||
* expression (`MulExpr`), a division expression (`DivExpr`), or a
|
||||
* remainder expression (`RemExpr`).
|
||||
*/
|
||||
class BinaryArithmeticExpr extends BinaryArithmeticOperation, @bin_arith_expr { }
|
||||
|
||||
/**
|
||||
* An addition expression, for example `x + y`.
|
||||
*/
|
||||
class AddExpr extends BinaryArithmeticExpr, AddOperation, @add_expr {
|
||||
class AddExpr extends BinaryArithmeticOperation, AddOperation, @add_expr {
|
||||
override string getOperator() { result = "+" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A subtraction expression, for example `x - y`.
|
||||
* A subtraction operation, for example `x - y`.
|
||||
*/
|
||||
class SubExpr extends BinaryArithmeticExpr, SubOperation, @sub_expr {
|
||||
class SubExpr extends BinaryArithmeticOperation, SubOperation, @sub_expr {
|
||||
override string getOperator() { result = "-" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A multiplication expression, for example `x * y`.
|
||||
* A multiplication operation, for example `x * y`.
|
||||
*/
|
||||
class MulExpr extends BinaryArithmeticExpr, MulOperation, @mul_expr {
|
||||
class MulExpr extends BinaryArithmeticOperation, MulOperation, @mul_expr {
|
||||
override string getOperator() { result = "*" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A division expression, for example `x / y`.
|
||||
* A division operation, for example `x / y`.
|
||||
*/
|
||||
class DivExpr extends BinaryArithmeticExpr, DivOperation, @div_expr {
|
||||
class DivExpr extends BinaryArithmeticOperation, DivOperation, @div_expr {
|
||||
override string getOperator() { result = "/" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder expression, for example `x % y`.
|
||||
* A remainder operation, for example `x % y`.
|
||||
*/
|
||||
class RemExpr extends BinaryArithmeticExpr, RemOperation, @rem_expr {
|
||||
class RemExpr extends BinaryArithmeticOperation, RemOperation, @rem_expr {
|
||||
override string getOperator() { result = "%" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RemExpr" }
|
||||
|
||||
@@ -72,9 +72,9 @@ class AssignExpr extends Assignment, @simple_assign_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* An assignment operation. Either an arithmetic assignment expression
|
||||
* (`AssignArithmeticExpr`), a bitwise assignment expression
|
||||
* (`AssignBitwiseExpr`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* An assignment operation. Either an arithmetic assignment operation
|
||||
* (`AssignArithmeticOperation`), a bitwise assignment operation
|
||||
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* a null-coalescing assignment (`AssignCoalesceExpr`).
|
||||
*/
|
||||
class AssignOperation extends Assignment, @assign_op_expr {
|
||||
@@ -94,147 +94,134 @@ class AssignOperation extends Assignment, @assign_op_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A compound assignment expression that invokes an operator.
|
||||
* A compound assignment operation that invokes an operator.
|
||||
*
|
||||
* (1) `x += y` invokes the compound assignment operator `+=` (if it exists).
|
||||
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
|
||||
*
|
||||
* Either an arithmetic assignment expression (`AssignArithmeticExpr`) or a bitwise
|
||||
* assignment expression (`AssignBitwiseExpr`).
|
||||
* Either an arithmetic assignment operation (`AssignArithmeticOperation`) or a bitwise
|
||||
* assignment operation (`AssignBitwiseOperation`).
|
||||
*/
|
||||
class AssignCallExpr extends AssignOperation, OperatorCall, QualifiableExpr, @assign_op_call_expr {
|
||||
class AssignCallOperation extends AssignOperation, OperatorCall, QualifiableExpr,
|
||||
@assign_op_call_expr
|
||||
{
|
||||
override string toString() { result = AssignOperation.super.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignCallExpr` instead.
|
||||
*/
|
||||
deprecated class AssignCallOperation = AssignCallExpr;
|
||||
|
||||
/**
|
||||
* An arithmetic assignment expression. Either an addition assignment expression
|
||||
* (`AssignAddExpr`), a subtraction assignment expression (`AssignSubExpr`), a
|
||||
* multiplication assignment expression (`AssignMulExpr`), a division assignment
|
||||
* expression (`AssignDivExpr`), or a remainder assignment expression
|
||||
* An arithmetic assignment operation. Either an addition assignment operation
|
||||
* (`AssignAddExpr`), a subtraction assignment operation (`AssignSubExpr`), a
|
||||
* multiplication assignment operation (`AssignMulExpr`), a division assignment
|
||||
* operation (`AssignDivExpr`), or a remainder assignment operation
|
||||
* (`AssignRemExpr`).
|
||||
*/
|
||||
class AssignArithmeticExpr extends AssignCallExpr, @assign_arith_expr { }
|
||||
class AssignArithmeticOperation extends AssignCallOperation, @assign_arith_expr { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignArithmeticExpr` instead.
|
||||
* An addition assignment operation, for example `x += y`.
|
||||
*/
|
||||
deprecated class AssignArithmeticOperation = AssignArithmeticExpr;
|
||||
|
||||
/**
|
||||
* An addition assignment expression, for example `x += y`.
|
||||
*/
|
||||
class AssignAddExpr extends AssignArithmeticExpr, AddOperation, @assign_add_expr {
|
||||
class AssignAddExpr extends AssignArithmeticOperation, AddOperation, @assign_add_expr {
|
||||
override string getOperator() { result = "+=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A subtraction assignment expression, for example `x -= y`.
|
||||
* A subtraction assignment operation, for example `x -= y`.
|
||||
*/
|
||||
class AssignSubExpr extends AssignArithmeticExpr, SubOperation, @assign_sub_expr {
|
||||
class AssignSubExpr extends AssignArithmeticOperation, SubOperation, @assign_sub_expr {
|
||||
override string getOperator() { result = "-=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A multiplication assignment expression, for example `x *= y`.
|
||||
* An multiplication assignment operation, for example `x *= y`.
|
||||
*/
|
||||
class AssignMulExpr extends AssignArithmeticExpr, MulOperation, @assign_mul_expr {
|
||||
class AssignMulExpr extends AssignArithmeticOperation, MulOperation, @assign_mul_expr {
|
||||
override string getOperator() { result = "*=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A division assignment expression, for example `x /= y`.
|
||||
* An division assignment operation, for example `x /= y`.
|
||||
*/
|
||||
class AssignDivExpr extends AssignArithmeticExpr, DivOperation, @assign_div_expr {
|
||||
class AssignDivExpr extends AssignArithmeticOperation, DivOperation, @assign_div_expr {
|
||||
override string getOperator() { result = "/=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder assignment expression, for example `x %= y`.
|
||||
* A remainder assignment operation, for example `x %= y`.
|
||||
*/
|
||||
class AssignRemExpr extends AssignArithmeticExpr, RemOperation, @assign_rem_expr {
|
||||
class AssignRemExpr extends AssignArithmeticOperation, RemOperation, @assign_rem_expr {
|
||||
override string getOperator() { result = "%=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise assignment expression. Either a bitwise-and assignment
|
||||
* expression (`AssignAndExpr`), a bitwise-or assignment
|
||||
* expression (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* expression (`AssignXorExpr`), a left-shift assignment
|
||||
* expression (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* expression (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* expression (`AssignUnsignedRightShiftExpr`).
|
||||
* A bitwise assignment operation. Either a bitwise-and assignment
|
||||
* operation (`AssignAndExpr`), a bitwise-or assignment
|
||||
* operation (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* operation (`AssignXorExpr`), a left-shift assignment
|
||||
* operation (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* operation (`AssignUnsignedRightShiftExpr`).
|
||||
*/
|
||||
class AssignBitwiseExpr extends AssignCallExpr, @assign_bitwise_expr { }
|
||||
class AssignBitwiseOperation extends AssignCallOperation, @assign_bitwise_expr { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AssignBitwiseExpr` instead.
|
||||
* A bitwise-and assignment operation, for example `x &= y`.
|
||||
*/
|
||||
deprecated class AssignBitwiseOperation = AssignBitwiseExpr;
|
||||
|
||||
/**
|
||||
* A bitwise-and assignment expression, for example `x &= y`.
|
||||
*/
|
||||
class AssignAndExpr extends AssignBitwiseExpr, BitwiseAndOperation, @assign_and_expr {
|
||||
class AssignAndExpr extends AssignBitwiseOperation, BitwiseAndOperation, @assign_and_expr {
|
||||
override string getOperator() { result = "&=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-or assignment expression, for example `x |= y`.
|
||||
* A bitwise-or assignment operation, for example `x |= y`.
|
||||
*/
|
||||
class AssignOrExpr extends AssignBitwiseExpr, BitwiseOrOperation, @assign_or_expr {
|
||||
class AssignOrExpr extends AssignBitwiseOperation, BitwiseOrOperation, @assign_or_expr {
|
||||
override string getOperator() { result = "|=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or assignment expression, for example `x ^= y`.
|
||||
* A bitwise exclusive-or assignment operation, for example `x ^= y`.
|
||||
*/
|
||||
class AssignXorExpr extends AssignBitwiseExpr, BitwiseXorOperation, @assign_xor_expr {
|
||||
class AssignXorExpr extends AssignBitwiseOperation, BitwiseXorOperation, @assign_xor_expr {
|
||||
override string getOperator() { result = "^=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A left-shift assignment expression, for example `x <<= y`.
|
||||
* A left-shift assignment operation, for example `x <<= y`.
|
||||
*/
|
||||
class AssignLeftShiftExpr extends AssignBitwiseExpr, LeftShiftOperation, @assign_lshift_expr {
|
||||
class AssignLeftShiftExpr extends AssignBitwiseOperation, LeftShiftOperation, @assign_lshift_expr {
|
||||
override string getOperator() { result = "<<=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A right-shift assignment expression, for example `x >>= y`.
|
||||
* A right-shift assignment operation, for example `x >>= y`.
|
||||
*/
|
||||
class AssignRightShiftExpr extends AssignBitwiseExpr, RightShiftOperation, @assign_rshift_expr {
|
||||
class AssignRightShiftExpr extends AssignBitwiseOperation, RightShiftOperation, @assign_rshift_expr {
|
||||
override string getOperator() { result = ">>=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unsigned right-shift assignment expression, for example `x >>>= y`.
|
||||
* An unsigned right-shift assignment operation, for example `x >>>= y`.
|
||||
*/
|
||||
class AssignUnsignedRightShiftExpr extends AssignBitwiseExpr, UnsignedRightShiftOperation,
|
||||
class AssignUnsignedRightShiftExpr extends AssignBitwiseOperation, UnsignedRightShiftOperation,
|
||||
@assign_urshift_expr
|
||||
{
|
||||
override string getOperator() { result = ">>>=" }
|
||||
@@ -310,10 +297,10 @@ class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A null-coalescing assignment expression, for example `x ??= y`.
|
||||
* A null-coalescing assignment operation, for example `x ??= y`.
|
||||
*/
|
||||
class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr {
|
||||
override string getOperator() { result = "??=" }
|
||||
override string toString() { result = "... ??= ..." }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
|
||||
}
|
||||
|
||||
@@ -10,16 +10,16 @@ import Expr
|
||||
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
|
||||
* or a binary bitwise operation (`BinaryBitwiseOperation`).
|
||||
*/
|
||||
class BitwiseOperation extends Operation, @bit_operation { }
|
||||
class BitwiseOperation extends Operation, @bit_expr { }
|
||||
|
||||
/**
|
||||
* A unary bitwise operation, that is, a bitwise complement operation
|
||||
* (`ComplementExpr`).
|
||||
*/
|
||||
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_operation { }
|
||||
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_op_expr { }
|
||||
|
||||
/**
|
||||
* A bitwise complement expression, for example `~x`.
|
||||
* A bitwise complement operation, for example `~x`.
|
||||
*/
|
||||
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||
override string getOperator() { result = "~" }
|
||||
@@ -28,101 +28,67 @@ class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary bitwise operation. Either a binary bitwise expression (`BinaryBitwiseExpr`) or
|
||||
* a bitwise assignment expression (`AssignBitwiseExpr`).
|
||||
* A binary bitwise operation. Either a bitwise-and operation
|
||||
* (`BitwiseAndExpr`), a bitwise-or operation (`BitwiseOrExpr`),
|
||||
* a bitwise exclusive-or operation (`BitwiseXorExpr`), a left-shift
|
||||
* operation (`LeftShiftExpr`), a right-shift operation (`RightShiftExpr`),
|
||||
* or an unsigned right-shift operation (`UnsignedRightShiftExpr`).
|
||||
*/
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_operation {
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-and operation, either `x & y` or `x &= y`.
|
||||
* A left-shift operation, for example `x << y`.
|
||||
*/
|
||||
class BitwiseAndOperation extends BinaryBitwiseOperation, @and_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-or operation, either `x | y` or `x |= y`.
|
||||
*/
|
||||
class BitwiseOrOperation extends BinaryBitwiseOperation, @or_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
||||
*/
|
||||
class BitwiseXorOperation extends BinaryBitwiseOperation, @xor_operation { }
|
||||
|
||||
/**
|
||||
* A left-shift operation, either `x << y` or `x <<= y`.
|
||||
*/
|
||||
class LeftShiftOperation extends BinaryBitwiseOperation, @lshift_operation { }
|
||||
|
||||
/**
|
||||
* A right-shift operation, either `x >> y` or `x >>= y`.
|
||||
*/
|
||||
class RightShiftOperation extends BinaryBitwiseOperation, @rshift_operation { }
|
||||
|
||||
/**
|
||||
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
||||
*/
|
||||
class UnsignedRightShiftOperation extends BinaryBitwiseOperation, @urshift_operation { }
|
||||
|
||||
/**
|
||||
* A binary bitwise expression. Either a bitwise-and expression
|
||||
* (`BitwiseAndExpr`), a bitwise-or expression (`BitwiseOrExpr`),
|
||||
* a bitwise exclusive-or expression (`BitwiseXorExpr`), a left-shift
|
||||
* expression (`LeftShiftExpr`), a right-shift expression (`RightShiftExpr`),
|
||||
* or an unsigned right-shift expression (`UnsignedRightShiftExpr`).
|
||||
*/
|
||||
class BinaryBitwiseExpr extends BinaryBitwiseOperation, @bin_bit_expr { }
|
||||
|
||||
/**
|
||||
* A left-shift expression, for example `x << y`.
|
||||
*/
|
||||
class LeftShiftExpr extends BinaryBitwiseExpr, LeftShiftOperation, @lshift_expr {
|
||||
class LeftShiftExpr extends BinaryBitwiseOperation, LeftShiftOperation, @lshift_expr {
|
||||
override string getOperator() { result = "<<" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A right-shift expression, for example `x >> y`.
|
||||
* A right-shift operation, for example `x >> y`.
|
||||
*/
|
||||
class RightShiftExpr extends BinaryBitwiseExpr, RightShiftOperation, @rshift_expr {
|
||||
class RightShiftExpr extends BinaryBitwiseOperation, RightShiftOperation, @rshift_expr {
|
||||
override string getOperator() { result = ">>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unsigned right-shift expression, for example `x >>> y`.
|
||||
* An unsigned right-shift operation, for example `x >>> y`.
|
||||
*/
|
||||
class UnsignedRightShiftExpr extends BinaryBitwiseExpr, UnsignedRightShiftOperation, @urshift_expr {
|
||||
class UnsignedRightShiftExpr extends BinaryBitwiseOperation, UnsignedRightShiftOperation,
|
||||
@urshift_expr
|
||||
{
|
||||
override string getOperator() { result = ">>>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-and expression, for example `x & y`.
|
||||
* A bitwise-and operation, for example `x & y`.
|
||||
*/
|
||||
class BitwiseAndExpr extends BinaryBitwiseExpr, BitwiseAndOperation, @bit_and_expr {
|
||||
class BitwiseAndExpr extends BinaryBitwiseOperation, BitwiseAndOperation, @bit_and_expr {
|
||||
override string getOperator() { result = "&" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise-or expression, for example `x | y`.
|
||||
* A bitwise-or operation, for example `x | y`.
|
||||
*/
|
||||
class BitwiseOrExpr extends BinaryBitwiseExpr, BitwiseOrOperation, @bit_or_expr {
|
||||
class BitwiseOrExpr extends BinaryBitwiseOperation, BitwiseOrOperation, @bit_or_expr {
|
||||
override string getOperator() { result = "|" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or expression, for example `x ^ y`.
|
||||
* A bitwise exclusive-or operation, for example `x ^ y`.
|
||||
*/
|
||||
class BitwiseXorExpr extends BinaryBitwiseExpr, BitwiseXorOperation, @bit_xor_expr {
|
||||
class BitwiseXorExpr extends BinaryBitwiseOperation, BitwiseXorOperation, @bit_xor_expr {
|
||||
override string getOperator() { result = "^" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
|
||||
@@ -609,7 +609,7 @@ class InstanceMutatorOperatorCall extends MutatorOperatorCall {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CompoundAssignmentOperatorCall extends AssignCallExpr {
|
||||
class CompoundAssignmentOperatorCall extends AssignCallOperation {
|
||||
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
|
||||
|
||||
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }
|
||||
@@ -762,12 +762,20 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr {
|
||||
*/
|
||||
class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
||||
override Accessor getReadTarget() {
|
||||
this instanceof AssignableRead and result = this.getProperty().getReadTarget()
|
||||
this instanceof AssignableRead and result = this.getProperty().getGetter()
|
||||
}
|
||||
|
||||
override Accessor getWriteTarget() {
|
||||
this instanceof AssignableWrite and
|
||||
result = this.getProperty().getWriteTarget()
|
||||
exists(Property p | p = this.getProperty() |
|
||||
result = p.getSetter()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = p.getGetter() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
@@ -798,12 +806,20 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
||||
*/
|
||||
class IndexerCall extends AccessorCall, IndexerAccessExpr {
|
||||
override Accessor getReadTarget() {
|
||||
this instanceof AssignableRead and result = this.getIndexer().getReadTarget()
|
||||
this instanceof AssignableRead and result = this.getIndexer().getGetter()
|
||||
}
|
||||
|
||||
override Accessor getWriteTarget() {
|
||||
this instanceof AssignableWrite and
|
||||
result = this.getIndexer().getWriteTarget()
|
||||
exists(Indexer i | i = this.getIndexer() |
|
||||
result = i.getSetter()
|
||||
or
|
||||
result =
|
||||
any(Getter g |
|
||||
g = i.getGetter() and
|
||||
g.getAnnotatedReturnType().isRef()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import Creation
|
||||
import Dynamic
|
||||
import Literal
|
||||
import LogicalOperation
|
||||
import Operation
|
||||
import semmle.code.csharp.controlflow.ControlFlowElement
|
||||
import semmle.code.csharp.Location
|
||||
import semmle.code.csharp.Stmt
|
||||
@@ -211,7 +212,7 @@ class LocalConstantDeclExpr extends LocalVariableDeclExpr {
|
||||
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
|
||||
* ternary operation (`TernaryOperation`).
|
||||
*/
|
||||
class Operation extends Expr, @operation_expr {
|
||||
class Operation extends Expr, @op_expr {
|
||||
/** Gets the name of the operator in this operation. */
|
||||
string getOperator() { none() }
|
||||
|
||||
@@ -226,7 +227,7 @@ class Operation extends Expr, @operation_expr {
|
||||
* indirection operation (`PointerIndirectionExpr`), an address-of operation
|
||||
* (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`).
|
||||
*/
|
||||
class UnaryOperation extends Operation, @un_operation {
|
||||
class UnaryOperation extends Operation, @un_op {
|
||||
/** Gets the operand of this unary operation. */
|
||||
Expr getOperand() { result = this.getChild(0) }
|
||||
|
||||
@@ -240,7 +241,7 @@ class UnaryOperation extends Operation, @un_operation {
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or an
|
||||
* assignment (`Assignment`).
|
||||
*/
|
||||
class BinaryOperation extends Operation, @bin_operation {
|
||||
class BinaryOperation extends Operation, @bin_op {
|
||||
/** Gets the left operand of this binary operation. */
|
||||
Expr getLeftOperand() { result = this.getChild(0) }
|
||||
|
||||
@@ -263,7 +264,7 @@ class BinaryOperation extends Operation, @bin_operation {
|
||||
* A ternary operation, that is, a ternary conditional operation
|
||||
* (`ConditionalExpr`).
|
||||
*/
|
||||
class TernaryOperation extends Operation, @ternary_operation { }
|
||||
class TernaryOperation extends Operation, @ternary_op { }
|
||||
|
||||
/**
|
||||
* A parenthesized expression, for example `(2 + 3)` in
|
||||
|
||||
@@ -11,14 +11,14 @@ import Expr
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
|
||||
* operation (`TernaryLogicalOperation`).
|
||||
*/
|
||||
class LogicalOperation extends Operation, @log_operation {
|
||||
class LogicalOperation extends Operation, @log_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`).
|
||||
*/
|
||||
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_operation { }
|
||||
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_op_expr { }
|
||||
|
||||
/**
|
||||
* A logical 'not', for example `!String.IsNullOrEmpty(s)`.
|
||||
@@ -31,10 +31,10 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
|
||||
|
||||
/**
|
||||
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
|
||||
* a logical 'or' (`LogicalOrExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingOperation`).
|
||||
* a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingExpr`).
|
||||
*/
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_operation {
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
@@ -57,12 +57,7 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
||||
*/
|
||||
class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_operation { }
|
||||
|
||||
/**
|
||||
* A null-coalescing expression, for example `s ?? ""` on line 2 in
|
||||
* A null-coalescing operation, for example `s ?? ""` on line 2 in
|
||||
*
|
||||
* ```csharp
|
||||
* string NonNullOrEmpty(string s) {
|
||||
@@ -70,7 +65,9 @@ class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_o
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr {
|
||||
class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation,
|
||||
@null_coalescing_expr
|
||||
{
|
||||
override string getOperator() { result = "??" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
|
||||
@@ -80,7 +77,7 @@ class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr
|
||||
* A ternary logical operation, that is, a ternary conditional expression
|
||||
* (`ConditionalExpr`).
|
||||
*/
|
||||
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_operation { }
|
||||
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr { }
|
||||
|
||||
/**
|
||||
* A conditional expression, for example `s != null ? s.Length : -1`
|
||||
|
||||
@@ -1,6 +1,71 @@
|
||||
/**
|
||||
* Provides classes for operations that also have compound assignment forms.
|
||||
*/
|
||||
deprecated module;
|
||||
|
||||
import Expr
|
||||
|
||||
/**
|
||||
* An addition operation, either `x + y` or `x += y`.
|
||||
*/
|
||||
class AddOperation extends BinaryOperation, @add_operation { }
|
||||
|
||||
/**
|
||||
* A subtraction operation, either `x - y` or `x -= y`.
|
||||
*/
|
||||
class SubOperation extends BinaryOperation, @sub_operation { }
|
||||
|
||||
/**
|
||||
* A multiplication operation, either `x * y` or `x *= y`.
|
||||
*/
|
||||
class MulOperation extends BinaryOperation, @mul_operation { }
|
||||
|
||||
/**
|
||||
* A division operation, either `x / y` or `x /= y`.
|
||||
*/
|
||||
class DivOperation extends BinaryOperation, @div_operation {
|
||||
/** Gets the numerator of this division operation. */
|
||||
Expr getNumerator() { result = this.getLeftOperand() }
|
||||
|
||||
/** Gets the denominator of this division operation. */
|
||||
Expr getDenominator() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A remainder operation, either `x % y` or `x %= y`.
|
||||
*/
|
||||
class RemOperation extends BinaryOperation, @rem_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-and operation, either `x & y` or `x &= y`.
|
||||
*/
|
||||
class BitwiseAndOperation extends BinaryOperation, @and_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise-or operation, either `x | y` or `x |= y`.
|
||||
*/
|
||||
class BitwiseOrOperation extends BinaryOperation, @or_operation { }
|
||||
|
||||
/**
|
||||
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
||||
*/
|
||||
class BitwiseXorOperation extends BinaryOperation, @xor_operation { }
|
||||
|
||||
/**
|
||||
* A left-shift operation, either `x << y` or `x <<= y`.
|
||||
*/
|
||||
class LeftShiftOperation extends BinaryOperation, @lshift_operation { }
|
||||
|
||||
/**
|
||||
* A right-shift operation, either `x >> y` or `x >>= y`.
|
||||
*/
|
||||
class RightShiftOperation extends BinaryOperation, @rshift_operation { }
|
||||
|
||||
/**
|
||||
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
||||
*/
|
||||
class UnsignedRightShiftOperation extends BinaryOperation, @urshift_operation { }
|
||||
|
||||
/**
|
||||
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
||||
*/
|
||||
class NullCoalescingOperation extends BinaryOperation, @null_coalescing_operation { }
|
||||
|
||||
@@ -13,7 +13,6 @@ private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.WCF
|
||||
private import semmle.code.csharp.frameworks.microsoft.Owin
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
private import semmle.code.csharp.frameworks.Razor
|
||||
private import semmle.code.csharp.dataflow.internal.ExternalFlow
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
|
||||
|
||||
@@ -315,22 +314,6 @@ class AspNetCoreActionMethodParameter extends AspNetCoreRemoteFlowSource, DataFl
|
||||
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
||||
}
|
||||
|
||||
/** A parameter to a Razor Page handler method, viewed as a source of remote user input. */
|
||||
class AspNetCorePageHandlerMethodParameter extends AspNetCoreRemoteFlowSource,
|
||||
DataFlow::ParameterNode
|
||||
{
|
||||
AspNetCorePageHandlerMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(PageModelClass pm).getAHandlerMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core Razor Page handler method parameter" }
|
||||
}
|
||||
|
||||
private class ExternalRemoteFlowSource extends RemoteFlowSource {
|
||||
ExternalRemoteFlowSource() { sourceNode(this, "remote") }
|
||||
|
||||
|
||||
@@ -1254,39 +1254,33 @@ case @expr.kind of
|
||||
|
||||
@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
|
||||
|
||||
@bin_arith_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||
@bin_arith_operation = @mul_operation | @div_operation | @rem_operation | @add_operation | @sub_operation;
|
||||
@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||
@incr_op_expr = @pre_incr_expr | @post_incr_expr;
|
||||
@decr_op_expr = @pre_decr_expr | @post_decr_expr;
|
||||
@mut_op_expr = @incr_op_expr | @decr_op_expr;
|
||||
@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
|
||||
@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
|
||||
|
||||
@incr_operation = @pre_incr_expr | @post_incr_expr;
|
||||
@decr_operation = @pre_decr_expr | @post_decr_expr;
|
||||
@mut_operation = @incr_operation | @decr_operation;
|
||||
@un_arith_operation = @plus_expr | @minus_expr | @mut_operation;
|
||||
@arith_operation = @bin_arith_operation | @un_arith_operation;
|
||||
@ternary_log_op_expr = @conditional_expr;
|
||||
@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
|
||||
@un_log_op_expr = @log_not_expr;
|
||||
@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
|
||||
|
||||
@ternary_log_operation = @conditional_expr;
|
||||
@bin_log_operation = @log_and_expr | @log_or_expr | @null_coalescing_operation;
|
||||
@un_log_operation = @log_not_expr;
|
||||
@log_operation = @un_log_operation | @bin_log_operation | @ternary_log_operation;
|
||||
|
||||
@bin_bit_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
||||
| @rshift_expr | @urshift_expr;
|
||||
@bin_bit_operation = @and_operation | @or_operation | @xor_operation | @lshift_operation
|
||||
| @rshift_operation | @urshift_operation;
|
||||
@un_bit_expr = @bit_not_expr;
|
||||
@un_bit_operation = @un_bit_expr;
|
||||
@bit_expr = @un_bit_expr | @bin_bit_expr;
|
||||
@bit_operation = @un_bit_operation | @bin_bit_operation;
|
||||
@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
||||
| @rshift_expr | @urshift_expr;
|
||||
@un_bit_op_expr = @bit_not_expr;
|
||||
@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
|
||||
|
||||
@equality_op_expr = @eq_expr | @ne_expr;
|
||||
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
|
||||
@comp_expr = @equality_op_expr | @rel_op_expr;
|
||||
|
||||
@operation_expr = @un_operation | @bin_operation | @ternary_operation;
|
||||
@op_expr = @un_op | @bin_op | @ternary_op;
|
||||
|
||||
@ternary_operation = @ternary_log_operation;
|
||||
@bin_operation = @assign_expr | @bin_arith_operation | @bin_log_operation | @bin_bit_operation | @comp_expr;
|
||||
@un_operation = @un_arith_operation | @un_log_operation | @un_bit_operation | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
@ternary_op = @ternary_log_op_expr;
|
||||
@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
|
||||
@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
|
||||
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -63,7 +63,7 @@ module CallTargetStats implements StatsSig {
|
||||
|
||||
additional predicate isNotOkCall(Call c) {
|
||||
not exists(c.getTarget()) and
|
||||
not c instanceof DelegateLikeCall and
|
||||
not c instanceof DelegateCall and
|
||||
not c instanceof DynamicExpr and
|
||||
not isNoSetterPropertyCallInConstructor(c) and
|
||||
not isNoSetterPropertyInitialization(c) and
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
binarybitwise
|
||||
| Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr |
|
||||
| Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr |
|
||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
||||
assignbitwise
|
||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
||||
userdefined
|
||||
|
||||
@@ -11,7 +11,7 @@ query predicate binarybitwise(
|
||||
}
|
||||
|
||||
query predicate assignbitwise(
|
||||
AssignBitwiseExpr op, Expr left, Expr right, string name, string qlclass
|
||||
AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass
|
||||
) {
|
||||
op.getFile().getStem() = "Operators" and
|
||||
left = op.getLeftOperand() and
|
||||
|
||||
@@ -442,31 +442,4 @@ namespace My.Qltest
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
|
||||
// Test operator overloads
|
||||
public class N
|
||||
{
|
||||
public void operator +=(N y) => throw null;
|
||||
|
||||
public void operator checked +=(N y) => throw null;
|
||||
|
||||
public void M1(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
n += n0;
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
public void M2(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
checked
|
||||
{
|
||||
n += n0;
|
||||
}
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,16 +32,14 @@ models
|
||||
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
||||
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
||||
| 34 | Summary: My.Qltest; N; false; op_AdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 35 | Summary: My.Qltest; N; false; op_CheckedAdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 42 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 43 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
| 34 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 35 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
edges
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
||||
@@ -164,77 +162,69 @@ edges
|
||||
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:40 |
|
||||
nodes
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||
@@ -453,16 +443,6 @@ nodes
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
subpaths
|
||||
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
||||
invalidModelRow
|
||||
@@ -509,5 +489,3 @@ invalidModelRow
|
||||
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | $@ | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | object creation of type N : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | $@ | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | object creation of type N : N |
|
||||
|
||||
@@ -53,8 +53,6 @@ extensions:
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_AdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_CheckedAdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
|
||||
@@ -63,32 +63,4 @@ namespace Testing
|
||||
{
|
||||
public void MyActionMethod(string param) { }
|
||||
}
|
||||
|
||||
// Razor Page handler tests
|
||||
public class MyPageModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||
{
|
||||
// Handler method parameters are remote flow sources
|
||||
public void OnGet(string id) { }
|
||||
|
||||
public void OnPost(string command, int count) { }
|
||||
|
||||
public void OnPostAsync(string data) { }
|
||||
|
||||
public void OnPut(string value) { }
|
||||
|
||||
public void OnDelete(string itemId) { }
|
||||
|
||||
// Not a handler method — does not start with "On", so not a flow source
|
||||
public void GetUser(string userId) { }
|
||||
|
||||
// Excluded by [NonHandler] attribute, so not a flow source
|
||||
[Microsoft.AspNetCore.Mvc.RazorPages.NonHandlerAttribute]
|
||||
public void OnGetNonHandler(string param) { }
|
||||
}
|
||||
|
||||
// Subclass of a PageModel subclass
|
||||
public class DerivedPageModel : MyPageModel
|
||||
{
|
||||
public void OnPost(string derivedParam) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,3 @@ remoteFlowSources
|
||||
| AspRemoteFlowSource.cs:54:69:54:82 | mapDeleteParam |
|
||||
| AspRemoteFlowSource.cs:56:41:56:44 | item |
|
||||
| AspRemoteFlowSource.cs:64:43:64:47 | param |
|
||||
| AspRemoteFlowSource.cs:71:34:71:35 | id |
|
||||
| AspRemoteFlowSource.cs:73:35:73:41 | command |
|
||||
| AspRemoteFlowSource.cs:73:48:73:52 | count |
|
||||
| AspRemoteFlowSource.cs:75:40:75:43 | data |
|
||||
| AspRemoteFlowSource.cs:77:34:77:38 | value |
|
||||
| AspRemoteFlowSource.cs:79:37:79:42 | itemId |
|
||||
| AspRemoteFlowSource.cs:92:35:92:46 | derivedParam |
|
||||
|
||||
@@ -293,69 +293,3 @@ properties.cs:
|
||||
# 160| 0: [LocalVariableAccess] access to local variable x
|
||||
# 160| 1: [PropertyCall] access to property Prop
|
||||
# 160| -1: [LocalVariableAccess] access to local variable s
|
||||
# 164| 13: [Class] BaseClass
|
||||
# 166| 6: [Property] Value
|
||||
# 166| -1: [TypeMention] int
|
||||
# 168| 3: [Getter] get_Value
|
||||
# 168| 4: [BlockStmt] {...}
|
||||
# 168| 0: [ReturnStmt] return ...;
|
||||
# 168| 0: [FieldAccess] access to field Value.field
|
||||
# 169| 4: [Setter] set_Value
|
||||
#-----| 2: (Parameters)
|
||||
# 169| 0: [Parameter] value
|
||||
# 169| 4: [BlockStmt] {...}
|
||||
# 169| 0: [ExprStmt] ...;
|
||||
# 169| 0: [AssignExpr] ... = ...
|
||||
# 169| 0: [FieldAccess] access to field Value.field
|
||||
# 169| 1: [ParameterAccess] access to parameter value
|
||||
# 166| 7: [Field] Value.field
|
||||
# 173| 14: [Class] DerivedClass1
|
||||
#-----| 3: (Base types)
|
||||
# 173| 0: [TypeMention] BaseClass
|
||||
# 175| 6: [Property] Value
|
||||
# 175| -1: [TypeMention] int
|
||||
# 177| 3: [Getter] get_Value
|
||||
# 177| 4: [BlockStmt] {...}
|
||||
# 177| 0: [ReturnStmt] return ...;
|
||||
# 177| 0: [IntLiteral] 20
|
||||
# 181| 15: [Class] DerivedClass2
|
||||
#-----| 3: (Base types)
|
||||
# 181| 0: [TypeMention] BaseClass
|
||||
# 183| 16: [Class] TestPartialPropertyOverride
|
||||
# 185| 6: [Method] M
|
||||
# 185| -1: [TypeMention] Void
|
||||
# 186| 4: [BlockStmt] {...}
|
||||
# 187| 0: [LocalVariableDeclStmt] ... ...;
|
||||
# 187| 0: [LocalVariableDeclAndInitExpr] DerivedClass1 d1 = ...
|
||||
# 187| -1: [TypeMention] DerivedClass1
|
||||
# 187| 0: [LocalVariableAccess] access to local variable d1
|
||||
# 187| 1: [ObjectCreation] object creation of type DerivedClass1
|
||||
# 187| 0: [TypeMention] DerivedClass1
|
||||
# 188| 1: [ExprStmt] ...;
|
||||
# 188| 0: [AssignExpr] ... = ...
|
||||
# 188| 0: [PropertyCall] access to property Value
|
||||
# 188| -1: [LocalVariableAccess] access to local variable d1
|
||||
# 188| 1: [IntLiteral] 11
|
||||
# 189| 2: [LocalVariableDeclStmt] ... ...;
|
||||
# 189| 0: [LocalVariableDeclAndInitExpr] Int32 test1 = ...
|
||||
# 189| -1: [TypeMention] int
|
||||
# 189| 0: [LocalVariableAccess] access to local variable test1
|
||||
# 189| 1: [PropertyCall] access to property Value
|
||||
# 189| -1: [LocalVariableAccess] access to local variable d1
|
||||
# 191| 3: [LocalVariableDeclStmt] ... ...;
|
||||
# 191| 0: [LocalVariableDeclAndInitExpr] DerivedClass2 d2 = ...
|
||||
# 191| -1: [TypeMention] DerivedClass2
|
||||
# 191| 0: [LocalVariableAccess] access to local variable d2
|
||||
# 191| 1: [ObjectCreation] object creation of type DerivedClass2
|
||||
# 191| 0: [TypeMention] DerivedClass2
|
||||
# 192| 4: [ExprStmt] ...;
|
||||
# 192| 0: [AssignExpr] ... = ...
|
||||
# 192| 0: [PropertyCall] access to property Value
|
||||
# 192| -1: [LocalVariableAccess] access to local variable d2
|
||||
# 192| 1: [IntLiteral] 12
|
||||
# 193| 5: [LocalVariableDeclStmt] ... ...;
|
||||
# 193| 0: [LocalVariableDeclAndInitExpr] Int32 test2 = ...
|
||||
# 193| -1: [TypeMention] int
|
||||
# 193| 0: [LocalVariableAccess] access to local variable test2
|
||||
# 193| 1: [PropertyCall] access to property Value
|
||||
# 193| -1: [LocalVariableAccess] access to local variable d2
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
| Prop.field |
|
||||
| Value.field |
|
||||
| caption |
|
||||
| next |
|
||||
| x |
|
||||
|
||||
@@ -6,7 +6,3 @@
|
||||
| properties.cs:71:28:71:28 | Y | properties.cs:83:39:83:44 | access to property Y | properties.cs:74:13:74:15 | set_Y |
|
||||
| properties.cs:146:24:146:27 | Prop | properties.cs:159:13:159:18 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||
| properties.cs:146:24:146:27 | Prop | properties.cs:160:21:160:26 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||
| properties.cs:166:28:166:32 | Value | properties.cs:192:13:192:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
||||
| properties.cs:166:28:166:32 | Value | properties.cs:193:25:193:32 | access to property Value | properties.cs:168:13:168:15 | get_Value |
|
||||
| properties.cs:175:29:175:33 | Value | properties.cs:188:13:188:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
||||
| properties.cs:175:29:175:33 | Value | properties.cs:189:25:189:32 | access to property Value | properties.cs:177:13:177:15 | get_Value |
|
||||
|
||||
@@ -160,37 +160,4 @@ namespace Properties
|
||||
var x = s.Prop;
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseClass
|
||||
{
|
||||
public virtual int Value
|
||||
{
|
||||
get { return field; }
|
||||
set { field = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass1 : BaseClass
|
||||
{
|
||||
public override int Value
|
||||
{
|
||||
get { return 20; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass2 : BaseClass { }
|
||||
|
||||
public class TestPartialPropertyOverride
|
||||
{
|
||||
public void M()
|
||||
{
|
||||
var d1 = new DerivedClass1();
|
||||
d1.Value = 11;
|
||||
var test1 = d1.Value;
|
||||
|
||||
var d2 = new DerivedClass2();
|
||||
d2.Value = 12;
|
||||
var test2 = d2.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
|
||||
public class C
|
||||
{
|
||||
public void M(int a, int b)
|
||||
{
|
||||
var s = "hello world";
|
||||
var sub1 = s[1..a];
|
||||
var sub2 = s[..2];
|
||||
var sub3 = s[3..];
|
||||
var sub4 = s[..^4];
|
||||
var sub5 = s[a..^b];
|
||||
var sub6 = s[..];
|
||||
|
||||
Range range = 1..a;
|
||||
var sub7 = s[range];
|
||||
|
||||
Span<int> sp = null;
|
||||
var slice1 = sp[5..a];
|
||||
var slice2 = sp[..6];
|
||||
var slice3 = sp[7..];
|
||||
var slice4 = sp[..^8];
|
||||
var slice5 = sp[a..^b];
|
||||
var slice6 = sp[..];
|
||||
|
||||
Range range2 = 1..a;
|
||||
var slice7 = sp[range2];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
methodArguments
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) | 0 | 1 |
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) | 1 | access to parameter a |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) | 1 | 2 |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) | 0 | 3 |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) | 1 | ^0 |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) | 1 | ^4 |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) | 0 | access to parameter a |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) | 1 | ^access to parameter b |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) | 0 | 0 |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) | 1 | ^0 |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) | 0 | 5 |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) | 1 | access to parameter a |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) | 1 | 6 |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) | 0 | 7 |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) | 1 | ^0 |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) | 1 | ^8 |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) | 0 | access to parameter a |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) | 1 | ^access to parameter b |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) | 0 | 0 |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) | 1 | ^0 |
|
||||
methodCalls
|
||||
| Slice.cs:3:14:3:14 | call to method <object initializer> | <object initializer>() |
|
||||
| Slice.cs:8:20:8:26 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:9:20:9:25 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:10:20:10:25 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:11:20:11:26 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:12:20:12:27 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:13:20:13:24 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:16:20:16:27 | call to method Substring | Substring(int, int) |
|
||||
| Slice.cs:19:22:19:29 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:20:22:20:28 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:21:22:21:28 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:22:22:22:29 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:23:22:23:30 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:24:22:24:27 | call to method Slice | Slice(int, int) |
|
||||
| Slice.cs:27:22:27:31 | call to method Slice | Slice(int, int) |
|
||||
@@ -1,17 +0,0 @@
|
||||
import csharp
|
||||
|
||||
private string printExpr(Expr e) {
|
||||
e = any(IndexExpr index | result = "^" + index.getExpr().toString())
|
||||
or
|
||||
not e instanceof IndexExpr and
|
||||
result = e.toString()
|
||||
}
|
||||
|
||||
query predicate methodArguments(MethodCall mc, string target, int i, string arg) {
|
||||
target = mc.getTarget().toStringWithTypes() and
|
||||
arg = printExpr(mc.getArgument(i))
|
||||
}
|
||||
|
||||
query predicate methodCalls(MethodCall mc, string target) {
|
||||
target = mc.getTarget().toStringWithTypes()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
|
||||
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
|
||||
|
||||
@@ -7,5 +7,7 @@
|
||||
| Quality.cs:20:13:20:23 | access to property MyProperty6 | Call without target $@. | Quality.cs:20:13:20:23 | access to property MyProperty6 | access to property MyProperty6 |
|
||||
| Quality.cs:23:9:23:14 | access to event Event1 | Call without target $@. | Quality.cs:23:9:23:14 | access to event Event1 | access to event Event1 |
|
||||
| Quality.cs:23:9:23:30 | delegate call | Call without target $@. | Quality.cs:23:9:23:30 | delegate call | delegate call |
|
||||
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
|
||||
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
|
||||
| Quality.cs:38:16:38:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:38:16:38:26 | access to property MyProperty2 | access to property MyProperty2 |
|
||||
| Quality.cs:50:20:50:26 | object creation of type T | Call without target $@. | Quality.cs:50:20:50:26 | object creation of type T | object creation of type T |
|
||||
|
||||
@@ -23,10 +23,10 @@ public class Test
|
||||
Event1.Invoke(this, 5);
|
||||
|
||||
var str = "abcd";
|
||||
var sub = str[..3];
|
||||
var sub = str[..3]; // TODO: this is not an indexer call, but rather a `str.Substring(0, 3)` call.
|
||||
|
||||
Span<int> sp = null;
|
||||
var slice = sp[..3];
|
||||
var slice = sp[..3]; // TODO: this is not an indexer call, but rather a `sp.Slice(0, 3)` call.
|
||||
|
||||
Span<byte> guidBytes = stackalloc byte[16];
|
||||
guidBytes[08] = 1;
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
.. _codeql-cli-2.25.6:
|
||||
|
||||
==========================
|
||||
CodeQL 2.25.6 (2026-06-04)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/application-security/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.25.6 runs a total of 496 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 131 queries (covering 32 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* When the :code:`git` executable is available, CodeQL can now obtain configuration and queries from SHA-256 Git repositories, and infer Git metadata about them.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The build of Eclipse Temurin OpenJDK that is used to run the CodeQL CLI has been updated to version 21.0.11.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`, :code:`actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted :code:`actions/untrusted-checkout/critical` to align more with other untrusted resource queries, where the alert location is the location where the artifact is obtained from (the checkout point). This aligns with the other 2 related queries. This will cause the same alerts to re-open for closed alerts of this query.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Altered the alert message for clarity for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`.
|
||||
* The :code:`actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Reversed adjustment of the name of :code:`actions/untrusted-checkout/high`, but kept the portion of the previous change for the word "trusted" to "privileged". Added a missing "a" to phrasing in :code:`actions/untrusted-checkout/high` and :code:`actions/untrusted-checkout/medium`.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Upgraded to allow analysis of Swift 6.3.2.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow source models for :code:`scanf_s` and related functions.
|
||||
* Added a :code:`Call` column to :code:`LocalFlowSourceFunction::hasLocalFlowSource` and :code:`RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a :code:`Call` column continue to be supported.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Full support for C# 14 / .NET 10. All new language features are now supported by the extractor. The QL library and data flow analysis now support the new C# 14 language constructs and include generated Models as Data (MaD) models for the .NET 10 runtime.
|
||||
* C# 14: Added support for user-defined instance increment/decrement operators.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Added LLM-generated source and sink models for :code:`org.apache.avro`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`js/clear-text-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`swift/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like :code:`^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`rust/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Deprecated APIs
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`UsingAliasTypedefType` class has been deprecated. Use :code:`TypeAliasType` instead.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a :code:`getOriginalTemplate` predicate to :code:`TemplateClass`, :code:`TemplateFunction`, :code:`TemplateVariable`, and :code:`AliasTemplateType`, which yields the class member template the template was generated from. The predicates only have results for templates that are members of class template instantiations.
|
||||
* Added :code:`AliasTemplateType` and :code:`AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
@@ -11,7 +11,6 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.25.6
|
||||
codeql-cli-2.25.5
|
||||
codeql-cli-2.25.4
|
||||
codeql-cli-2.25.3
|
||||
|
||||
@@ -4,7 +4,7 @@ inputs:
|
||||
go-test-version:
|
||||
description: Which Go version to use for running the tests
|
||||
required: false
|
||||
default: "~1.26.4"
|
||||
default: "~1.26.0"
|
||||
run-code-checks:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
|
||||
@@ -2,15 +2,15 @@ module github.com/github/codeql-go/extractor
|
||||
|
||||
go 1.26
|
||||
|
||||
toolchain go1.26.4
|
||||
toolchain go1.26.0
|
||||
|
||||
// when updating this, run
|
||||
// bazel run @rules_go//go -- mod tidy
|
||||
// when adding or removing dependencies, run
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.37.0
|
||||
golang.org/x/tools v0.46.0
|
||||
golang.org/x/mod v0.36.0
|
||||
golang.org/x/tools v0.45.0
|
||||
)
|
||||
|
||||
require github.com/stretchr/testify v1.11.1
|
||||
@@ -18,6 +18,6 @@ require github.com/stretchr/testify v1.11.1
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -6,12 +6,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk=
|
||||
golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
3
go/ql/consistency-queries/CfgConsistency.ql
Normal file
3
go/ql/consistency-queries/CfgConsistency.ql
Normal file
@@ -0,0 +1,3 @@
|
||||
import go
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
import GoCfg::ControlFlow::Consistency
|
||||
4
go/ql/lib/change-notes/2026-03-30-shared-cfg-library.md
Normal file
4
go/ql/lib/change-notes/2026-03-30-shared-cfg-library.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The Go control flow graph implementation has been migrated to use the shared CFG library. This is an internal change with no user-visible API changes.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
|
||||
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
|
||||
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
|
||||
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
|
||||
through `slog`.
|
||||
@@ -1,29 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/go-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
# Package-level convenience functions (msg string, args ...any).
|
||||
- ["log/slog", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
# Context variants (ctx, msg string, args ...any).
|
||||
- ["log/slog", "", False, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
# Log/LogAttrs (ctx, level, msg string, args/attrs ...).
|
||||
- ["log/slog", "", False, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
- ["log/slog", "", False, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
# Methods on *slog.Logger.
|
||||
- ["log/slog", "Logger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "DebugContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "InfoContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "WarnContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "ErrorContext", "", "", "Argument[1..2]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "Log", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
- ["log/slog", "Logger", True, "LogAttrs", "", "", "Argument[2..3]", "log-injection", "manual"]
|
||||
53
go/ql/lib/printCfg.ql
Normal file
53
go/ql/lib/printCfg.ql
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @name Print CFG
|
||||
* @description Produces a representation of a file's Control Flow Graph.
|
||||
* This query is used by the VS Code extension.
|
||||
* @id go/print-cfg
|
||||
* @kind graph
|
||||
* @tags ide-contextual-queries/print-cfg
|
||||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.controlflow.ControlFlowGraph
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
|
||||
external string selectedSourceFile();
|
||||
|
||||
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
||||
|
||||
external int selectedSourceLine();
|
||||
|
||||
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
||||
|
||||
external int selectedSourceColumn();
|
||||
|
||||
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
||||
|
||||
module ViewCfgQueryInput implements GoCfg::ControlFlow::ViewCfgQueryInputSig<File> {
|
||||
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
||||
|
||||
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
||||
|
||||
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
||||
|
||||
predicate cfgScopeSpan(
|
||||
CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn
|
||||
) {
|
||||
file = scope.getFile() and
|
||||
scope.getLocation().getStartLine() = startLine and
|
||||
scope.getLocation().getStartColumn() = startColumn and
|
||||
exists(Location loc |
|
||||
loc.getEndLine() = endLine and
|
||||
loc.getEndColumn() = endColumn and
|
||||
loc = scope.(FuncDef).getBody().getLocation()
|
||||
)
|
||||
or
|
||||
file = scope.(File) and
|
||||
startLine = 1 and
|
||||
startColumn = 1 and
|
||||
endLine = file.getNumberOfLines() and
|
||||
endColumn = 999999
|
||||
}
|
||||
}
|
||||
|
||||
import GoCfg::ControlFlow::ViewCfgQuery<File, ViewCfgQueryInput>
|
||||
@@ -431,7 +431,7 @@ private class HeuristicLoggerFunction extends Method {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
|
||||
override predicate mustNotReturnNormally() { logFunctionPrefix = "Fatal" }
|
||||
|
||||
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
||||
}
|
||||
|
||||
@@ -1049,29 +1049,17 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
*/
|
||||
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th result declaration of this function type (0-based).
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
/** Gets the `i`th result of this function type (0-based). */
|
||||
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
|
||||
|
||||
/**
|
||||
* Gets a result declaration of this function type.
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
/** Gets a result of this function type. */
|
||||
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
|
||||
|
||||
/** Gets the number of result parameters of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl().getANameExpr()) }
|
||||
/** Gets the number of results of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl()) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getResultDecl(int i)` instead.
|
||||
*/
|
||||
deprecated ResultVariableDecl getResultDecl() {
|
||||
this.getNumResult() = 1 and result = this.getAResultDecl()
|
||||
}
|
||||
/** Gets the result of this function type, if there is only one. */
|
||||
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
|
||||
|
||||
override string toString() { result = "function type" }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a Go AST as a graph.
|
||||
*/
|
||||
overlay[local]
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
import go
|
||||
|
||||
@@ -437,11 +437,12 @@ class Function extends ValueEntity, @functionobject {
|
||||
* This predicate is an over-approximation: it may hold for functions that can never
|
||||
* return normally, but it never fails to hold for functions that can.
|
||||
*
|
||||
* Note this is declared here and not in `DeclaredFunction` so that library models can override this
|
||||
* by extending `Function` rather than having to remember to extend `DeclaredFunction`.
|
||||
* Library models should not override this predicate; override `mustNotReturnNormally`
|
||||
* instead, so that the control-flow graph construction can take the model into account.
|
||||
*/
|
||||
predicate mayReturnNormally() {
|
||||
not this.mustPanic() and
|
||||
not this.mustNotReturnNormally() and
|
||||
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
||||
}
|
||||
|
||||
@@ -461,6 +462,16 @@ class Function extends ValueEntity, @functionobject {
|
||||
*/
|
||||
predicate mustPanic() { none() }
|
||||
|
||||
/**
|
||||
* Holds if calling this function never returns normally (for example because it
|
||||
* always panics, exits the process, or loops forever).
|
||||
*
|
||||
* Unlike `mayReturnNormally`, this predicate must be defined without reference to
|
||||
* the control-flow graph, so that it can be used during CFG construction to
|
||||
* suppress normal-flow successors of calls to this function.
|
||||
*/
|
||||
predicate mustNotReturnNormally() { none() }
|
||||
|
||||
/** Gets the number of parameters of this function. */
|
||||
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
||||
|
||||
|
||||
@@ -5,66 +5,27 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphImpl
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
private import codeql.controlflow.SuccessorType
|
||||
private import ControlFlowGraphShared
|
||||
|
||||
private module Input implements BB::InputSig<Location> {
|
||||
/** A delineated part of the AST with its own CFG. */
|
||||
class CfgScope = ControlFlow::Root;
|
||||
/** A basic block in the control-flow graph. */
|
||||
class BasicBlock = GoCfg::Cfg::BasicBlock;
|
||||
|
||||
/** The class of control flow nodes. */
|
||||
class Node = ControlFlowNode;
|
||||
|
||||
/** Gets the CFG scope in which this node occurs. */
|
||||
CfgScope nodeGetCfgScope(Node node) { node.getRoot() = result }
|
||||
|
||||
/** Gets an immediate successor of this node. */
|
||||
Node nodeGetASuccessor(Node node, SuccessorType t) {
|
||||
result = node.getASuccessor() and
|
||||
(
|
||||
not result instanceof ControlFlow::ConditionGuardNode and t instanceof DirectSuccessor
|
||||
or
|
||||
t.(BooleanSuccessor).getValue() = result.(ControlFlow::ConditionGuardNode).getOutcome()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an entry node to be used when calculating
|
||||
* dominance.
|
||||
*/
|
||||
predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an exit node to be used when calculating
|
||||
* post dominance.
|
||||
*/
|
||||
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
|
||||
}
|
||||
|
||||
private module BbImpl = BB::Make<Location, Input>;
|
||||
|
||||
class BasicBlock = BbImpl::BasicBlock;
|
||||
|
||||
class EntryBasicBlock = BbImpl::EntryBasicBlock;
|
||||
|
||||
cached
|
||||
private predicate reachableBB(BasicBlock bb) {
|
||||
bb instanceof EntryBasicBlock
|
||||
or
|
||||
exists(BasicBlock predBB | predBB.getASuccessor(_) = bb | reachableBB(predBB))
|
||||
}
|
||||
/** An entry basic block. */
|
||||
class EntryBasicBlock = GoCfg::Cfg::EntryBasicBlock;
|
||||
|
||||
/**
|
||||
* A basic block that is reachable from an entry basic block.
|
||||
*
|
||||
* Since the shared CFG library only creates nodes for reachable code,
|
||||
* all basic blocks are reachable by construction.
|
||||
*/
|
||||
class ReachableBasicBlock extends BasicBlock {
|
||||
ReachableBasicBlock() { reachableBB(this) }
|
||||
ReachableBasicBlock() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reachable basic block with more than one predecessor.
|
||||
*/
|
||||
class ReachableJoinBlock extends ReachableBasicBlock {
|
||||
ReachableJoinBlock() { this.getFirstNode().isJoin() }
|
||||
ReachableJoinBlock() { this.getFirstNode().(ControlFlow::Node).isJoin() }
|
||||
}
|
||||
|
||||
@@ -5,13 +5,17 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphImpl
|
||||
private import ControlFlowGraphShared
|
||||
|
||||
/** Provides helper predicates for mapping btween CFG nodes and the AST. */
|
||||
/** Provides helper predicates for mapping between CFG nodes and the AST. */
|
||||
module ControlFlow {
|
||||
/** A file or function with which a CFG is associated. */
|
||||
class Root extends AstNode {
|
||||
Root() { exists(this.(File).getADecl()) or exists(this.(FuncDef).getBody()) }
|
||||
Root() {
|
||||
exists(this.(FuncDef).getBody())
|
||||
or
|
||||
exists(this.(File).getADecl())
|
||||
}
|
||||
|
||||
/** Holds if `nd` belongs to this file or function. */
|
||||
predicate isRootOf(AstNode nd) {
|
||||
@@ -29,22 +33,16 @@ module ControlFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* A node in the intra-procedural control-flow graph of a Go function or file.
|
||||
* A node in the intra-procedural control-flow graph of a Go function.
|
||||
*
|
||||
* Nodes correspond to expressions and statements that compute a value or perform
|
||||
* an operation (as opposed to providing syntactic structure or type information).
|
||||
*
|
||||
* There are also synthetic entry and exit nodes for each Go function and file
|
||||
* There are also synthetic entry and exit nodes for each Go function
|
||||
* that mark the beginning and the end, respectively, of the execution of the
|
||||
* function and the loading of the file.
|
||||
* function.
|
||||
*/
|
||||
class Node extends TControlFlowNode {
|
||||
/** Gets a node that directly follows this one in the control-flow graph. */
|
||||
Node getASuccessor() { result = CFG::succ(this) }
|
||||
|
||||
/** Gets a node that directly precedes this one in the control-flow graph. */
|
||||
Node getAPredecessor() { this = result.getASuccessor() }
|
||||
|
||||
class Node extends GoCfg::ControlFlowNode {
|
||||
/** Holds if this is a node with more than one successor. */
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
|
||||
@@ -52,22 +50,23 @@ module ControlFlow {
|
||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||
|
||||
/** Holds if this is the first control-flow node in `subtree`. */
|
||||
predicate isFirstNodeOf(AstNode subtree) { CFG::firstNode(subtree, this) }
|
||||
predicate isFirstNodeOf(AstNode subtree) {
|
||||
this.isBefore(subtree)
|
||||
or
|
||||
this.injects(subtree)
|
||||
}
|
||||
|
||||
/** Holds if this node is the (unique) entry node of a function or file. */
|
||||
predicate isEntryNode() { this instanceof MkEntryNode }
|
||||
/** Holds if this node is the (unique) entry node of a function. */
|
||||
predicate isEntryNode() { this instanceof GoCfg::ControlFlow::EntryNode }
|
||||
|
||||
/** Holds if this node is the (unique) exit node of a function or file. */
|
||||
predicate isExitNode() { this instanceof MkExitNode }
|
||||
|
||||
/** Gets the basic block to which this node belongs. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
/** Holds if this node is the (unique) exit node of a function. */
|
||||
predicate isExitNode() { this instanceof GoCfg::ControlFlow::ExitNode }
|
||||
|
||||
/** Holds if this node dominates `dominee` in the control-flow graph. */
|
||||
overlay[caller?]
|
||||
pragma[inline]
|
||||
predicate dominatesNode(ControlFlow::Node dominee) {
|
||||
exists(ReachableBasicBlock thisbb, ReachableBasicBlock dbb, int i, int j |
|
||||
exists(GoCfg::Cfg::BasicBlock thisbb, GoCfg::Cfg::BasicBlock dbb, int i, int j |
|
||||
this = thisbb.getNode(i) and dominee = dbb.getNode(j)
|
||||
|
|
||||
thisbb.strictlyDominates(dbb)
|
||||
@@ -76,20 +75,12 @@ module ControlFlow {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the innermost function or file to which this node belongs. */
|
||||
Root getRoot() { none() }
|
||||
/** Gets the innermost function to which this node belongs. */
|
||||
Root getRoot() { result = this.getEnclosingCallable() }
|
||||
|
||||
/** Gets the file to which this node belongs. */
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this control flow node.
|
||||
*/
|
||||
string toString() { result = "control-flow node" }
|
||||
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation()` instead.
|
||||
*
|
||||
@@ -113,6 +104,22 @@ module ControlFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** A synthetic entry node for a function. */
|
||||
class EntryNode extends Node instanceof GoCfg::ControlFlow::EntryNode { }
|
||||
|
||||
/** A synthetic exit node for a function. */
|
||||
class ExitNode extends Node instanceof GoCfg::ControlFlow::ExitNode { }
|
||||
|
||||
private predicate isBranchConditionRoot(Expr expr) {
|
||||
expr = any(LogicalBinaryExpr lbe).getLeftOperand()
|
||||
or
|
||||
expr = any(ForStmt fs).getCond()
|
||||
or
|
||||
expr = any(IfStmt is).getCond()
|
||||
or
|
||||
expr = any(ExpressionSwitchStmt ess | not exists(ess.getExpr())).getACase().getAnExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* A control-flow node that initializes or updates the value of a constant, a variable,
|
||||
* a field, or an (array, slice, or map) element.
|
||||
@@ -172,7 +179,7 @@ module ControlFlow {
|
||||
exists(IR::FieldTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getField() = f and
|
||||
super.getRhs() = rhs
|
||||
@@ -220,7 +227,7 @@ module ControlFlow {
|
||||
exists(IR::ElementTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getIndex() = index and
|
||||
super.getRhs() = rhs
|
||||
@@ -250,11 +257,19 @@ module ControlFlow {
|
||||
* A control-flow node recording the fact that a certain expression has a known
|
||||
* Boolean value at this point in the program.
|
||||
*/
|
||||
class ConditionGuardNode extends IR::Instruction, MkConditionGuardNode {
|
||||
class ConditionGuardNode extends IR::Instruction {
|
||||
Expr cond;
|
||||
boolean outcome;
|
||||
|
||||
ConditionGuardNode() { this = MkConditionGuardNode(cond, outcome) }
|
||||
ConditionGuardNode() {
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterTrue(cond) and
|
||||
outcome = true
|
||||
or
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterFalse(cond) and
|
||||
outcome = false
|
||||
}
|
||||
|
||||
private predicate ensuresAux(Expr expr, boolean b) {
|
||||
expr = cond and b = outcome
|
||||
@@ -320,21 +335,17 @@ module ControlFlow {
|
||||
boolean getOutcome() { result = outcome }
|
||||
|
||||
override Root getRoot() { result.isRootOf(cond) }
|
||||
|
||||
override string toString() { result = cond + " is " + outcome }
|
||||
|
||||
override Location getLocation() { result = cond.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entry node of function or file `root`.
|
||||
* Gets the entry node of function `root`.
|
||||
*/
|
||||
Node entryNode(Root root) { result = MkEntryNode(root) }
|
||||
EntryNode entryNode(Root root) { result.getEnclosingCallable() = root }
|
||||
|
||||
/**
|
||||
* Gets the exit node of function or file `root`.
|
||||
* Gets the exit node of function `root`.
|
||||
*/
|
||||
Node exitNode(Root root) { result = MkExitNode(root) }
|
||||
ExitNode exitNode(Root root) { result.getEnclosingCallable() = root }
|
||||
|
||||
/**
|
||||
* Holds if the function `f` may return without panicking, exiting the process, or looping forever.
|
||||
@@ -342,7 +353,12 @@ module ControlFlow {
|
||||
* This is defined conservatively, and so may also hold of a function that in fact
|
||||
* cannot return normally, but never fails to hold of a function that can return normally.
|
||||
*/
|
||||
predicate mayReturnNormally(FuncDecl f) { CFG::mayReturnNormally(f.getBody()) }
|
||||
predicate mayReturnNormally(FuncDecl f) {
|
||||
exists(GoCfg::ControlFlow::NormalExitNode exit |
|
||||
exit.getEnclosingCallable() = f and
|
||||
exists(exit.getAPredecessor())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is the node for the case `testExpr` in an expression
|
||||
@@ -352,10 +368,18 @@ module ControlFlow {
|
||||
predicate isSwitchCaseTestPassingEdge(
|
||||
ControlFlow::Node pred, ControlFlow::Node succ, Expr switchExpr, Expr testExpr
|
||||
) {
|
||||
CFG::isSwitchCaseTestPassingEdge(pred, succ, switchExpr, testExpr)
|
||||
exists(ExpressionSwitchStmt ess, CaseClause cc, int i |
|
||||
ess.getExpr() = switchExpr and
|
||||
cc = ess.getACase() and
|
||||
testExpr = cc.getExpr(i) and
|
||||
pred.isAfter(testExpr) and
|
||||
succ.isFirstNodeOf(cc.getStmt(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ControlFlowNode = ControlFlow::Node;
|
||||
|
||||
class CfgScope = GoCfg::CfgScope;
|
||||
|
||||
class Write = ControlFlow::WriteNode;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1591
go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll
Normal file
1591
go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -200,7 +200,7 @@ private ControlFlow::Node mostRecentSideEffect(ControlFlow::Node entry, ControlF
|
||||
|
||||
cached
|
||||
private ControlFlow::Node mostRecentSideEffectUnique(ControlFlow::Node node) {
|
||||
result = unique( | | mostRecentSideEffect(_, node))
|
||||
result = unique( | | mostRecentSideEffect(getControlFlowEntry(node), node))
|
||||
}
|
||||
|
||||
/** Used to represent the "global value number" of an expression. */
|
||||
|
||||
@@ -89,7 +89,7 @@ private module Internal {
|
||||
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
|
||||
private predicate entryNode(FuncDef f, ReachableBasicBlock bb, int i) {
|
||||
f = bb.getScope() and
|
||||
bb.getNode(i).isEntryNode()
|
||||
bb.getNode(i).(ControlFlow::Node).isEntryNode()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -923,20 +923,15 @@ module Public {
|
||||
/**
|
||||
* A node whose value is returned as a result from a function.
|
||||
*
|
||||
* If the function declares named result variables, this is a node representing
|
||||
* the current value of one of those variables at function exit. Otherwise, this
|
||||
* is a node corresponding to an expression in a return statement.
|
||||
* This can either be a node corresponding to an expression in a return statement,
|
||||
* or a node representing the current value of a named result variable at the exit
|
||||
* of the function.
|
||||
*/
|
||||
class ResultNode extends InstructionNode {
|
||||
int i;
|
||||
|
||||
ResultNode() {
|
||||
exists(FuncDef fd |
|
||||
// If the function has named result variables, then the
|
||||
// `IR::ReadResultInstruction` nodes at the end of the function are
|
||||
// the correct result nodes. Otherwise, the returned expressions are
|
||||
// the result nodes.
|
||||
not exists(fd.getAResultVar()) and
|
||||
exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i))
|
||||
or
|
||||
insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user