mirror of
https://github.com/github/codeql.git
synced 2026-06-22 13:21:10 +02:00
Compare commits
2 Commits
copilot/tw
...
bazookamus
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e40a7124d4 | ||
|
|
7b5cceadf5 |
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")
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
## 0.4.37
|
||||
|
||||
### 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.
|
||||
|
||||
## 0.4.36
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
## 0.4.37
|
||||
|
||||
### 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.37
|
||||
lastReleaseVersion: 0.4.36
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.38-dev
|
||||
version: 0.4.37-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
## 0.6.29
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
* Reversed adjustment of the name of `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 `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Adjusted `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
|
||||
|
||||
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.
|
||||
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
### 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.
|
||||
|
||||
## 0.6.28
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Adjusted `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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* 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,0 +1,4 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* Reversed adjustment of the name of `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 `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.
|
||||
@@ -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.
|
||||
@@ -1,18 +0,0 @@
|
||||
## 0.6.29
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
* Reversed adjustment of the name of `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 `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Adjusted `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
|
||||
|
||||
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.
|
||||
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
### 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.29
|
||||
lastReleaseVersion: 0.6.28
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.30-dev
|
||||
version: 0.6.29-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -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
|
||||
@@ -1,19 +1,3 @@
|
||||
## 10.2.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `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 `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added flow source models for `scanf_s` and related functions.
|
||||
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.
|
||||
|
||||
## 10.1.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
5
cpp/ql/lib/change-notes/2026-05-15-secure-scanf.md
Normal file
5
cpp/ql/lib/change-notes/2026-05-15-secure-scanf.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added flow source models for `scanf_s` and related functions.
|
||||
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.
|
||||
4
cpp/ql/lib/change-notes/2026-05-16-alias-template.md
Normal file
4
cpp/ql/lib/change-notes/2026-05-16-alias-template.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
4
cpp/ql/lib/change-notes/2026-05-18-alias-type.md
Normal file
4
cpp/ql/lib/change-notes/2026-05-18-alias-type.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.
|
||||
4
cpp/ql/lib/change-notes/2026-05-21-generated-from.md
Normal file
4
cpp/ql/lib/change-notes/2026-05-21-generated-from.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `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.
|
||||
@@ -1,15 +0,0 @@
|
||||
## 10.2.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `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 `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added flow source models for `scanf_s` and related functions.
|
||||
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 10.2.0
|
||||
lastReleaseVersion: 10.1.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 10.2.1-dev
|
||||
version: 10.1.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -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, _, _) }
|
||||
|
||||
@@ -276,45 +276,6 @@ private predicate isClassConstructedFrom(Class c, Class templateClass) {
|
||||
not c.isConstructedFrom(_) and c = templateClass
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `c`. */
|
||||
private Class getFullyTemplatedClassOld(Class c) {
|
||||
not c.isFromUninstantiatedTemplate(_) and
|
||||
isClassConstructedFrom(c, result)
|
||||
}
|
||||
|
||||
private TemplateClass getOriginalClassTemplate(TemplateClass tc) {
|
||||
result = tc.getOriginalTemplate()
|
||||
or
|
||||
not exists(tc.getOriginalTemplate()) and
|
||||
result = tc
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `c`. */
|
||||
private Class getFullyTemplatedClassNew(Class c) {
|
||||
not c.isFromUninstantiatedTemplate(_) and
|
||||
exists(Class mid |
|
||||
c.isConstructedFrom(mid)
|
||||
or
|
||||
not c.isConstructedFrom(_) and c = mid
|
||||
|
|
||||
result = getOriginalClassTemplate(mid)
|
||||
or
|
||||
not mid instanceof TemplateClass and mid = result
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `c`. */
|
||||
private Class getFullyTemplatedClass(Class c) {
|
||||
// The `Class::getOriginalTemplate` predicate was introduced in CodeQL
|
||||
// version 2.25.6 and the upgrade script leaves the
|
||||
// `class_template_generated_from` extensionals empty if the database
|
||||
// was generated with an older extractor. So we use the old implementation
|
||||
// if the `class_template_generated_from` extensional is empty.
|
||||
if class_template_generated_from(_, _)
|
||||
then result = getFullyTemplatedClassNew(c)
|
||||
else result = getFullyTemplatedClassOld(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is an instantiation of a function template `templateFunc`, or
|
||||
* holds with `f = templateFunc` if `f` is not an instantiation of any function
|
||||
@@ -331,7 +292,7 @@ private predicate isFunctionConstructedFrom(Function f, Function templateFunc) {
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `f`. */
|
||||
private Function getFullyTemplatedFunctionOld(Function f) {
|
||||
Function getFullyTemplatedFunction(Function f) {
|
||||
not f.isFromUninstantiatedTemplate(_) and
|
||||
(
|
||||
exists(Class c, Class templateClass, int i |
|
||||
@@ -345,46 +306,13 @@ private Function getFullyTemplatedFunctionOld(Function f) {
|
||||
)
|
||||
}
|
||||
|
||||
private TemplateFunction getOriginalFunctionTemplate(TemplateFunction tf) {
|
||||
result = tf.getOriginalTemplate()
|
||||
or
|
||||
not exists(tf.getOriginalTemplate()) and
|
||||
result = tf
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `f`. */
|
||||
private Function getFullyTemplatedFunctionNew(Function f) {
|
||||
not f.isFromUninstantiatedTemplate(_) and
|
||||
exists(Function mid |
|
||||
f.isConstructedFrom(mid)
|
||||
or
|
||||
not f.isConstructedFrom(_) and f = mid
|
||||
|
|
||||
result = getOriginalFunctionTemplate(mid)
|
||||
or
|
||||
not mid instanceof TemplateFunction and mid = result
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `f`. */
|
||||
Function getFullyTemplatedFunction(Function f) {
|
||||
// The `Function::getOriginalTemplate` predicate was introduced in CodeQL
|
||||
// version 2.25.6 and the upgrade script leaves the
|
||||
// `function_template_generated_from` extensionals empty if the database
|
||||
// was generated with an older extractor. So we use the old implementation
|
||||
// if the `function_template_generated_from` extensional is empty.
|
||||
if function_template_generated_from(_, _)
|
||||
then result = getFullyTemplatedFunctionNew(f)
|
||||
else result = getFullyTemplatedFunctionOld(f)
|
||||
}
|
||||
|
||||
/** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
|
||||
bindingset[s, t]
|
||||
private string withConst(string s, Type t) {
|
||||
if t.isConst() then result = "const " + s else result = s
|
||||
}
|
||||
|
||||
/** Prefixes `volatile` to `s` if `t` is volatile, or returns `s` otherwise. */
|
||||
/** Prefixes `volatile` to `s` if `t` is const, or returns `s` otherwise. */
|
||||
bindingset[s, t]
|
||||
private string withVolatile(string s, Type t) {
|
||||
if t.isVolatile() then result = "volatile " + s else result = s
|
||||
@@ -562,7 +490,7 @@ pragma[nomagic]
|
||||
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
|
||||
// If there is a declaring type then we start by expanding the function templates
|
||||
exists(Class template |
|
||||
template = getFullyTemplatedClass(f.getDeclaringType()) and
|
||||
isClassConstructedFrom(f.getDeclaringType(), template) and
|
||||
remaining = getNumberOfSupportedClassTemplateArguments(template) and
|
||||
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||
)
|
||||
@@ -574,7 +502,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
|
||||
or
|
||||
exists(string mid, TypeTemplateParameter tp, Class template |
|
||||
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
||||
template = getFullyTemplatedClass(f.getDeclaringType()) and
|
||||
isClassConstructedFrom(f.getDeclaringType(), template) and
|
||||
tp = getSupportedClassTemplateArgument(template, remaining)
|
||||
|
|
||||
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
|
||||
|
||||
@@ -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 @@
|
||||
## 1.6.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.6.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.6.4
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.6.4
|
||||
lastReleaseVersion: 1.6.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.6.5-dev
|
||||
version: 1.6.4-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -51,16 +51,13 @@ models
|
||||
| 50 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
|
||||
| 51 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 52 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 53 | Summary: ; TemplateClass1; true; templateFunction2<U,V>; (U,V); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 54 | Summary: ; TemplateClass1<T>; false; templateFunction<U>; (T,U); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 55 | Summary: ; TemplateClass2<T,U>; true; function; (U,T); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 56 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
|
||||
| 57 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
|
||||
| 58 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
|
||||
| 59 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
|
||||
| 60 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
| 53 | Summary: Azure::Core::IO; BodyStream; true; Read; ; ; Argument[-1]; Argument[*0]; taint; manual |
|
||||
| 54 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
|
||||
| 55 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
|
||||
| 56 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
|
||||
| 57 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
edges
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:60 |
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:57 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:32 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:32 Sink:MaD:2 |
|
||||
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
|
||||
@@ -69,24 +66,24 @@ edges
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:60 |
|
||||
| azure.cpp:62:10:62:14 | [summary param] this in Value | azure.cpp:62:10:62:14 | [summary] to write: ReturnValue[*] in Value | provenance | MaD:59 |
|
||||
| azure.cpp:113:16:113:19 | [summary param] this in Read | azure.cpp:113:16:113:19 | [summary param] *0 in Read [Return] | provenance | MaD:56 |
|
||||
| azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | azure.cpp:114:16:114:26 | [summary param] *0 in ReadToCount [Return] | provenance | MaD:57 |
|
||||
| azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | provenance | MaD:58 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:57 |
|
||||
| azure.cpp:62:10:62:14 | [summary param] this in Value | azure.cpp:62:10:62:14 | [summary] to write: ReturnValue[*] in Value | provenance | MaD:56 |
|
||||
| azure.cpp:113:16:113:19 | [summary param] this in Read | azure.cpp:113:16:113:19 | [summary param] *0 in Read [Return] | provenance | MaD:53 |
|
||||
| azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | azure.cpp:114:16:114:26 | [summary param] *0 in ReadToCount [Return] | provenance | MaD:54 |
|
||||
| azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | provenance | MaD:55 |
|
||||
| azure.cpp:115:30:115:38 | [summary] to write: ReturnValue.Element in ReadToEnd | azure.cpp:115:30:115:38 | [summary] to write: ReturnValue in ReadToEnd [element] | provenance | |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:253:48:253:60 | *call to GetBodyStream | provenance | Src:MaD:29 |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | |
|
||||
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | |
|
||||
| azure.cpp:257:5:257:8 | *resp | azure.cpp:113:16:113:19 | [summary param] this in Read | provenance | |
|
||||
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:56 |
|
||||
| azure.cpp:257:5:257:8 | *resp | azure.cpp:257:16:257:21 | Read output argument | provenance | MaD:53 |
|
||||
| azure.cpp:257:16:257:21 | Read output argument | azure.cpp:258:10:258:16 | * ... | provenance | |
|
||||
| azure.cpp:262:5:262:8 | *resp | azure.cpp:114:16:114:26 | [summary param] this in ReadToCount | provenance | |
|
||||
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:57 |
|
||||
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument | provenance | MaD:54 |
|
||||
| azure.cpp:262:23:262:28 | ReadToCount output argument | azure.cpp:263:10:263:16 | * ... | provenance | |
|
||||
| azure.cpp:266:38:266:41 | *resp | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | |
|
||||
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:58 |
|
||||
| azure.cpp:266:38:266:41 | *resp | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | MaD:55 |
|
||||
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:266:44:266:52 | call to ReadToEnd [element] | provenance | |
|
||||
| azure.cpp:266:44:266:52 | call to ReadToEnd [element] | azure.cpp:267:10:267:12 | vec [element] | provenance | |
|
||||
| azure.cpp:267:10:267:12 | vec [element] | azure.cpp:267:10:267:12 | vec | provenance | |
|
||||
@@ -103,11 +100,11 @@ edges
|
||||
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:281:68:281:84 | *call to ExtractBodyStream | provenance | Src:MaD:26 |
|
||||
| azure.cpp:281:68:281:84 | *call to ExtractBodyStream | azure.cpp:282:21:282:23 | *call to get | provenance | |
|
||||
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:115:30:115:38 | [summary param] this in ReadToEnd | provenance | |
|
||||
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:58 |
|
||||
| azure.cpp:282:21:282:23 | *call to get | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | MaD:55 |
|
||||
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:10:282:38 | call to ReadToEnd | provenance | |
|
||||
| azure.cpp:282:28:282:36 | call to ReadToEnd [element] | azure.cpp:282:28:282:36 | call to ReadToEnd [element] | provenance | |
|
||||
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:62:10:62:14 | [summary param] this in Value | provenance | |
|
||||
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:59 |
|
||||
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value | provenance | MaD:56 |
|
||||
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:24:289:56 | call to GetHeader | provenance | |
|
||||
| azure.cpp:289:32:289:40 | call to GetHeader | azure.cpp:289:32:289:40 | call to GetHeader | provenance | Src:MaD:30 |
|
||||
| azure.cpp:289:63:289:65 | call to Value | azure.cpp:289:63:289:65 | call to Value | provenance | |
|
||||
@@ -183,39 +180,6 @@ edges
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:48 |
|
||||
| test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | provenance | MaD:54 |
|
||||
| test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | provenance | MaD:53 |
|
||||
| test.cpp:133:10:133:18 | call to ymlSource | test.cpp:133:10:133:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:133:10:133:18 | call to ymlSource | test.cpp:134:45:134:45 | x | provenance | |
|
||||
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:134:13:134:43 | call to templateFunction | provenance | |
|
||||
| test.cpp:134:13:134:43 | call to templateFunction | test.cpp:135:10:135:10 | y | provenance | Sink:MaD:1 |
|
||||
| test.cpp:134:45:134:45 | x | test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | provenance | |
|
||||
| test.cpp:134:45:134:45 | x | test.cpp:134:13:134:43 | call to templateFunction | provenance | MaD:54 |
|
||||
| test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | provenance | MaD:55 |
|
||||
| test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | provenance | MaD:55 |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:146:10:146:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | test.cpp:148:26:148:26 | x | provenance | |
|
||||
| test.cpp:148:10:148:27 | call to function | test.cpp:148:10:148:27 | call to function | provenance | |
|
||||
| test.cpp:148:10:148:27 | call to function | test.cpp:149:10:149:10 | z | provenance | Sink:MaD:1 |
|
||||
| test.cpp:148:26:148:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | provenance | |
|
||||
| test.cpp:148:26:148:26 | x | test.cpp:148:10:148:27 | call to function | provenance | MaD:55 |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:155:10:155:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | test.cpp:157:26:157:26 | x | provenance | |
|
||||
| test.cpp:157:13:157:20 | call to function | test.cpp:157:13:157:20 | call to function | provenance | |
|
||||
| test.cpp:157:13:157:20 | call to function | test.cpp:158:10:158:10 | z | provenance | Sink:MaD:1 |
|
||||
| test.cpp:157:26:157:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | provenance | |
|
||||
| test.cpp:157:26:157:26 | x | test.cpp:157:13:157:20 | call to function | provenance | MaD:55 |
|
||||
| test.cpp:164:34:164:34 | x | test.cpp:165:69:165:69 | x | provenance | |
|
||||
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:164:7:164:7 | *templateFunction3 | provenance | |
|
||||
| test.cpp:165:12:165:64 | call to templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | |
|
||||
| test.cpp:165:69:165:69 | x | test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | provenance | |
|
||||
| test.cpp:165:69:165:69 | x | test.cpp:165:12:165:64 | call to templateFunction2 | provenance | MaD:53 |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:170:10:170:18 | call to ymlSource | provenance | Src:MaD:25 |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | test.cpp:172:51:172:51 | x | provenance | |
|
||||
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | |
|
||||
| test.cpp:172:13:172:44 | call to templateFunction3 | test.cpp:173:10:173:10 | y | provenance | Sink:MaD:1 |
|
||||
| test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | provenance | |
|
||||
| test.cpp:172:51:172:51 | x | test.cpp:172:13:172:44 | call to templateFunction3 | provenance | MaD:53 |
|
||||
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:33 |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
|
||||
@@ -519,43 +483,6 @@ nodes
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
|
||||
| test.cpp:118:44:118:44 | *x | semmle.label | *x |
|
||||
| test.cpp:119:10:119:11 | y2 | semmle.label | y2 |
|
||||
| test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | semmle.label | [summary param] 0 in templateFunction |
|
||||
| test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | semmle.label | [summary] to write: ReturnValue in templateFunction |
|
||||
| test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | semmle.label | [summary param] 1 in templateFunction2 |
|
||||
| test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | semmle.label | [summary] to write: ReturnValue in templateFunction2 |
|
||||
| test.cpp:133:10:133:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:133:10:133:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:134:13:134:43 | call to templateFunction | semmle.label | call to templateFunction |
|
||||
| test.cpp:134:13:134:43 | call to templateFunction | semmle.label | call to templateFunction |
|
||||
| test.cpp:134:45:134:45 | x | semmle.label | x |
|
||||
| test.cpp:135:10:135:10 | y | semmle.label | y |
|
||||
| test.cpp:140:4:140:11 | [summary param] 1 in function | semmle.label | [summary param] 1 in function |
|
||||
| test.cpp:140:4:140:11 | [summary param] 1 in function | semmle.label | [summary param] 1 in function |
|
||||
| test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | semmle.label | [summary] to write: ReturnValue in function |
|
||||
| test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | semmle.label | [summary] to write: ReturnValue in function |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:148:10:148:27 | call to function | semmle.label | call to function |
|
||||
| test.cpp:148:10:148:27 | call to function | semmle.label | call to function |
|
||||
| test.cpp:148:26:148:26 | x | semmle.label | x |
|
||||
| test.cpp:149:10:149:10 | z | semmle.label | z |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:157:13:157:20 | call to function | semmle.label | call to function |
|
||||
| test.cpp:157:13:157:20 | call to function | semmle.label | call to function |
|
||||
| test.cpp:157:26:157:26 | x | semmle.label | x |
|
||||
| test.cpp:158:10:158:10 | z | semmle.label | z |
|
||||
| test.cpp:164:7:164:7 | *templateFunction3 | semmle.label | *templateFunction3 |
|
||||
| test.cpp:164:34:164:34 | x | semmle.label | x |
|
||||
| test.cpp:165:12:165:64 | call to templateFunction2 | semmle.label | call to templateFunction2 |
|
||||
| test.cpp:165:12:165:64 | call to templateFunction2 | semmle.label | call to templateFunction2 |
|
||||
| test.cpp:165:69:165:69 | x | semmle.label | x |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:172:13:172:44 | call to templateFunction3 | semmle.label | call to templateFunction3 |
|
||||
| test.cpp:172:13:172:44 | call to templateFunction3 | semmle.label | call to templateFunction3 |
|
||||
| test.cpp:172:51:172:51 | x | semmle.label | x |
|
||||
| test.cpp:173:10:173:10 | y | semmle.label | y |
|
||||
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
|
||||
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
|
||||
@@ -761,11 +688,6 @@ subpaths
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
|
||||
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate |
|
||||
| test.cpp:134:45:134:45 | x | test.cpp:125:5:125:20 | [summary param] 0 in templateFunction | test.cpp:125:5:125:20 | [summary] to write: ReturnValue in templateFunction | test.cpp:134:13:134:43 | call to templateFunction |
|
||||
| test.cpp:148:26:148:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | test.cpp:148:10:148:27 | call to function |
|
||||
| test.cpp:157:26:157:26 | x | test.cpp:140:4:140:11 | [summary param] 1 in function | test.cpp:140:4:140:11 | [summary] to write: ReturnValue in function | test.cpp:157:13:157:20 | call to function |
|
||||
| test.cpp:165:69:165:69 | x | test.cpp:128:5:128:21 | [summary param] 1 in templateFunction2 | test.cpp:128:5:128:21 | [summary] to write: ReturnValue in templateFunction2 | test.cpp:165:12:165:64 | call to templateFunction2 |
|
||||
| test.cpp:172:51:172:51 | x | test.cpp:164:34:164:34 | x | test.cpp:164:7:164:7 | *templateFunction3 | test.cpp:172:13:172:44 | call to templateFunction3 |
|
||||
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |
|
||||
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument |
|
||||
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument |
|
||||
|
||||
@@ -18,7 +18,4 @@ extensions:
|
||||
- ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
- ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]
|
||||
- ["", "TemplateClass1<T>", False, "templateFunction<U>", "(T,U)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["", "TemplateClass1", True, "templateFunction2<U,V>", "(U,V)", "", "Argument[1]", "ReturnValue", "value", "manual"]
|
||||
- ["", "TemplateClass2<T,U>", True, "function", "(U,T)", "", "Argument[1]", "ReturnValue", "value", "manual"]
|
||||
- ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]
|
||||
@@ -15,7 +15,3 @@
|
||||
| test.cpp:89:11:89:11 | y | test-sink |
|
||||
| test.cpp:116:10:116:11 | y1 | test-sink |
|
||||
| test.cpp:119:10:119:11 | y2 | test-sink |
|
||||
| test.cpp:135:10:135:10 | y | test-sink |
|
||||
| test.cpp:149:10:149:10 | z | test-sink |
|
||||
| test.cpp:158:10:158:10 | z | test-sink |
|
||||
| test.cpp:173:10:173:10 | y | test-sink |
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
| test.cpp:56:8:56:16 | call to ymlSource | local |
|
||||
| test.cpp:94:10:94:18 | call to ymlSource | local |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | local |
|
||||
| test.cpp:133:10:133:18 | call to ymlSource | local |
|
||||
| test.cpp:146:10:146:18 | call to ymlSource | local |
|
||||
| test.cpp:155:10:155:18 | call to ymlSource | local |
|
||||
| test.cpp:170:10:170:18 | call to ymlSource | local |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
|
||||
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
|
||||
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |
|
||||
|
||||
@@ -118,57 +118,3 @@ void test_callWithNonTypeTemplate() {
|
||||
int y2 = callWithNonTypeTemplate<int, 10>(x);
|
||||
ymlSink(y2); // $ ir
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct TemplateClass1 {
|
||||
template<class U>
|
||||
U templateFunction(T, U);
|
||||
|
||||
template<class U, class V>
|
||||
V templateFunction2(U, V);
|
||||
};
|
||||
|
||||
void test_template_function_in_template_class() {
|
||||
TemplateClass1<int> b;
|
||||
int x = ymlSource();
|
||||
auto y = b.templateFunction<unsigned long>(x, 0UL);
|
||||
ymlSink(y); // $ ir
|
||||
}
|
||||
|
||||
template<class S, class T>
|
||||
struct TemplateClass2 {
|
||||
T function(T, S);
|
||||
};
|
||||
|
||||
template<class V> using PartialInstantiationOfTemplateClass2 = TemplateClass2<int, V>;
|
||||
|
||||
void test_partial_class_instantiation() {
|
||||
int x = ymlSource();
|
||||
PartialInstantiationOfTemplateClass2<unsigned long> y;
|
||||
int z = y.function(0UL, x);
|
||||
ymlSink(z); // $ ir
|
||||
}
|
||||
|
||||
template<class V> struct DeriveFromFromPartialTemplateInstantiation : TemplateClass2<int, V> { };
|
||||
|
||||
void test_inheritance() {
|
||||
int x = ymlSource();
|
||||
DeriveFromFromPartialTemplateInstantiation<long> y;
|
||||
auto z = y.function(0L, x);
|
||||
ymlSink(z); // $ ir
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct Class1 : TemplateClass1<T> {
|
||||
template<class U>
|
||||
int templateFunction3(U u, int x) {
|
||||
return TemplateClass1<T>::template templateFunction2<U, int>(u, x);
|
||||
}
|
||||
};
|
||||
|
||||
void test_class1() {
|
||||
int x = ymlSource();
|
||||
Class1<int> c;
|
||||
auto y = c.templateFunction3<unsigned long>(0UL, x);
|
||||
ymlSink(y); // $ ir
|
||||
}
|
||||
@@ -27383,55 +27383,54 @@ getParameterTypeName
|
||||
| stl.h:91:24:91:33 | operator++ | 0 | int |
|
||||
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
|
||||
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
|
||||
| stl.h:147:12:147:23 | basic_string | 0 | const class:2 & |
|
||||
| stl.h:148:3:148:14 | basic_string | 0 | const class:0 * |
|
||||
| stl.h:148:3:148:14 | basic_string | 1 | const class:2 & |
|
||||
| stl.h:149:33:149:44 | basic_string | 0 | func:0 |
|
||||
| stl.h:149:33:149:44 | basic_string | 1 | func:0 |
|
||||
| stl.h:149:33:149:44 | basic_string | 2 | const class:2 & |
|
||||
| stl.h:165:8:165:16 | push_back | 0 | class:0 |
|
||||
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & |
|
||||
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * |
|
||||
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & |
|
||||
| stl.h:151:16:151:20 | c_str | 0 | func:0 |
|
||||
| stl.h:151:16:151:20 | c_str | 1 | func:0 |
|
||||
| stl.h:151:16:151:20 | c_str | 2 | const class:2 & |
|
||||
| stl.h:173:13:173:22 | operator[] | 0 | size_type |
|
||||
| stl.h:175:13:175:14 | at | 0 | size_type |
|
||||
| stl.h:176:35:176:44 | operator+= | 0 | const func:0 & |
|
||||
| stl.h:176:35:176:44 | operator+= | 0 | const func:0 & |
|
||||
| stl.h:177:17:177:26 | operator+= | 0 | const class:0 * |
|
||||
| stl.h:178:17:178:22 | append | 0 | const basic_string & |
|
||||
| stl.h:179:17:179:22 | append | 0 | const class:0 * |
|
||||
| stl.h:180:17:180:22 | append | 0 | size_type |
|
||||
| stl.h:180:17:180:22 | append | 1 | class:0 |
|
||||
| stl.h:181:47:181:52 | append | 0 | func:0 |
|
||||
| stl.h:181:47:181:52 | append | 1 | func:0 |
|
||||
| stl.h:182:17:182:22 | assign | 0 | const basic_string & |
|
||||
| stl.h:183:17:183:22 | assign | 0 | size_type |
|
||||
| stl.h:183:17:183:22 | assign | 1 | class:0 |
|
||||
| stl.h:184:47:184:52 | assign | 0 | func:0 |
|
||||
| stl.h:184:47:184:52 | assign | 1 | func:0 |
|
||||
| stl.h:185:17:185:22 | insert | 0 | size_type |
|
||||
| stl.h:185:17:185:22 | insert | 1 | const basic_string & |
|
||||
| stl.h:176:35:176:44 | operator+= | 0 | size_type |
|
||||
| stl.h:176:35:176:44 | operator+= | 0 | size_type |
|
||||
| stl.h:177:17:177:26 | operator+= | 0 | const func:0 & |
|
||||
| stl.h:178:17:178:22 | append | 0 | const class:0 * |
|
||||
| stl.h:179:17:179:22 | append | 0 | const basic_string & |
|
||||
| stl.h:180:17:180:22 | append | 0 | const class:0 * |
|
||||
| stl.h:181:47:181:52 | append | 0 | size_type |
|
||||
| stl.h:181:47:181:52 | append | 1 | class:0 |
|
||||
| stl.h:182:17:182:22 | assign | 0 | func:0 |
|
||||
| stl.h:182:17:182:22 | assign | 1 | func:0 |
|
||||
| stl.h:183:17:183:22 | assign | 0 | const basic_string & |
|
||||
| stl.h:184:47:184:52 | assign | 0 | size_type |
|
||||
| stl.h:184:47:184:52 | assign | 1 | class:0 |
|
||||
| stl.h:185:17:185:22 | insert | 0 | func:0 |
|
||||
| stl.h:185:17:185:22 | insert | 1 | func:0 |
|
||||
| stl.h:186:17:186:22 | insert | 0 | size_type |
|
||||
| stl.h:186:17:186:22 | insert | 1 | size_type |
|
||||
| stl.h:186:17:186:22 | insert | 2 | class:0 |
|
||||
| stl.h:186:17:186:22 | insert | 1 | const basic_string & |
|
||||
| stl.h:187:17:187:22 | insert | 0 | size_type |
|
||||
| stl.h:187:17:187:22 | insert | 1 | const class:0 * |
|
||||
| stl.h:188:12:188:17 | insert | 0 | const_iterator |
|
||||
| stl.h:188:12:188:17 | insert | 1 | size_type |
|
||||
| stl.h:188:12:188:17 | insert | 2 | class:0 |
|
||||
| stl.h:187:17:187:22 | insert | 1 | size_type |
|
||||
| stl.h:187:17:187:22 | insert | 2 | class:0 |
|
||||
| stl.h:188:12:188:17 | insert | 0 | size_type |
|
||||
| stl.h:188:12:188:17 | insert | 1 | const class:0 * |
|
||||
| stl.h:189:42:189:47 | insert | 0 | const_iterator |
|
||||
| stl.h:189:42:189:47 | insert | 1 | func:0 |
|
||||
| stl.h:189:42:189:47 | insert | 2 | func:0 |
|
||||
| stl.h:190:17:190:23 | replace | 0 | size_type |
|
||||
| stl.h:190:17:190:23 | replace | 1 | size_type |
|
||||
| stl.h:190:17:190:23 | replace | 2 | const basic_string & |
|
||||
| stl.h:189:42:189:47 | insert | 1 | size_type |
|
||||
| stl.h:189:42:189:47 | insert | 2 | class:0 |
|
||||
| stl.h:190:17:190:23 | replace | 0 | const_iterator |
|
||||
| stl.h:190:17:190:23 | replace | 1 | func:0 |
|
||||
| stl.h:190:17:190:23 | replace | 2 | func:0 |
|
||||
| stl.h:191:17:191:23 | replace | 0 | size_type |
|
||||
| stl.h:191:17:191:23 | replace | 1 | size_type |
|
||||
| stl.h:191:17:191:23 | replace | 2 | size_type |
|
||||
| stl.h:191:17:191:23 | replace | 3 | class:0 |
|
||||
| stl.h:192:13:192:16 | copy | 0 | class:0 * |
|
||||
| stl.h:191:17:191:23 | replace | 2 | const basic_string & |
|
||||
| stl.h:192:13:192:16 | copy | 0 | size_type |
|
||||
| stl.h:192:13:192:16 | copy | 1 | size_type |
|
||||
| stl.h:192:13:192:16 | copy | 2 | size_type |
|
||||
| stl.h:194:16:194:21 | substr | 0 | size_type |
|
||||
| stl.h:194:16:194:21 | substr | 1 | size_type |
|
||||
| stl.h:195:8:195:11 | swap | 0 | basic_string & |
|
||||
| stl.h:192:13:192:16 | copy | 3 | class:0 |
|
||||
| stl.h:193:8:193:12 | clear | 0 | class:0 * |
|
||||
| stl.h:193:8:193:12 | clear | 1 | size_type |
|
||||
| stl.h:193:8:193:12 | clear | 2 | size_type |
|
||||
| stl.h:195:8:195:11 | swap | 0 | size_type |
|
||||
| stl.h:195:8:195:11 | swap | 1 | size_type |
|
||||
| stl.h:198:94:198:102 | operator+ | 0 | const basic_string & |
|
||||
| stl.h:198:94:198:102 | operator+ | 1 | const basic_string & |
|
||||
| stl.h:199:94:199:102 | operator+ | 0 | const basic_string & |
|
||||
|
||||
@@ -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>();
|
||||
};
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
if (!EnumerateFiles.TryGetValue(dir, out var str))
|
||||
throw new ArgumentException("Missing EnumerateFiles " + dir);
|
||||
|
||||
return str.Split("\n").Select(p => PathJoin(dir, p));
|
||||
return str.Split("\n").Select(p => PathCombine(dir, p));
|
||||
}
|
||||
|
||||
public IDictionary<string, string> EnumerateDirectories { get; } = new Dictionary<string, string>();
|
||||
@@ -147,7 +147,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
|
||||
return string.IsNullOrEmpty(str)
|
||||
? Enumerable.Empty<string>()
|
||||
: str.Split("\n").Select(p => PathJoin(dir, p));
|
||||
: str.Split("\n").Select(p => PathCombine(dir, p));
|
||||
}
|
||||
|
||||
public bool IsWindows { get; set; }
|
||||
@@ -170,7 +170,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
|
||||
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
||||
|
||||
public string PathJoin(params string[] parts)
|
||||
public string PathCombine(params string[] parts)
|
||||
{
|
||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
=> WithDotNet(builder, ensureDotNetAvailable: false, (_, env) => f(env));
|
||||
|
||||
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
||||
dotNetPath is not null ? actions.PathJoin(dotNetPath, "dotnet") : "dotnet";
|
||||
dotNetPath is not null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
||||
|
||||
private static CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
|
||||
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
||||
|
||||
string IBuildActions.PathJoin(params string[] parts)
|
||||
string IBuildActions.PathCombine(params string[] parts)
|
||||
{
|
||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// </summary>
|
||||
/// <param name="path">The relative path.</param>
|
||||
/// <returns>True iff the path was found.</returns>
|
||||
public bool HasRelativePath(string path) => HasPath(Actions.PathJoin(RootDirectory, path));
|
||||
public bool HasRelativePath(string path) => HasPath(Actions.PathCombine(RootDirectory, path));
|
||||
|
||||
/// <summary>
|
||||
/// List of project/solution files to build.
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Semmle.Autobuild.Shared
|
||||
yield break;
|
||||
|
||||
// Attempt to use vswhere to find installations of Visual Studio
|
||||
var vswhere = actions.PathJoin(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
||||
var vswhere = actions.PathCombine(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
||||
|
||||
if (actions.FileExists(vswhere))
|
||||
{
|
||||
@@ -51,14 +51,14 @@ namespace Semmle.Autobuild.Shared
|
||||
if (majorVersion < 15)
|
||||
{
|
||||
// Visual Studio 2015 and below
|
||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Visual Studio 2017 and above
|
||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
|
||||
}
|
||||
}
|
||||
// else: Skip installation without a version
|
||||
@@ -68,10 +68,10 @@ namespace Semmle.Autobuild.Shared
|
||||
}
|
||||
|
||||
// vswhere not installed or didn't run correctly - return legacy Visual Studio versions
|
||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
|
||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
|
||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
|
||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
|
||||
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Semmle.Autobuild.Shared
|
||||
// Use `nuget.exe` from source code repo, if present, otherwise first attempt with global
|
||||
// `nuget` command, and if that fails, attempt to download `nuget.exe` from nuget.org
|
||||
var nuget = builder.GetFilename("nuget.exe").Select(t => t.Item1).FirstOrDefault() ?? "nuget";
|
||||
var nugetDownloadPath = builder.Actions.PathJoin(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
|
||||
var nugetDownloadPath = builder.Actions.PathCombine(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
|
||||
var nugetDownloaded = false;
|
||||
|
||||
var ret = BuildScript.Success;
|
||||
|
||||
@@ -107,9 +107,8 @@ namespace Semmle.Autobuild.Shared
|
||||
continue;
|
||||
}
|
||||
|
||||
var includePath = builder.Actions.PathJoin(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
||||
var path = Path.IsPathRooted(includePath) ? includePath : builder.Actions.PathJoin(DirectoryName, includePath);
|
||||
ret.Add(new Project<TAutobuildOptions>(builder, path));
|
||||
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
||||
ret.Add(new Project<TAutobuildOptions>(builder, builder.Actions.PathCombine(DirectoryName, includePath)));
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
includedProjects = solution.ProjectsInOrder
|
||||
.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
|
||||
.Select(p => builder.Actions.PathJoin(DirectoryName, builder.Actions.PathJoin(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
|
||||
.Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
|
||||
.Select(p => new Project<TAutobuildOptions>(builder, p))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return;
|
||||
}
|
||||
|
||||
var path = Path.Join(p, ParseFilePath(d));
|
||||
var path = Path.Combine(p, ParseFilePath(d));
|
||||
Paths.Add(path);
|
||||
Packages.Add(GetPackageName(p));
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
this.diagnosticsWriter = new DiagnosticsStream(Path.Join(
|
||||
this.diagnosticsWriter = new DiagnosticsStream(Path.Combine(
|
||||
diagDirEnv ?? "",
|
||||
$"dependency-manager-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc"));
|
||||
this.sourceDir = new DirectoryInfo(srcDir);
|
||||
@@ -327,7 +327,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
private void RemoveNugetPackageReference(string packagePrefix, ISet<AssemblyLookupLocation> dllLocations)
|
||||
{
|
||||
var packageFolder = nugetPackageRestorer.PackageDirectory.DirInfo.FullName.ToLowerInvariant();
|
||||
var packagePathPrefix = Path.Join(packageFolder, packagePrefix.ToLowerInvariant());
|
||||
var packagePathPrefix = Path.Combine(packageFolder, packagePrefix.ToLowerInvariant());
|
||||
var toRemove = dllLocations.Where(s => s.Path.StartsWith(packagePathPrefix, StringComparison.InvariantCultureIgnoreCase));
|
||||
foreach (var path in toRemove)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Join(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
|
||||
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
|
||||
|
||||
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, bool runDotnetInfo) => new DotNet(dotnetCliInvoker, logger, runDotnetInfo);
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var path = ".empty";
|
||||
if (tempWorkingDirectory != null)
|
||||
{
|
||||
path = Path.Join(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
|
||||
path = Path.Combine(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
else
|
||||
{
|
||||
var dotnetInstallPath = actions.PathJoin(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
|
||||
var dotnetInstallPath = actions.PathCombine(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
|
||||
var downloadDotNetInstallSh = BuildScript.DownloadFile(
|
||||
"https://dot.net/v1/dotnet-install.sh",
|
||||
dotnetInstallPath,
|
||||
@@ -339,7 +339,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
};
|
||||
}
|
||||
|
||||
var dotnetInfo = InfoScript(actions, actions.PathJoin(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
|
||||
var dotnetInfo = InfoScript(actions, actions.PathCombine(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
|
||||
|
||||
Func<string, BuildScript> getInstallAndVerify = version =>
|
||||
// run `dotnet --info` after install, to check that it executes successfully
|
||||
@@ -384,7 +384,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
|
||||
{
|
||||
var installDir = actions.PathJoin(tempWorkingDirectory, ".dotnet");
|
||||
var installDir = actions.PathCombine(tempWorkingDirectory, ".dotnet");
|
||||
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
|
||||
return BuildScript.Bind(installScript, installed =>
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
private string FullVersion =>
|
||||
version.ToString();
|
||||
|
||||
public string FullPath => Path.Join(dir, FullVersion);
|
||||
public string FullPath => Path.Combine(dir, FullVersion);
|
||||
|
||||
/**
|
||||
* The full path to the reference assemblies for this runtime.
|
||||
@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
directories[^2] = "packs";
|
||||
directories[^1] = $"{directories[^1]}.Ref";
|
||||
return Path.Join(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
|
||||
return Path.Combine(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage the downloading of NuGet packages with nuget.exe.
|
||||
/// Locates packages in a source tree and downloads all of the
|
||||
/// referenced assemblies to a temp folder.
|
||||
/// </summary>
|
||||
internal class NugetExeWrapper : IDisposable
|
||||
{
|
||||
private readonly string? nugetExe;
|
||||
private readonly Semmle.Util.Logging.ILogger logger;
|
||||
|
||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
||||
|
||||
private readonly string? backupNugetConfig;
|
||||
private readonly string? nugetConfigPath;
|
||||
private readonly FileProvider fileProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The packages directory.
|
||||
/// This will be in the user-specified or computed Temp location
|
||||
/// so as to not trample the source tree.
|
||||
/// </summary>
|
||||
private readonly DependencyDirectory packageDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// Create the package manager for a specified source tree.
|
||||
/// </summary>
|
||||
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
||||
{
|
||||
this.fileProvider = fileProvider;
|
||||
this.packageDirectory = packageDirectory;
|
||||
this.logger = logger;
|
||||
|
||||
if (fileProvider.PackagesConfigs.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
|
||||
nugetExe = ResolveNugetExe();
|
||||
if (HasNoPackageSource() && useDefaultFeed())
|
||||
{
|
||||
// We only modify or add a top level nuget.config file
|
||||
nugetConfigPath = Path.Combine(fileProvider.SourceDir.FullName, "nuget.config");
|
||||
try
|
||||
{
|
||||
if (File.Exists(nugetConfigPath))
|
||||
{
|
||||
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
|
||||
|
||||
do
|
||||
{
|
||||
backupNugetConfig = Path.Combine(tempFolderPath, Path.GetRandomFileName());
|
||||
}
|
||||
while (File.Exists(backupNugetConfig));
|
||||
File.Copy(nugetConfigPath, backupNugetConfig, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText(nugetConfigPath,
|
||||
"""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
</packageSources>
|
||||
</configuration>
|
||||
""");
|
||||
}
|
||||
AddDefaultPackageSource(nugetConfigPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find the location of `nuget.exe`. It looks for
|
||||
/// - the environment variable specifying a location,
|
||||
/// - files in the repository,
|
||||
/// - tries to resolve nuget from the PATH, or
|
||||
/// - downloads it if it is not found.
|
||||
/// </summary>
|
||||
private string ResolveNugetExe()
|
||||
{
|
||||
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
|
||||
if (!string.IsNullOrEmpty(envVarPath))
|
||||
{
|
||||
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
|
||||
return envVarPath;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
|
||||
}
|
||||
|
||||
var nugetExesInRepo = fileProvider.NugetExes;
|
||||
if (nugetExesInRepo.Count > 1)
|
||||
{
|
||||
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
|
||||
}
|
||||
|
||||
if (nugetExesInRepo.Count > 0)
|
||||
{
|
||||
var path = nugetExesInRepo.First();
|
||||
logger.LogInfo($"Using nuget.exe from path '{path}'");
|
||||
return path;
|
||||
}
|
||||
|
||||
var executableName = Win32.IsWindows() ? "nuget.exe" : "nuget";
|
||||
var nugetPath = FileUtils.FindProgramOnPath(executableName);
|
||||
if (nugetPath is not null)
|
||||
{
|
||||
nugetPath = Path.Combine(nugetPath, executableName);
|
||||
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
|
||||
return nugetPath;
|
||||
}
|
||||
|
||||
throw new Exception("Could not find or download nuget.exe.");
|
||||
}
|
||||
|
||||
private string DownloadNugetExe(string sourceDir)
|
||||
{
|
||||
var directory = Path.Combine(sourceDir, ".nuget");
|
||||
var nuget = Path.Combine(directory, "nuget.exe");
|
||||
|
||||
// Nuget.exe already exists in the .nuget directory.
|
||||
if (File.Exists(nuget))
|
||||
{
|
||||
logger.LogInfo($"Found nuget.exe at {nuget}");
|
||||
return nuget;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(directory);
|
||||
logger.LogInfo("Attempting to download nuget.exe");
|
||||
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
|
||||
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
||||
return nuget;
|
||||
}
|
||||
|
||||
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
||||
|
||||
/// <summary>
|
||||
/// Restore all packages in the specified packages.config file.
|
||||
/// </summary>
|
||||
/// <param name="packagesConfig">The packages.config file.</param>
|
||||
private bool TryRestoreNugetPackage(string packagesConfig)
|
||||
{
|
||||
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
|
||||
|
||||
/* Use nuget.exe to install a package.
|
||||
* Note that there is a clutch of NuGet assemblies which could be used to
|
||||
* invoke this directly, which would arguably be nicer. However they are
|
||||
* really unwieldy and this solution works for now.
|
||||
*/
|
||||
|
||||
string exe, args;
|
||||
if (RunWithMono)
|
||||
{
|
||||
exe = "mono";
|
||||
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
exe = nugetExe!;
|
||||
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||
}
|
||||
|
||||
var pi = new ProcessStartInfo(exe, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
var threadId = Environment.CurrentManagedThreadId;
|
||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||
void onError(string s) => logger.LogError(s, threadId);
|
||||
var exitCode = pi.ReadOutput(out _, onOut, onError);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInfo($"Restored file \"{packagesConfig}\"");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the packages to the temp folder.
|
||||
/// </summary>
|
||||
public int InstallPackages()
|
||||
{
|
||||
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
|
||||
}
|
||||
|
||||
private bool HasNoPackageSource()
|
||||
{
|
||||
if (Win32.IsWindows())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
logger.LogInfo("Checking if default package source is available...");
|
||||
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
|
||||
if (stdout.All(line => line != "No sources found."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning($"Failed to check if default package source is added: {e}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RunMonoNugetCommand(string command, out IList<string> stdout)
|
||||
{
|
||||
string exe, args;
|
||||
if (RunWithMono)
|
||||
{
|
||||
exe = "mono";
|
||||
args = $"\"{nugetExe}\" {command}";
|
||||
}
|
||||
else
|
||||
{
|
||||
exe = nugetExe!;
|
||||
args = command;
|
||||
}
|
||||
|
||||
var pi = new ProcessStartInfo(exe, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
var threadId = Environment.CurrentManagedThreadId;
|
||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||
void onError(string s) => logger.LogError(s, threadId);
|
||||
pi.ReadOutput(out stdout, onOut, onError);
|
||||
}
|
||||
|
||||
private void AddDefaultPackageSource(string nugetConfig)
|
||||
{
|
||||
logger.LogInfo("Adding default package source...");
|
||||
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (nugetConfigPath is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (backupNugetConfig is null)
|
||||
{
|
||||
logger.LogInfo("Removing nuget.config file");
|
||||
File.Delete(nugetConfigPath);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogInfo("Reverting nuget.config file content");
|
||||
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
|
||||
using (var backup = File.OpenRead(backupNugetConfig))
|
||||
using (var current = File.OpenWrite(nugetConfigPath))
|
||||
{
|
||||
current.SetLength(0); // Truncate file
|
||||
backup.CopyTo(current); // Restore original content
|
||||
}
|
||||
|
||||
logger.LogInfo("Deleting backup nuget.config file");
|
||||
File.Delete(backupNugetConfig);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
logger.LogError($"Failed to restore original nuget.config file: {exc}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,13 +161,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
reachableFeeds.UnionWith(reachableInheritedFeeds);
|
||||
}
|
||||
|
||||
using (var packagesConfigRestore = PackagesConfigRestoreFactory.Create(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
|
||||
using (var nuget = new NugetExeWrapper(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
|
||||
{
|
||||
var count = packagesConfigRestore.InstallPackages();
|
||||
var count = nuget.InstallPackages();
|
||||
|
||||
if (packagesConfigRestore.PackageCount > 0)
|
||||
if (nuget.PackageCount > 0)
|
||||
{
|
||||
compilationInfoContainer.CompilationInfos.Add(("packages.config files", packagesConfigRestore.PackageCount.ToString()));
|
||||
compilationInfoContainer.CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
|
||||
compilationInfoContainer.CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
var paths = dependencies
|
||||
.Paths
|
||||
.Select(d => Path.Join(PackageDirectory.DirInfo.FullName, d))
|
||||
.Select(d => Path.Combine(PackageDirectory.DirInfo.FullName, d))
|
||||
.ToList();
|
||||
assemblyLookupLocations.UnionWith(paths.Select(p => new AssemblyLookupLocation(p)));
|
||||
|
||||
@@ -527,7 +527,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var sb = new StringBuilder();
|
||||
fallbackNugetFeeds.ForEach((feed, index) => sb.AppendLine($"<add key=\"feed{index}\" value=\"{feed}\" />"));
|
||||
|
||||
var nugetConfigPath = Path.Join(folderPath, "nuget.config");
|
||||
var nugetConfigPath = Path.Combine(folderPath, "nuget.config");
|
||||
logger.LogInfo($"Creating fallback nuget.config file {nugetConfigPath}.");
|
||||
File.WriteAllText(nugetConfigPath,
|
||||
$"""
|
||||
@@ -1052,7 +1052,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
private static string ComputeTempDirectoryPath(string subfolderName)
|
||||
{
|
||||
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
|
||||
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1060,7 +1060,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
|
||||
{
|
||||
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
|
||||
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,368 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
internal interface IPackagesConfigRestore : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of packages.config files found in the source tree.
|
||||
/// </summary>
|
||||
int PackageCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Download the packages to the temp folder.
|
||||
/// </summary>
|
||||
int InstallPackages();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating a package manager to restore NuGet packages referenced in packages.config files.
|
||||
/// If the environment doesn't support using nuget.exe to restore packages from packages.config files, a no-op implementation is returned.
|
||||
/// It is worth noting that for macOS and Linux, nuget.exe is used with mono. However, mono is being deprecated and the last GitHub images
|
||||
/// to contain mono are:
|
||||
/// - Ubuntu 22.04
|
||||
/// - macOS 14
|
||||
///
|
||||
/// If the packages from the packages.config files are not restored with the packages.config restore functionality below, there is a subsequent
|
||||
/// step that still may succeed in restoring the packages without the help of nuget.exe (by attempting to restore using dotnet).
|
||||
/// </summary>
|
||||
internal class PackagesConfigRestoreFactory
|
||||
{
|
||||
public static IPackagesConfigRestore Create(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
||||
{
|
||||
if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMonoInstalled())
|
||||
{
|
||||
return new NugetExeWrapper(fileProvider, packageDirectory, logger, useDefaultFeed);
|
||||
}
|
||||
|
||||
return new NoOpPackagesConfig(fileProvider, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manage the downloading of NuGet packages with nuget.exe.
|
||||
/// Locates packages in a source tree and downloads all of the
|
||||
/// referenced assemblies to a temp folder.
|
||||
/// </summary>
|
||||
private class NugetExeWrapper : IPackagesConfigRestore
|
||||
{
|
||||
private readonly string? nugetExe;
|
||||
private readonly Semmle.Util.Logging.ILogger logger;
|
||||
|
||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
||||
|
||||
private readonly string? backupNugetConfig;
|
||||
private readonly string? nugetConfigPath;
|
||||
private readonly FileProvider fileProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The packages directory.
|
||||
/// This will be in the user-specified or computed Temp location
|
||||
/// so as to not trample the source tree.
|
||||
/// </summary>
|
||||
private readonly DependencyDirectory packageDirectory;
|
||||
|
||||
private bool IsWindows => SystemBuildActions.Instance.IsWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Create the package manager for a specified source tree.
|
||||
/// </summary>
|
||||
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
||||
{
|
||||
this.fileProvider = fileProvider;
|
||||
this.packageDirectory = packageDirectory;
|
||||
this.logger = logger;
|
||||
|
||||
if (fileProvider.PackagesConfigs.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
|
||||
nugetExe = ResolveNugetExe();
|
||||
if (!HasPackageSource() && useDefaultFeed())
|
||||
{
|
||||
// We only modify or add a top level nuget.config file
|
||||
nugetConfigPath = Path.Join(fileProvider.SourceDir.FullName, "nuget.config");
|
||||
try
|
||||
{
|
||||
if (File.Exists(nugetConfigPath))
|
||||
{
|
||||
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
|
||||
|
||||
do
|
||||
{
|
||||
backupNugetConfig = Path.Join(tempFolderPath, Path.GetRandomFileName());
|
||||
}
|
||||
while (File.Exists(backupNugetConfig));
|
||||
File.Copy(nugetConfigPath, backupNugetConfig, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText(nugetConfigPath,
|
||||
"""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
</packageSources>
|
||||
</configuration>
|
||||
""");
|
||||
}
|
||||
AddDefaultPackageSource(nugetConfigPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find the location of `nuget.exe`. It looks for
|
||||
/// - the environment variable specifying a location,
|
||||
/// - files in the repository,
|
||||
/// - tries to resolve nuget from the PATH, or
|
||||
/// - downloads it if it is not found.
|
||||
/// </summary>
|
||||
private string ResolveNugetExe()
|
||||
{
|
||||
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
|
||||
if (!string.IsNullOrEmpty(envVarPath))
|
||||
{
|
||||
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
|
||||
return envVarPath;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
|
||||
}
|
||||
|
||||
var nugetExesInRepo = fileProvider.NugetExes;
|
||||
if (nugetExesInRepo.Count > 1)
|
||||
{
|
||||
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
|
||||
}
|
||||
|
||||
if (nugetExesInRepo.Count > 0)
|
||||
{
|
||||
var path = nugetExesInRepo.First();
|
||||
logger.LogInfo($"Using nuget.exe from path '{path}'");
|
||||
return path;
|
||||
}
|
||||
|
||||
var executableName = IsWindows ? "nuget.exe" : "nuget";
|
||||
var nugetPath = FileUtils.FindProgramOnPath(executableName);
|
||||
if (nugetPath is not null)
|
||||
{
|
||||
nugetPath = Path.Join(nugetPath, executableName);
|
||||
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
|
||||
return nugetPath;
|
||||
}
|
||||
|
||||
throw new Exception("Could not find or download nuget.exe.");
|
||||
}
|
||||
|
||||
private string DownloadNugetExe(string sourceDir)
|
||||
{
|
||||
var directory = Path.Join(sourceDir, ".nuget");
|
||||
var nuget = Path.Join(directory, "nuget.exe");
|
||||
|
||||
// Nuget.exe already exists in the .nuget directory.
|
||||
if (File.Exists(nuget))
|
||||
{
|
||||
logger.LogInfo($"Found nuget.exe at {nuget}");
|
||||
return nuget;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(directory);
|
||||
logger.LogInfo("Attempting to download nuget.exe");
|
||||
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
|
||||
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
||||
return nuget;
|
||||
}
|
||||
|
||||
private bool RunWithMono => !IsWindows && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
||||
|
||||
/// <summary>
|
||||
/// Restore all packages in the specified packages.config file.
|
||||
/// </summary>
|
||||
/// <param name="packagesConfig">The packages.config file.</param>
|
||||
private bool TryRestoreNugetPackage(string packagesConfig)
|
||||
{
|
||||
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
|
||||
|
||||
/* Use nuget.exe to install a package.
|
||||
* Note that there is a clutch of NuGet assemblies which could be used to
|
||||
* invoke this directly, which would arguably be nicer. However they are
|
||||
* really unwieldy and this solution works for now.
|
||||
*/
|
||||
|
||||
string exe, args;
|
||||
if (RunWithMono)
|
||||
{
|
||||
exe = "mono";
|
||||
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
exe = nugetExe!;
|
||||
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||
}
|
||||
|
||||
var pi = new ProcessStartInfo(exe, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
var threadId = Environment.CurrentManagedThreadId;
|
||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||
void onError(string s) => logger.LogError(s, threadId);
|
||||
var exitCode = pi.ReadOutput(out _, onOut, onError);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInfo($"Restored file \"{packagesConfig}\"");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the packages to the temp folder.
|
||||
/// </summary>
|
||||
public int InstallPackages()
|
||||
{
|
||||
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
|
||||
}
|
||||
|
||||
private bool HasPackageSource()
|
||||
{
|
||||
if (IsWindows)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
logger.LogInfo("Checking if default package source is available...");
|
||||
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
|
||||
if (stdout.All(line => line != "No sources found."))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning($"Failed to check if default package source is added: {e}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void RunMonoNugetCommand(string command, out IList<string> stdout)
|
||||
{
|
||||
string exe, args;
|
||||
if (RunWithMono)
|
||||
{
|
||||
exe = "mono";
|
||||
args = $"\"{nugetExe}\" {command}";
|
||||
}
|
||||
else
|
||||
{
|
||||
exe = nugetExe!;
|
||||
args = command;
|
||||
}
|
||||
|
||||
var pi = new ProcessStartInfo(exe, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
var threadId = Environment.CurrentManagedThreadId;
|
||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||
void onError(string s) => logger.LogError(s, threadId);
|
||||
pi.ReadOutput(out stdout, onOut, onError);
|
||||
}
|
||||
|
||||
private void AddDefaultPackageSource(string nugetConfig)
|
||||
{
|
||||
logger.LogInfo("Adding default package source...");
|
||||
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (nugetConfigPath is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (backupNugetConfig is null)
|
||||
{
|
||||
logger.LogInfo("Removing nuget.config file");
|
||||
File.Delete(nugetConfigPath);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogInfo("Reverting nuget.config file content");
|
||||
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
|
||||
using (var backup = File.OpenRead(backupNugetConfig))
|
||||
using (var current = File.OpenWrite(nugetConfigPath))
|
||||
{
|
||||
current.SetLength(0); // Truncate file
|
||||
backup.CopyTo(current); // Restore original content
|
||||
}
|
||||
|
||||
logger.LogInfo("Deleting backup nuget.config file");
|
||||
File.Delete(backupNugetConfig);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
logger.LogError($"Failed to restore original nuget.config file: {exc}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NoOpPackagesConfig : IPackagesConfigRestore
|
||||
{
|
||||
private readonly Semmle.Util.Logging.ILogger logger;
|
||||
private readonly FileProvider fileProvider;
|
||||
|
||||
public NoOpPackagesConfig(FileProvider fileProvider, Semmle.Util.Logging.ILogger logger)
|
||||
{
|
||||
this.fileProvider = fileProvider;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
||||
|
||||
public int InstallPackages()
|
||||
{
|
||||
if (PackageCount > 0)
|
||||
{
|
||||
logger.LogInfo("Found packages.config files, but nuget.exe cannot be used to restore packages on this platform. Skipping restore of packages.config files.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
|
||||
string[] monoDirs = monoPath is not null
|
||||
? [Path.GetFullPath(Path.Join(monoPath, "..", "lib", "mono")), monoPath]
|
||||
? [Path.GetFullPath(Path.Combine(monoPath, "..", "lib", "mono")), monoPath]
|
||||
: ["/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono"];
|
||||
|
||||
var monoDir = monoDirs.FirstOrDefault(Directory.Exists);
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = Path.Join(version.FullPath, "Roslyn", "bincore", "csc.dll");
|
||||
var path = Path.Combine(version.FullPath, "Roslyn", "bincore", "csc.dll");
|
||||
logger.LogDebug($"Source generator CSC: '{path}'");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
|
||||
@@ -41,10 +41,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
.Replace('\\', '/'); // Ensure we're generating the same hash regardless of the OS
|
||||
var name = FileUtils.ComputeHash($"{relativePathToCsProj}\n{this.GetType().Name}");
|
||||
using var tempDir = new TemporaryDirectory(Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), "source-generator"), "source generator temporary", logger);
|
||||
var analyzerConfigPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.txt");
|
||||
var dllPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.dll");
|
||||
var cscArgsPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.rsp");
|
||||
var outputFolder = Path.Join(targetDir, name);
|
||||
var analyzerConfigPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.txt");
|
||||
var dllPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.dll");
|
||||
var cscArgsPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.rsp");
|
||||
var outputFolder = Path.Combine(targetDir, name);
|
||||
Directory.CreateDirectory(outputFolder);
|
||||
logger.LogInfo("Producing analyzer config content.");
|
||||
GenerateAnalyzerConfig(additionalFiles, csprojFile, analyzerConfigPath);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
throw new Exception("No SDK path available.");
|
||||
}
|
||||
|
||||
SourceGeneratorFolder = Path.Join(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
|
||||
SourceGeneratorFolder = Path.Combine(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
|
||||
this.logger.LogInfo($"Razor source generator folder: {SourceGeneratorFolder}");
|
||||
if (!Directory.Exists(SourceGeneratorFolder))
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
if (usings.Count > 0)
|
||||
{
|
||||
var tempDir = GetTemporaryWorkingDirectory("implicitUsings");
|
||||
var path = Path.Join(tempDir, "GlobalUsings.g.cs");
|
||||
var path = Path.Combine(tempDir, "GlobalUsings.g.cs");
|
||||
using (var writer = new StreamWriter(path))
|
||||
{
|
||||
writer.WriteLine("// <auto-generated/>");
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var nugetFolder = nugetPackageRestorer.TryRestore("Microsoft.CodeAnalysis.ResxSourceGenerator");
|
||||
if (nugetFolder is not null)
|
||||
{
|
||||
sourceGeneratorFolder = System.IO.Path.Join(nugetFolder, "analyzers", "dotnet", "cs");
|
||||
sourceGeneratorFolder = System.IO.Path.Combine(nugetFolder, "analyzers", "dotnet", "cs");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
protected string GetTemporaryWorkingDirectory(string subfolder)
|
||||
{
|
||||
var temp = Path.Join(tempWorkingDirectory.ToString(), subfolder);
|
||||
var temp = Path.Combine(tempWorkingDirectory.ToString(), subfolder);
|
||||
Directory.CreateDirectory(temp);
|
||||
|
||||
return temp;
|
||||
|
||||
@@ -664,7 +664,7 @@ namespace Semmle.Extraction.CSharp
|
||||
// Find the (possibly unbound) original extension method that maps to this implementation (if any).
|
||||
var unboundDeclaration = extensions.SelectMany(e => e.GetMembers())
|
||||
.OfType<IMethodSymbol>()
|
||||
.FirstOrDefault(m => SymbolEqualityComparer.Default.Equals(m.AssociatedExtensionImplementation?.ConstructedFrom, method.ConstructedFrom));
|
||||
.FirstOrDefault(m => SymbolEqualityComparer.Default.Equals(m.AssociatedExtensionImplementation, method.ConstructedFrom));
|
||||
|
||||
var isFullyConstructed = method.IsBoundGenericMethod();
|
||||
if (isFullyConstructed && unboundDeclaration?.ContainingType is INamedTypeSymbol extensionType)
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
Overrides(trapFile);
|
||||
ExtractRefReturn(trapFile, Symbol, this);
|
||||
|
||||
if (Symbol.FromSource() && !HasBody)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -23,9 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||
}
|
||||
else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }'
|
||||
{
|
||||
var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type));
|
||||
trapFile.catch_type(this, type.TypeRef, true);
|
||||
TypeMention.Create(Context, Stmt.Declaration!.Type, this, type);
|
||||
trapFile.catch_type(this, Type.Create(Context, Context.GetType(Stmt.Declaration!.Type)).TypeRef, true);
|
||||
}
|
||||
else // A catch clause of the form 'catch { ... }'
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Semmle.Extraction.CSharp
|
||||
return;
|
||||
}
|
||||
|
||||
var mscorlibExists = File.Exists(Path.Join(compilerDir, "mscorlib.dll"));
|
||||
var mscorlibExists = File.Exists(Path.Combine(compilerDir, "mscorlib.dll"));
|
||||
|
||||
if (specifiedFramework is null && mscorlibExists)
|
||||
{
|
||||
@@ -107,7 +107,7 @@ namespace Semmle.Extraction.CSharp
|
||||
/// <summary>
|
||||
/// The file csc.rsp.
|
||||
/// </summary>
|
||||
private string CscRsp => Path.Join(FrameworkPath, csc_rsp);
|
||||
private string CscRsp => Path.Combine(FrameworkPath, csc_rsp);
|
||||
|
||||
/// <summary>
|
||||
/// Should we skip extraction?
|
||||
|
||||
@@ -680,7 +680,7 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
try
|
||||
{
|
||||
var fullPath = Path.GetFullPath(Path.Join(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
|
||||
var fullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
|
||||
ExtractionContext.Logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
|
||||
|
||||
mappedToPath = fullPath;
|
||||
|
||||
@@ -159,11 +159,7 @@ namespace Semmle.Extraction.CSharp
|
||||
return null;
|
||||
}
|
||||
|
||||
var normalized = Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file;
|
||||
var path = projDir is not null && !Path.IsPathRooted(normalized)
|
||||
? Path.Join(projDir.FullName, normalized)
|
||||
: normalized;
|
||||
return Path.GetFullPath(path);
|
||||
return Path.GetFullPath(Path.Combine(projDir?.FullName ?? string.Empty, Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file));
|
||||
}
|
||||
|
||||
private readonly string[] references;
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace Semmle.Extraction.CSharp
|
||||
TracingAnalyser.GetOutputName(compilation, args),
|
||||
compilation,
|
||||
generatedSyntaxTrees,
|
||||
Path.Join(compilationIdentifierPath, diagnosticName),
|
||||
Path.Combine(compilationIdentifierPath, diagnosticName),
|
||||
options),
|
||||
() => { });
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace Semmle.Extraction.CSharp
|
||||
else
|
||||
{
|
||||
var composed = referencePaths.Value
|
||||
.Select(path => Path.Join(path, clref.Reference))
|
||||
.Select(path => Path.Combine(path, clref.Reference))
|
||||
.Where(path => File.Exists(path))
|
||||
.Select(path => analyser.PathCache.GetCanonicalPath(path))
|
||||
.FirstOrDefault();
|
||||
@@ -559,13 +559,13 @@ namespace Semmle.Extraction.CSharp
|
||||
/// Gets the path to the `csharp.log` file written to by the C# extractor.
|
||||
/// </summary>
|
||||
public static string GetCSharpLogPath() =>
|
||||
Path.Join(GetCSharpLogDirectory(), "csharp.log");
|
||||
Path.Combine(GetCSharpLogDirectory(), "csharp.log");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to a `csharp.{hash}.txt` file written to by the C# extractor.
|
||||
/// </summary>
|
||||
public static string GetCSharpArgsLogPath(string hash) =>
|
||||
Path.Join(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
|
||||
Path.Combine(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory.
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace Semmle.Extraction.CSharp
|
||||
return Path.ChangeExtension(entryPointFilename, ".exe");
|
||||
}
|
||||
|
||||
return Path.Join(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
|
||||
return Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
|
||||
}
|
||||
|
||||
private int LogDiagnostics()
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp
|
||||
* Although GetRandomFileName() is cryptographically secure,
|
||||
* there's a tiny chance the file could already exists.
|
||||
*/
|
||||
tmpFile = Path.Join(tempPath, Path.GetRandomFileName());
|
||||
tmpFile = Path.Combine(tempPath, Path.GetRandomFileName());
|
||||
}
|
||||
while (File.Exists(tmpFile));
|
||||
|
||||
|
||||
@@ -82,13 +82,13 @@ namespace SemmleTests.Semmle.Util
|
||||
[Fact]
|
||||
public void CanonicalPathMissingFile()
|
||||
{
|
||||
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
|
||||
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanonicalPathMissingAbsolutePath()
|
||||
{
|
||||
Assert.Equal(Path.Join(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Join(root, "no", "such", "file")));
|
||||
Assert.Equal(Path.Combine(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Combine(root, "no", "such", "file")));
|
||||
|
||||
if (Win32.IsWindows())
|
||||
Assert.Equal(@"C:\Windows\no\such\file", cache.GetCanonicalPath(@"C:\windOws\no\such\file"));
|
||||
@@ -97,7 +97,7 @@ namespace SemmleTests.Semmle.Util
|
||||
[Fact]
|
||||
public void CanonicalPathMissingRelativePath()
|
||||
{
|
||||
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Join("NO", "SUCH")));
|
||||
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Combine("NO", "SUCH")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -125,7 +125,7 @@ namespace SemmleTests.Semmle.Util
|
||||
public void CanonicalPathDots()
|
||||
{
|
||||
var abcPath = Path.GetFullPath("abc");
|
||||
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Join("foo", ".", "..", "abc")));
|
||||
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Combine("foo", ".", "..", "abc")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -14,20 +14,20 @@ namespace SemmleTests.Semmle.Util
|
||||
public sealed class LongPaths
|
||||
{
|
||||
private static readonly string tmpDir = Environment.GetEnvironmentVariable("TEST_TMPDIR") ?? Path.GetTempPath();
|
||||
private static readonly string longPathDir = Path.Join(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
private static readonly string longPathDir = Path.Combine(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
"ccccccccccccccccccccccccccccccc", "ddddddddddddddddddddddddddddddddddddd", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "fffffffffffffffffffffffffffffffff",
|
||||
"ggggggggggggggggggggggggggggggggggg", "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
|
||||
|
||||
private static string MakeLongPath()
|
||||
{
|
||||
var uniquePostfix = Guid.NewGuid().ToString("N");
|
||||
return Path.Join(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
|
||||
return Path.Combine(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
|
||||
}
|
||||
|
||||
private static string MakeShortPath()
|
||||
{
|
||||
var uniquePostfix = Guid.NewGuid().ToString("N");
|
||||
return Path.Join(tmpDir, $"test{uniquePostfix}.txt");
|
||||
return Path.Combine(tmpDir, $"test{uniquePostfix}.txt");
|
||||
}
|
||||
|
||||
public LongPaths()
|
||||
@@ -62,7 +62,7 @@ namespace SemmleTests.Semmle.Util
|
||||
[Fact]
|
||||
public void ParentDirectory()
|
||||
{
|
||||
Assert.Equal("abc", Path.GetDirectoryName(Path.Join("abc", "def")));
|
||||
Assert.Equal("abc", Path.GetDirectoryName(Path.Combine("abc", "def")));
|
||||
Assert.Equal(Win32.IsWindows() ? "\\" : "/", Path.GetDirectoryName($@"{Path.DirectorySeparatorChar}def"));
|
||||
Assert.Equal("", Path.GetDirectoryName(@"def"));
|
||||
|
||||
|
||||
@@ -137,11 +137,11 @@ namespace Semmle.Util
|
||||
bool IsMonoInstalled();
|
||||
|
||||
/// <summary>
|
||||
/// Joins path segments, Path.Join().
|
||||
/// Combine path segments, Path.Combine().
|
||||
/// </summary>
|
||||
/// <param name="parts">The parts of the path.</param>
|
||||
/// <returns>The combined path.</returns>
|
||||
string PathJoin(params string[] parts);
|
||||
string PathCombine(params string[] parts);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path for <paramref name="path"/>, Path.GetFullPath().
|
||||
@@ -293,7 +293,7 @@ namespace Semmle.Util
|
||||
}
|
||||
}
|
||||
|
||||
string IBuildActions.PathJoin(params string[] parts) => Path.Join(parts);
|
||||
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
|
||||
|
||||
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Semmle.Util
|
||||
var parent = Directory.GetParent(path);
|
||||
|
||||
return parent is not null ?
|
||||
Path.Join(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
|
||||
Path.Combine(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
|
||||
path.ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
@@ -138,12 +138,12 @@ namespace Semmle.Util
|
||||
var entries = Directory.GetFileSystemEntries(parentPath, name);
|
||||
return entries.Length == 1
|
||||
? entries[0]
|
||||
: Path.Join(parentPath, name);
|
||||
: Path.Combine(parentPath, name);
|
||||
}
|
||||
catch // lgtm[cs/catch-of-all-exceptions]
|
||||
{
|
||||
// IO error or security error querying directory.
|
||||
return Path.Join(parentPath, name);
|
||||
return Path.Combine(parentPath, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Semmle.Util
|
||||
{
|
||||
exes = new[] { prog };
|
||||
}
|
||||
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Join(path, exe0))));
|
||||
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Combine(path, exe0))));
|
||||
return candidates?.FirstOrDefault();
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Semmle.Util
|
||||
{
|
||||
innerpath = ConvertPathToSafeRelativePath(innerpath);
|
||||
|
||||
nested = Path.Join(outerpath, innerpath);
|
||||
nested = Path.Combine(outerpath, innerpath);
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -203,7 +203,7 @@ namespace Semmle.Util
|
||||
{
|
||||
var tempPath = Path.GetTempPath();
|
||||
var name = Guid.NewGuid().ToString("N").ToUpper();
|
||||
var tempFolder = Path.Join(tempPath, "GitHub", name);
|
||||
var tempFolder = Path.Combine(tempPath, "GitHub", name);
|
||||
Directory.CreateDirectory(tempFolder);
|
||||
return tempFolder;
|
||||
});
|
||||
@@ -231,7 +231,7 @@ namespace Semmle.Util
|
||||
string outputPath;
|
||||
do
|
||||
{
|
||||
outputPath = Path.Join(tempFolder, Path.GetRandomFileName() + extension);
|
||||
outputPath = Path.Combine(tempFolder, Path.GetRandomFileName() + extension);
|
||||
}
|
||||
while (File.Exists(outputPath));
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ source https://api.nuget.org/v3/index.json
|
||||
# behave like nuget in choosing transitive dependency versions
|
||||
strategy: max
|
||||
|
||||
nuget Basic.CompilerLog.Util 0.9.39
|
||||
nuget Basic.CompilerLog.Util 0.9.25
|
||||
nuget Mono.Posix.NETStandard
|
||||
nuget Newtonsoft.Json
|
||||
nuget NuGet.Versioning
|
||||
@@ -12,7 +12,7 @@ nuget xunit
|
||||
nuget xunit.runner.visualstudio
|
||||
nuget xunit.runner.utility
|
||||
nuget Microsoft.NET.Test.Sdk
|
||||
nuget Microsoft.CodeAnalysis.CSharp 5.3.0
|
||||
nuget Microsoft.CodeAnalysis 5.3.0
|
||||
nuget Microsoft.Build 18.6.3
|
||||
nuget Microsoft.CodeAnalysis.CSharp 5.0.0
|
||||
nuget Microsoft.CodeAnalysis 5.0.0
|
||||
nuget Microsoft.Build 18.0.2
|
||||
nuget Microsoft.VisualStudio.SolutionPersistence
|
||||
|
||||
100
csharp/paket.lock
generated
100
csharp/paket.lock
generated
@@ -3,42 +3,45 @@ STRATEGY: MAX
|
||||
RESTRICTION: == net10.0
|
||||
NUGET
|
||||
remote: https://api.nuget.org/v3/index.json
|
||||
Basic.CompilerLog.Util (0.9.39)
|
||||
Basic.CompilerLog.Util (0.9.25)
|
||||
MessagePack (>= 3.1.4)
|
||||
Microsoft.Bcl.Memory (>= 10.0.7)
|
||||
Microsoft.Bcl.Memory (>= 9.0.10)
|
||||
Microsoft.CodeAnalysis (>= 4.8)
|
||||
Microsoft.CodeAnalysis.CSharp (>= 4.8)
|
||||
Microsoft.CodeAnalysis.VisualBasic (>= 4.8)
|
||||
Microsoft.Extensions.ObjectPool (>= 10.0.7)
|
||||
MSBuild.StructuredLogger (>= 2.3.178)
|
||||
Microsoft.Extensions.ObjectPool (>= 9.0.10)
|
||||
MSBuild.StructuredLogger (>= 2.3.71)
|
||||
NaturalSort.Extension (>= 4.4)
|
||||
NuGet.Versioning (>= 6.14)
|
||||
Humanizer.Core (3.0.10)
|
||||
MessagePack (3.1.6)
|
||||
MessagePack.Annotations (>= 3.1.6)
|
||||
MessagePackAnalyzer (>= 3.1.6)
|
||||
MessagePack (3.1.4)
|
||||
MessagePack.Annotations (>= 3.1.4)
|
||||
MessagePackAnalyzer (>= 3.1.4)
|
||||
Microsoft.NET.StringTools (>= 17.11.4)
|
||||
MessagePack.Annotations (3.1.6)
|
||||
MessagePackAnalyzer (3.1.6)
|
||||
MessagePack.Annotations (3.1.4)
|
||||
MessagePackAnalyzer (3.1.4)
|
||||
Microsoft.Bcl.AsyncInterfaces (10.0.8)
|
||||
Microsoft.Bcl.Memory (10.0.8)
|
||||
Microsoft.Build (18.6.3)
|
||||
Microsoft.Build.Framework (>= 18.6.3)
|
||||
System.Configuration.ConfigurationManager (>= 10.0.3)
|
||||
System.Diagnostics.EventLog (>= 10.0.3)
|
||||
System.Reflection.MetadataLoadContext (>= 10.0.3)
|
||||
System.Security.Cryptography.ProtectedData (>= 10.0.3)
|
||||
Microsoft.Build.Framework (18.6.3)
|
||||
Microsoft.NET.StringTools (>= 18.6.3)
|
||||
Microsoft.Build.Utilities.Core (18.6.3)
|
||||
Microsoft.Build.Framework (>= 18.6.3)
|
||||
System.Configuration.ConfigurationManager (>= 10.0.3)
|
||||
System.Diagnostics.EventLog (>= 10.0.3)
|
||||
System.Security.Cryptography.ProtectedData (>= 10.0.3)
|
||||
Microsoft.CodeAnalysis (5.3)
|
||||
Microsoft.Build (18.0.2)
|
||||
Microsoft.Build.Framework (>= 18.0.2)
|
||||
Microsoft.NET.StringTools (>= 18.0.2)
|
||||
System.Configuration.ConfigurationManager (>= 9.0)
|
||||
System.Diagnostics.EventLog (>= 9.0)
|
||||
System.Reflection.MetadataLoadContext (>= 9.0)
|
||||
System.Security.Cryptography.ProtectedData (>= 9.0.6)
|
||||
Microsoft.Build.Framework (18.4)
|
||||
Microsoft.Build.Utilities.Core (18.4)
|
||||
Microsoft.Build.Framework (>= 18.4)
|
||||
Microsoft.NET.StringTools (>= 18.4)
|
||||
System.Configuration.ConfigurationManager (>= 10.0.1)
|
||||
System.Diagnostics.EventLog (>= 10.0.1)
|
||||
System.Security.Cryptography.ProtectedData (>= 10.0.1)
|
||||
Microsoft.CodeAnalysis (5.0)
|
||||
Humanizer.Core (>= 2.14.1)
|
||||
Microsoft.Bcl.AsyncInterfaces (>= 9.0)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.CSharp.Workspaces (5.3)
|
||||
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.CSharp.Workspaces (5.0)
|
||||
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.0)
|
||||
System.Buffers (>= 4.6)
|
||||
System.Collections.Immutable (>= 9.0)
|
||||
System.Composition (>= 9.0)
|
||||
@@ -51,36 +54,36 @@ NUGET
|
||||
System.Threading.Channels (>= 8.0)
|
||||
System.Threading.Tasks.Extensions (>= 4.6)
|
||||
Microsoft.CodeAnalysis.Analyzers (5.3)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.CSharp (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.CSharp.Workspaces (5.3)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.CSharp (5.0)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
Microsoft.CodeAnalysis.CSharp.Workspaces (5.0)
|
||||
Humanizer.Core (>= 2.14.1)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.CSharp (5.3)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
Microsoft.CodeAnalysis.CSharp (5.0)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.0)
|
||||
System.Composition (>= 9.0)
|
||||
Microsoft.CodeAnalysis.VisualBasic (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.3)
|
||||
Microsoft.CodeAnalysis.VisualBasic (5.0)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
Microsoft.CodeAnalysis.VisualBasic.Workspaces (5.0)
|
||||
Humanizer.Core (>= 2.14.1)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.VisualBasic (5.3)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
Microsoft.CodeAnalysis.VisualBasic (5.0)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.0)
|
||||
System.Composition (>= 9.0)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.3)
|
||||
Microsoft.CodeAnalysis.Workspaces.Common (5.0)
|
||||
Humanizer.Core (>= 2.14.1)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 5.3.0-2.25625.1)
|
||||
Microsoft.CodeAnalysis.Common (5.3)
|
||||
Microsoft.CodeAnalysis.Analyzers (>= 3.11)
|
||||
Microsoft.CodeAnalysis.Common (5.0)
|
||||
System.Composition (>= 9.0)
|
||||
Microsoft.CodeCoverage (18.5.1)
|
||||
Microsoft.Extensions.ObjectPool (10.0.8)
|
||||
Microsoft.NET.StringTools (18.6.3)
|
||||
Microsoft.NET.StringTools (18.4)
|
||||
Microsoft.NET.Test.Sdk (18.5.1)
|
||||
Microsoft.CodeCoverage (>= 18.5.1)
|
||||
Microsoft.TestPlatform.TestHost (>= 18.5.1)
|
||||
@@ -94,6 +97,7 @@ NUGET
|
||||
MSBuild.StructuredLogger (2.3.204)
|
||||
Microsoft.Build.Framework (>= 17.5)
|
||||
Microsoft.Build.Utilities.Core (>= 17.5)
|
||||
NaturalSort.Extension (4.4.1)
|
||||
Newtonsoft.Json (13.0.4)
|
||||
NuGet.Versioning (7.6)
|
||||
System.Buffers (4.6.1)
|
||||
|
||||
31
csharp/paket.main.bzl
generated
31
csharp/paket.main.bzl
generated
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user