mirror of
https://github.com/github/codeql.git
synced 2026-06-26 15:17:06 +02:00
Compare commits
52 Commits
codeql-cli
...
copilot/vs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
030af8eac3 | ||
|
|
6fa89ef39f | ||
|
|
62f90735fd | ||
|
|
67488a81c8 | ||
|
|
8e99548cac | ||
|
|
9f488f6daf | ||
|
|
d5f866535c | ||
|
|
cc80ecaaf6 | ||
|
|
73bf0613d9 | ||
|
|
aa7bdb575f | ||
|
|
2e1289dbdd | ||
|
|
7bfab958dd | ||
|
|
80bd6117ec | ||
|
|
8fd9c31e81 | ||
|
|
5b79e0d20d | ||
|
|
71cc56464b | ||
|
|
ac1b126efd | ||
|
|
0e50b3c00a | ||
|
|
b0e886f553 | ||
|
|
9090ed3802 | ||
|
|
ebe24b26f7 | ||
|
|
e5cd376670 | ||
|
|
4a3fbf3beb | ||
|
|
f5b0127bba | ||
|
|
f436d89b3f | ||
|
|
c5895a85ce | ||
|
|
85d198ebdf | ||
|
|
4409d8271c | ||
|
|
3a955b172f | ||
|
|
c4011f16aa | ||
|
|
63464ecb84 | ||
|
|
4d627be3a0 | ||
|
|
5962a22bdb | ||
|
|
7430209c3a | ||
|
|
dc7867b459 | ||
|
|
8c7859929c | ||
|
|
c1dfeaca9f | ||
|
|
1bcdbd2d34 | ||
|
|
cffc3c7bec | ||
|
|
8fb4875021 | ||
|
|
008cbbadcf | ||
|
|
d6d254fdda | ||
|
|
a5e761254e | ||
|
|
e328a5d69e | ||
|
|
01568dd2db | ||
|
|
c136d3ec30 | ||
|
|
6a1649d384 | ||
|
|
fbd82ffd68 | ||
|
|
3937a96ca4 | ||
|
|
a26cbad255 | ||
|
|
412f4c2403 | ||
|
|
1e05710256 |
@@ -248,7 +248,6 @@ use_repo(
|
||||
"kotlin-compiler-2.2.20-Beta2",
|
||||
"kotlin-compiler-2.3.0",
|
||||
"kotlin-compiler-2.3.20",
|
||||
"kotlin-compiler-2.4.0",
|
||||
"kotlin-compiler-embeddable-1.8.0",
|
||||
"kotlin-compiler-embeddable-1.9.0-Beta",
|
||||
"kotlin-compiler-embeddable-1.9.20-Beta",
|
||||
@@ -260,7 +259,6 @@ use_repo(
|
||||
"kotlin-compiler-embeddable-2.2.20-Beta2",
|
||||
"kotlin-compiler-embeddable-2.3.0",
|
||||
"kotlin-compiler-embeddable-2.3.20",
|
||||
"kotlin-compiler-embeddable-2.4.0",
|
||||
"kotlin-stdlib-1.8.0",
|
||||
"kotlin-stdlib-1.9.0-Beta",
|
||||
"kotlin-stdlib-1.9.20-Beta",
|
||||
@@ -272,7 +270,6 @@ use_repo(
|
||||
"kotlin-stdlib-2.2.20-Beta2",
|
||||
"kotlin-stdlib-2.3.0",
|
||||
"kotlin-stdlib-2.3.20",
|
||||
"kotlin-stdlib-2.4.0",
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
## 0.4.38
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* GitHub Actions queries now better account for permission checks on jobs that call reusable workflows.
|
||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
||||
|
||||
## 0.4.37
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
||||
@@ -1,6 +0,0 @@
|
||||
## 0.4.38
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* GitHub Actions queries now better account for permission checks on jobs that call reusable workflows.
|
||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.38
|
||||
lastReleaseVersion: 0.4.37
|
||||
|
||||
@@ -42,15 +42,6 @@ string actor_not_attacker_event() {
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the outer caller of `ej`, i.e. the `ExternalJob` that calls the
|
||||
* reusable workflow containing `ej`. Used with transitive closure to
|
||||
* walk up nested reusable workflow chains.
|
||||
*/
|
||||
private ExternalJob getAnOuterCaller(ExternalJob ej) {
|
||||
result = ej.getEnclosingWorkflow().(ReusableWorkflow).getACaller()
|
||||
}
|
||||
|
||||
/** An If node that contains an actor, user or label check */
|
||||
abstract class ControlCheck extends AstNode {
|
||||
ControlCheck() {
|
||||
@@ -62,170 +53,43 @@ abstract class ControlCheck extends AstNode {
|
||||
|
||||
predicate protects(AstNode node, Event event, string category) {
|
||||
// The check dominates the step it should protect
|
||||
this.dominates(node, event) and
|
||||
this.dominates(node) and
|
||||
// The check is effective against the event and category
|
||||
this.protectsCategoryAndEvent(category, event.getName()) and
|
||||
// The check can be triggered by the event
|
||||
this.getATriggerEvent() = event and
|
||||
// For reusable workflows, there must be no unprotected caller chain for this event.
|
||||
(
|
||||
not node.getEnclosingWorkflow() instanceof ReusableWorkflow
|
||||
or
|
||||
this.dominatesSameWorkflow(node, event)
|
||||
or
|
||||
not exists(ExternalJob directCaller |
|
||||
directCaller = node.getEnclosingWorkflow().(ReusableWorkflow).getACaller() and
|
||||
unprotectedCallerChain(directCaller, event, category)
|
||||
)
|
||||
)
|
||||
this.getATriggerEvent() = event
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this control check must execute and pass before `node` can run.
|
||||
*/
|
||||
predicate dominates(AstNode node, Event event) {
|
||||
this.dominatesSameWorkflow(node, event)
|
||||
or
|
||||
// When the node is inside a reusable workflow,
|
||||
// this check dominates via at least one caller chain.
|
||||
this.dominatesViaCaller(node, event, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this control check dominates `node` within the same workflow.
|
||||
*/
|
||||
predicate dominatesSameWorkflow(AstNode node, Event event) {
|
||||
this.getATriggerEvent() = event and
|
||||
(
|
||||
// Step-level: the check is an `if:` on the step containing `node`,
|
||||
// or on the enclosing job, or on a needed job/step.
|
||||
this instanceof If and
|
||||
(
|
||||
node.getEnclosingStep().getIf() = this or
|
||||
node.getEnclosingJob().getIf() = this or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
|
||||
)
|
||||
or
|
||||
// Job-level: the check is an environment on the enclosing job or a needed job.
|
||||
this instanceof Environment and
|
||||
(
|
||||
node.getEnclosingJob().getEnvironment() = this
|
||||
or
|
||||
node.getEnclosingJob().getANeededJob().getEnvironment() = this
|
||||
)
|
||||
or
|
||||
// Step-level: the check is a Run/UsesStep that precedes `node`'s step
|
||||
// in the same job, or is a step in a needed job.
|
||||
(
|
||||
this instanceof Run or
|
||||
this instanceof UsesStep
|
||||
) and
|
||||
(
|
||||
this.(Step).getAFollowingStep() = node.getEnclosingStep()
|
||||
or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep() = this
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this control check dominates `node` in a reusable workflow
|
||||
* via the caller chain starting at `directCaller`.
|
||||
*/
|
||||
predicate dominatesViaCaller(AstNode node, Event event, ExternalJob directCaller) {
|
||||
directCaller = node.getEnclosingWorkflow().(ReusableWorkflow).getACaller() and
|
||||
directCaller.getATriggerEvent() = event and
|
||||
exists(ExternalJob caller |
|
||||
caller = getAnOuterCaller*(directCaller) and
|
||||
this.dominatesCaller(caller)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this control check directly dominates `caller`.
|
||||
*/
|
||||
predicate dominatesCaller(ExternalJob caller) {
|
||||
predicate dominates(AstNode node) {
|
||||
this instanceof If and
|
||||
(
|
||||
caller.getIf() = this or
|
||||
caller.getANeededJob().(LocalJob).getIf() = this or
|
||||
caller.getANeededJob().(LocalJob).getAStep().getIf() = this
|
||||
node.getEnclosingStep().getIf() = this or
|
||||
node.getEnclosingJob().getIf() = this or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
|
||||
)
|
||||
or
|
||||
this instanceof Environment and
|
||||
(
|
||||
caller.getEnvironment() = this or
|
||||
caller.getANeededJob().getEnvironment() = this
|
||||
node.getEnclosingJob().getEnvironment() = this
|
||||
or
|
||||
node.getEnclosingJob().getANeededJob().getEnvironment() = this
|
||||
)
|
||||
or
|
||||
(this instanceof Run or this instanceof UsesStep) and
|
||||
caller.getANeededJob().(LocalJob).getAStep() = this
|
||||
(
|
||||
this instanceof Run or
|
||||
this instanceof UsesStep
|
||||
) and
|
||||
(
|
||||
this.(Step).getAFollowingStep() = node.getEnclosingStep()
|
||||
or
|
||||
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep() = this.(Step)
|
||||
)
|
||||
}
|
||||
|
||||
abstract predicate protectsCategoryAndEvent(string category, string event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this control check directly protects `caller`.
|
||||
*/
|
||||
bindingset[caller, event, category]
|
||||
private predicate protectedCaller(ExternalJob caller, Event event, string category) {
|
||||
exists(ControlCheck check |
|
||||
check.protectsCategoryAndEvent(category, event.getName()) and
|
||||
check.getATriggerEvent() = event and
|
||||
check.dominatesCaller(caller)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private newtype TCallerState =
|
||||
MkCallerState(ExternalJob caller, Event event, string category) {
|
||||
caller.getATriggerEvent() = event and
|
||||
category = any_category()
|
||||
}
|
||||
|
||||
private class CallerState extends TCallerState, MkCallerState {
|
||||
ExternalJob caller;
|
||||
Event event;
|
||||
string category;
|
||||
|
||||
CallerState() { this = MkCallerState(caller, event, category) }
|
||||
|
||||
ExternalJob getCaller() { result = caller }
|
||||
|
||||
Event getEvent() { result = event }
|
||||
|
||||
string getCategory() { result = category }
|
||||
|
||||
/**
|
||||
* Gets an outer caller state if this caller is not protected.
|
||||
*/
|
||||
CallerState getUnprotectedOuterState() {
|
||||
not protectedCaller(this.getCaller(), this.getEvent(), this.getCategory()) and
|
||||
result = MkCallerState(getAnOuterCaller(this.getCaller()), this.getEvent(), this.getCategory())
|
||||
}
|
||||
|
||||
predicate isUnprotectedOutermost() {
|
||||
not protectedCaller(this.getCaller(), this.getEvent(), this.getCategory()) and
|
||||
not exists(getAnOuterCaller(this.getCaller()))
|
||||
}
|
||||
|
||||
string toString() { result = caller + " / " + event + " / " + category }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a caller path from `caller` to an outer workflow that has no protection.
|
||||
*/
|
||||
bindingset[caller, event, category]
|
||||
private predicate unprotectedCallerChain(ExternalJob caller, Event event, string category) {
|
||||
exists(CallerState start, CallerState outermost |
|
||||
start = MkCallerState(caller, event, category) and
|
||||
outermost = start.getUnprotectedOuterState*() and
|
||||
outermost.isUnprotectedOutermost()
|
||||
)
|
||||
}
|
||||
|
||||
abstract class AssociationCheck extends ControlCheck {
|
||||
// Checks if the actor is a MEMBER/OWNER the repo
|
||||
// - they are effective against pull requests and workflow_run (since these are triggered by pull_requests) since they can control who is making the PR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.38
|
||||
version: 0.4.38-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
## 0.6.30
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
||||
|
||||
## 0.6.29
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
@@ -18,7 +18,7 @@ from LocalJob job, LabelCheck check, MutableRefCheckoutStep checkout, Event even
|
||||
where
|
||||
job.isPrivileged() and
|
||||
job.getAStep() = checkout and
|
||||
check.dominates(checkout, event) and
|
||||
check.dominates(checkout) and
|
||||
(
|
||||
job.getATriggerEvent() = event and
|
||||
event.getName() = "pull_request_target" and
|
||||
|
||||
@@ -34,8 +34,8 @@ where
|
||||
check instanceof AssociationCheck or
|
||||
check instanceof PermissionCheck
|
||||
) and
|
||||
check.dominates(checkout, event) and
|
||||
date_check.dominates(checkout, event)
|
||||
check.dominates(checkout) and
|
||||
date_check.dominates(checkout)
|
||||
)
|
||||
or
|
||||
// not issue_comment triggered workflows
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
## 0.6.30
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.30
|
||||
lastReleaseVersion: 0.6.29
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.30
|
||||
version: 0.6.30-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
COMMIT_SHA:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.COMMIT_SHA }}
|
||||
- run: |
|
||||
npm install
|
||||
npm run lint
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
COMMIT_SHA:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
COMMIT_SHA:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build_safe:
|
||||
needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}
|
||||
build_unsafe:
|
||||
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}
|
||||
@@ -1,31 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
#needs: is-collaborator Mistake, doesn't wait for the collaborator - no security check
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # should alert
|
||||
fetch-depth: 2
|
||||
- run: yarn test
|
||||
@@ -1,26 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build:
|
||||
needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check
|
||||
@@ -1,31 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build_unsafe:
|
||||
# needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # should alert since no permission check
|
||||
build_safe:
|
||||
needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check
|
||||
@@ -1,8 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: TestOrg/TestRepo/.github/workflows/build_nested_branching.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -1,26 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build:
|
||||
needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check
|
||||
@@ -1,26 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build:
|
||||
# needs: is-collaborator
|
||||
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -1,41 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: is-collaborator
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check
|
||||
fetch-depth: 2
|
||||
- run: yarn test
|
||||
build_unsafe:
|
||||
runs-on: ubuntu-latest
|
||||
# needs: is-collaborator
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # should alert since no permission check
|
||||
fetch-depth: 2
|
||||
- run: yarn test
|
||||
@@ -1,48 +0,0 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
is-collaborator-a:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
caller-a:
|
||||
needs: is-collaborator-a
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
is-collaborator-b:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get User Permission
|
||||
id: checkAccess
|
||||
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
|
||||
with:
|
||||
require: write
|
||||
username: ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check User Permission
|
||||
if: steps.checkAccess.outputs.require-result == 'false'
|
||||
run: |
|
||||
echo "${{ github.actor }} does not have permissions on this repo."
|
||||
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
|
||||
exit 1
|
||||
caller-b:
|
||||
needs: is-collaborator-b
|
||||
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
|
||||
with:
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -93,8 +93,6 @@ edges
|
||||
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:20:9:25:6 | Uses Step |
|
||||
| .github/workflows/dependabot3.yml:20:9:25:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone |
|
||||
| .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:48:9:52:57 | Run Step |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build_nested_branching.yml:11:9:19:6 | Uses Step: checkAccess | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build_nested_branching.yml:19:9:25:2 | Run Step |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:14:9:19:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:19:9:25:6 | Run Step |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:19:9:25:6 | Run Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:25:9:70:20 | Run Step |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step |
|
||||
@@ -336,17 +334,6 @@ edges
|
||||
| .github/workflows/untrusted_checkout_6.yml:11:9:14:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:14:9:17:6 | Uses Step |
|
||||
| .github/workflows/untrusted_checkout_6.yml:14:9:17:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:17:9:21:6 | Uses Step |
|
||||
| .github/workflows/untrusted_checkout_6.yml:17:9:21:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:21:9:23:23 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_no_needs.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_no_needs.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:31:9:31:23 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permission_check_reusable2.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable2.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permission_check_reusable.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permission_check_reusable_level2.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable_level2.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permissions_check.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permissions_check.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permissions_check.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:31:9:32:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:41:9:41:22 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_two_callers_both_protected.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_two_callers_both_protected.yml:16:9:22:2 | Run Step |
|
||||
| .github/workflows/untrusted_checkout_two_callers_both_protected.yml:30:9:38:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_two_callers_both_protected.yml:38:9:44:2 | Run Step |
|
||||
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step |
|
||||
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step |
|
||||
| .github/workflows/workflow_run_untrusted_checkout_3.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_3.yml:16:9:18:31 | Uses Step |
|
||||
@@ -357,9 +344,6 @@ edges
|
||||
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable2.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable_branching_nested.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
@@ -393,5 +377,3 @@ edges
|
||||
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
|
||||
| .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:31:9:31:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_no_needs.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:41:9:41:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permissions_check.yml:2:3:2:21 | pull_request_target | pull_request_target |
|
||||
|
||||
@@ -1,20 +1,3 @@
|
||||
## 11.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
|
||||
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
|
||||
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.
|
||||
* Removed the deprecated `exprExits` predicate from `Options.qll`. Use `CustomOptions.exprExits` instead.
|
||||
* Removed the deprecated `alwaysCheckReturnValue` predicate from `Options.qll`. Use `CustomOptions.alwaysCheckReturnValue` instead.
|
||||
* Removed the deprecated `okToIgnoreReturnValue` predicate from `Options.qll`. Use `CustomOptions.okToIgnoreReturnValue` instead.
|
||||
* Removed the deprecated `semmle.code.cpp.Member`. Import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly.
|
||||
* Removed the deprecated `UnknownDefaultLocation` class. Use `UnknownLocation` instead.
|
||||
* Removed the deprecated `UnknownExprLocation` class. Use `UnknownLocation` instead.
|
||||
* Removed the deprecated `UnknownStmtLocation` class. Use `UnknownLocation` instead.
|
||||
* Removed the deprecated `TemplateParameter` class. Use `TypeTemplateParameter` instead.
|
||||
* Support for class resolution across link targets has been removed for databases which were created with CodeQL versions before 1.23.0.
|
||||
|
||||
## 10.2.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
## 11.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
|
||||
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
|
||||
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 11.0.0
|
||||
lastReleaseVersion: 10.2.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 11.0.0
|
||||
version: 10.2.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.6.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.6.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.6.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.6.5
|
||||
lastReleaseVersion: 1.6.4
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.6.5
|
||||
version: 1.6.5-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.7.69
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.68
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.7.69
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.69
|
||||
lastReleaseVersion: 1.7.68
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.69
|
||||
version: 1.7.69-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.7.69
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.68
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.7.69
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.69
|
||||
lastReleaseVersion: 1.7.68
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.69
|
||||
version: 1.7.69-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,19 +1,3 @@
|
||||
## 7.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
||||
* Improved call target resolution for ref-return properties and indexers.
|
||||
|
||||
## 6.0.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved call target resolution for ref-return properties and indexers.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
||||
@@ -1,15 +0,0 @@
|
||||
## 7.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
||||
* Improved call target resolution for ref-return properties and indexers.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 7.0.0
|
||||
lastReleaseVersion: 6.0.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 7.0.0
|
||||
version: 6.0.3-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.7.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -14,6 +14,54 @@
|
||||
|
||||
import csharp
|
||||
|
||||
/**
|
||||
* Gets a callable that either directly captures local variable `v`, or which
|
||||
* is enclosed by the callable that declares `v` and encloses a callable that
|
||||
* captures `v`.
|
||||
*/
|
||||
Callable getACapturingCallableAncestor(LocalVariable v) {
|
||||
result = v.getACapturingCallable()
|
||||
or
|
||||
exists(Callable mid | mid = getACapturingCallableAncestor(v) |
|
||||
result = mid.getEnclosingCallable() and
|
||||
not v.getEnclosingCallable() = result
|
||||
)
|
||||
}
|
||||
|
||||
Expr getADelegateExpr(Callable c) {
|
||||
c = result.(CallableAccess).getTarget()
|
||||
or
|
||||
result = c.(AnonymousFunctionExpr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `c` is a call where any delegate argument is evaluated immediately.
|
||||
*/
|
||||
predicate nonEscapingCall(Call c) {
|
||||
exists(string name | c.getTarget().hasName(name) |
|
||||
name =
|
||||
[
|
||||
"ForEach", "Count", "Any", "All", "Average", "Aggregate", "First", "Last", "FirstOrDefault",
|
||||
"LastOrDefault", "LongCount", "Max", "Single", "SingleOrDefault", "Sum"
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `v` is a captured local variable, and one of the callables capturing
|
||||
* `v` may escape the local scope.
|
||||
*/
|
||||
predicate mayEscape(LocalVariable v) {
|
||||
exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) |
|
||||
e = getADelegateExpr(c) and
|
||||
DataFlow::localExprFlow(e, succ) and
|
||||
not succ = any(DelegateCall dc).getExpr() and
|
||||
not succ = any(Cast cast).getExpr() and
|
||||
not succ = any(Call call | nonEscapingCall(call)).getAnArgument() and
|
||||
not succ = any(AssignableDefinition ad | ad.getTarget() instanceof LocalVariable).getSource()
|
||||
)
|
||||
}
|
||||
|
||||
class RelevantDefinition extends AssignableDefinition {
|
||||
RelevantDefinition() {
|
||||
this.(AssignableDefinitions::AssignmentDefinition).getAssignment() =
|
||||
@@ -46,6 +94,8 @@ class RelevantDefinition extends AssignableDefinition {
|
||||
// SSA definitions are only created for live variables
|
||||
this = any(SsaExplicitWrite ssaDef).getDefinition()
|
||||
or
|
||||
mayEscape(v)
|
||||
or
|
||||
v.isCaptured()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.7.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.5
|
||||
lastReleaseVersion: 1.7.4
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 1.7.5
|
||||
version: 1.7.5-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [7]_",``.java``
|
||||
Kotlin,"Kotlin 1.8.0 to 2.4.0\ *x*","kotlinc",``.kt``
|
||||
Kotlin,"Kotlin 1.8.0 to 2.3.2\ *x*","kotlinc",``.kt``
|
||||
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_"
|
||||
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
|
||||
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.0.52
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.51
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
go/ql/consistency-queries/CfgConsistency.ql
Normal file
3
go/ql/consistency-queries/CfgConsistency.ql
Normal file
@@ -0,0 +1,3 @@
|
||||
import go
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
import GoCfg::ControlFlow::Consistency
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.0.52
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.52
|
||||
lastReleaseVersion: 1.0.51
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql-go-consistency-queries
|
||||
version: 1.0.52
|
||||
version: 1.0.52-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -1,20 +1,3 @@
|
||||
## 7.2.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
|
||||
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
|
||||
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
|
||||
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
|
||||
through `slog`.
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
* More logging functions are now recognized as not returning or panicking.
|
||||
|
||||
## 7.1.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
4
go/ql/lib/change-notes/2026-03-30-shared-cfg-library.md
Normal file
4
go/ql/lib/change-notes/2026-03-30-shared-cfg-library.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The Go control flow graph implementation has been migrated to use the shared CFG library. This is an internal change with no user-visible API changes.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* More logging functions are now recognized as not returning or panicking.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
4
go/ql/lib/change-notes/2026-06-08-fix-result-nodes.md
Normal file
4
go/ql/lib/change-notes/2026-06-08-fix-result-nodes.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
8
go/ql/lib/change-notes/2026-06-17-model-log-slog.md
Normal file
8
go/ql/lib/change-notes/2026-06-17-model-log-slog.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
|
||||
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
|
||||
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
|
||||
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
|
||||
through `slog`.
|
||||
@@ -1,16 +0,0 @@
|
||||
## 7.2.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added models for the `log/slog` package (Go 1.21+). Its logging functions and
|
||||
`*slog.Logger` methods (`Debug`/`Info`/`Warn`/`Error`, their `Context`
|
||||
variants, and `Log`/`LogAttrs`) are now recognized as logging sinks, so the
|
||||
`go/log-injection` and `go/clear-text-logging` queries cover code that logs
|
||||
through `slog`.
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
* More logging functions are now recognized as not returning or panicking.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 7.2.0
|
||||
lastReleaseVersion: 7.1.2
|
||||
|
||||
53
go/ql/lib/printCfg.ql
Normal file
53
go/ql/lib/printCfg.ql
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @name Print CFG
|
||||
* @description Produces a representation of a file's Control Flow Graph.
|
||||
* This query is used by the VS Code extension.
|
||||
* @id go/print-cfg
|
||||
* @kind graph
|
||||
* @tags ide-contextual-queries/print-cfg
|
||||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.controlflow.ControlFlowGraph
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
|
||||
external string selectedSourceFile();
|
||||
|
||||
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
||||
|
||||
external int selectedSourceLine();
|
||||
|
||||
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
||||
|
||||
external int selectedSourceColumn();
|
||||
|
||||
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
||||
|
||||
module ViewCfgQueryInput implements GoCfg::ControlFlow::ViewCfgQueryInputSig<File> {
|
||||
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
||||
|
||||
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
||||
|
||||
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
||||
|
||||
predicate cfgScopeSpan(
|
||||
CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn
|
||||
) {
|
||||
file = scope.getFile() and
|
||||
scope.getLocation().getStartLine() = startLine and
|
||||
scope.getLocation().getStartColumn() = startColumn and
|
||||
exists(Location loc |
|
||||
loc.getEndLine() = endLine and
|
||||
loc.getEndColumn() = endColumn and
|
||||
loc = scope.(FuncDef).getBody().getLocation()
|
||||
)
|
||||
or
|
||||
file = scope.(File) and
|
||||
startLine = 1 and
|
||||
startColumn = 1 and
|
||||
endLine = file.getNumberOfLines() and
|
||||
endColumn = 999999
|
||||
}
|
||||
}
|
||||
|
||||
import GoCfg::ControlFlow::ViewCfgQuery<File, ViewCfgQueryInput>
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-all
|
||||
version: 7.2.0
|
||||
version: 7.1.3-dev
|
||||
groups: go
|
||||
dbscheme: go.dbscheme
|
||||
extractor: go
|
||||
|
||||
@@ -431,7 +431,7 @@ private class HeuristicLoggerFunction extends Method {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
|
||||
override predicate mustNotReturnNormally() { logFunctionPrefix = "Fatal" }
|
||||
|
||||
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a Go AST as a graph.
|
||||
*/
|
||||
overlay[local]
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
import go
|
||||
|
||||
@@ -437,11 +437,12 @@ class Function extends ValueEntity, @functionobject {
|
||||
* This predicate is an over-approximation: it may hold for functions that can never
|
||||
* return normally, but it never fails to hold for functions that can.
|
||||
*
|
||||
* Note this is declared here and not in `DeclaredFunction` so that library models can override this
|
||||
* by extending `Function` rather than having to remember to extend `DeclaredFunction`.
|
||||
* Library models should not override this predicate; override `mustNotReturnNormally`
|
||||
* instead, so that the control-flow graph construction can take the model into account.
|
||||
*/
|
||||
predicate mayReturnNormally() {
|
||||
not this.mustPanic() and
|
||||
not this.mustNotReturnNormally() and
|
||||
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
||||
}
|
||||
|
||||
@@ -461,6 +462,16 @@ class Function extends ValueEntity, @functionobject {
|
||||
*/
|
||||
predicate mustPanic() { none() }
|
||||
|
||||
/**
|
||||
* Holds if calling this function never returns normally (for example because it
|
||||
* always panics, exits the process, or loops forever).
|
||||
*
|
||||
* Unlike `mayReturnNormally`, this predicate must be defined without reference to
|
||||
* the control-flow graph, so that it can be used during CFG construction to
|
||||
* suppress normal-flow successors of calls to this function.
|
||||
*/
|
||||
predicate mustNotReturnNormally() { none() }
|
||||
|
||||
/** Gets the number of parameters of this function. */
|
||||
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
||||
|
||||
|
||||
@@ -761,7 +761,7 @@ class CaseClause extends @caseclause, Stmt, ScopeNode {
|
||||
*
|
||||
* Note that the default clause does not have any expressions.
|
||||
*/
|
||||
Expr getAnExpr() { result = this.getAChildExpr() }
|
||||
Expr getAnExpr() { result = this.getExpr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of expressions of this `case` clause.
|
||||
|
||||
@@ -5,66 +5,27 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphImpl
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
private import codeql.controlflow.SuccessorType
|
||||
private import ControlFlowGraphShared
|
||||
|
||||
private module Input implements BB::InputSig<Location> {
|
||||
/** A delineated part of the AST with its own CFG. */
|
||||
class CfgScope = ControlFlow::Root;
|
||||
/** A basic block in the control-flow graph. */
|
||||
class BasicBlock = GoCfg::Cfg::BasicBlock;
|
||||
|
||||
/** The class of control flow nodes. */
|
||||
class Node = ControlFlowNode;
|
||||
|
||||
/** Gets the CFG scope in which this node occurs. */
|
||||
CfgScope nodeGetCfgScope(Node node) { node.getRoot() = result }
|
||||
|
||||
/** Gets an immediate successor of this node. */
|
||||
Node nodeGetASuccessor(Node node, SuccessorType t) {
|
||||
result = node.getASuccessor() and
|
||||
(
|
||||
not result instanceof ControlFlow::ConditionGuardNode and t instanceof DirectSuccessor
|
||||
or
|
||||
t.(BooleanSuccessor).getValue() = result.(ControlFlow::ConditionGuardNode).getOutcome()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an entry node to be used when calculating
|
||||
* dominance.
|
||||
*/
|
||||
predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an exit node to be used when calculating
|
||||
* post dominance.
|
||||
*/
|
||||
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
|
||||
}
|
||||
|
||||
module Cfg = BB::Make<Location, Input>;
|
||||
|
||||
class BasicBlock = Cfg::BasicBlock;
|
||||
|
||||
class EntryBasicBlock = Cfg::EntryBasicBlock;
|
||||
|
||||
cached
|
||||
private predicate reachableBB(BasicBlock bb) {
|
||||
bb instanceof EntryBasicBlock
|
||||
or
|
||||
exists(BasicBlock predBB | predBB.getASuccessor(_) = bb | reachableBB(predBB))
|
||||
}
|
||||
/** An entry basic block. */
|
||||
class EntryBasicBlock = GoCfg::Cfg::EntryBasicBlock;
|
||||
|
||||
/**
|
||||
* A basic block that is reachable from an entry basic block.
|
||||
*
|
||||
* Since the shared CFG library only creates nodes for reachable code,
|
||||
* all basic blocks are reachable by construction.
|
||||
*/
|
||||
class ReachableBasicBlock extends BasicBlock {
|
||||
ReachableBasicBlock() { reachableBB(this) }
|
||||
ReachableBasicBlock() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reachable basic block with more than one predecessor.
|
||||
*/
|
||||
class ReachableJoinBlock extends ReachableBasicBlock {
|
||||
ReachableJoinBlock() { this.getFirstNode().isJoin() }
|
||||
ReachableJoinBlock() { this.getFirstNode().(ControlFlow::Node).isJoin() }
|
||||
}
|
||||
|
||||
@@ -5,13 +5,17 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphImpl
|
||||
private import ControlFlowGraphShared
|
||||
|
||||
/** Provides helper predicates for mapping btween CFG nodes and the AST. */
|
||||
/** Provides helper predicates for mapping between CFG nodes and the AST. */
|
||||
module ControlFlow {
|
||||
/** A file or function with which a CFG is associated. */
|
||||
class Root extends AstNode {
|
||||
Root() { exists(this.(File).getADecl()) or exists(this.(FuncDef).getBody()) }
|
||||
Root() {
|
||||
exists(this.(FuncDef).getBody())
|
||||
or
|
||||
exists(this.(File).getADecl())
|
||||
}
|
||||
|
||||
/** Holds if `nd` belongs to this file or function. */
|
||||
predicate isRootOf(AstNode nd) {
|
||||
@@ -29,22 +33,16 @@ module ControlFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* A node in the intra-procedural control-flow graph of a Go function or file.
|
||||
* A node in the intra-procedural control-flow graph of a Go function.
|
||||
*
|
||||
* Nodes correspond to expressions and statements that compute a value or perform
|
||||
* an operation (as opposed to providing syntactic structure or type information).
|
||||
*
|
||||
* There are also synthetic entry and exit nodes for each Go function and file
|
||||
* There are also synthetic entry and exit nodes for each Go function
|
||||
* that mark the beginning and the end, respectively, of the execution of the
|
||||
* function and the loading of the file.
|
||||
* function.
|
||||
*/
|
||||
class Node extends TControlFlowNode {
|
||||
/** Gets a node that directly follows this one in the control-flow graph. */
|
||||
Node getASuccessor() { result = CFG::succ(this) }
|
||||
|
||||
/** Gets a node that directly precedes this one in the control-flow graph. */
|
||||
Node getAPredecessor() { this = result.getASuccessor() }
|
||||
|
||||
class Node extends GoCfg::ControlFlowNode {
|
||||
/** Holds if this is a node with more than one successor. */
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
|
||||
@@ -52,22 +50,23 @@ module ControlFlow {
|
||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||
|
||||
/** Holds if this is the first control-flow node in `subtree`. */
|
||||
predicate isFirstNodeOf(AstNode subtree) { CFG::firstNode(subtree, this) }
|
||||
predicate isFirstNodeOf(AstNode subtree) {
|
||||
this.isBefore(subtree)
|
||||
or
|
||||
this.injects(subtree)
|
||||
}
|
||||
|
||||
/** Holds if this node is the (unique) entry node of a function or file. */
|
||||
predicate isEntryNode() { this instanceof MkEntryNode }
|
||||
/** Holds if this node is the (unique) entry node of a function. */
|
||||
predicate isEntryNode() { this instanceof GoCfg::ControlFlow::EntryNode }
|
||||
|
||||
/** Holds if this node is the (unique) exit node of a function or file. */
|
||||
predicate isExitNode() { this instanceof MkExitNode }
|
||||
|
||||
/** Gets the basic block to which this node belongs. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
/** Holds if this node is the (unique) exit node of a function. */
|
||||
predicate isExitNode() { this instanceof GoCfg::ControlFlow::ExitNode }
|
||||
|
||||
/** Holds if this node dominates `dominee` in the control-flow graph. */
|
||||
overlay[caller?]
|
||||
pragma[inline]
|
||||
predicate dominatesNode(ControlFlow::Node dominee) {
|
||||
exists(ReachableBasicBlock thisbb, ReachableBasicBlock dbb, int i, int j |
|
||||
exists(GoCfg::Cfg::BasicBlock thisbb, GoCfg::Cfg::BasicBlock dbb, int i, int j |
|
||||
this = thisbb.getNode(i) and dominee = dbb.getNode(j)
|
||||
|
|
||||
thisbb.strictlyDominates(dbb)
|
||||
@@ -76,20 +75,12 @@ module ControlFlow {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the innermost function or file to which this node belongs. */
|
||||
Root getRoot() { none() }
|
||||
/** Gets the innermost function to which this node belongs. */
|
||||
Root getRoot() { result = this.getEnclosingCallable() }
|
||||
|
||||
/** Gets the file to which this node belongs. */
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this control flow node.
|
||||
*/
|
||||
string toString() { result = "control-flow node" }
|
||||
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation()` instead.
|
||||
*
|
||||
@@ -113,6 +104,22 @@ module ControlFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** A synthetic entry node for a function. */
|
||||
class EntryNode extends Node instanceof GoCfg::ControlFlow::EntryNode { }
|
||||
|
||||
/** A synthetic exit node for a function. */
|
||||
class ExitNode extends Node instanceof GoCfg::ControlFlow::ExitNode { }
|
||||
|
||||
private predicate isBranchConditionRoot(Expr expr) {
|
||||
expr = any(LogicalBinaryExpr lbe).getLeftOperand()
|
||||
or
|
||||
expr = any(ForStmt fs).getCond()
|
||||
or
|
||||
expr = any(IfStmt is).getCond()
|
||||
or
|
||||
expr = any(ExpressionSwitchStmt ess | not exists(ess.getExpr())).getACase().getAnExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* A control-flow node that initializes or updates the value of a constant, a variable,
|
||||
* a field, or an (array, slice, or map) element.
|
||||
@@ -172,7 +179,7 @@ module ControlFlow {
|
||||
exists(IR::FieldTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getField() = f and
|
||||
super.getRhs() = rhs
|
||||
@@ -220,7 +227,7 @@ module ControlFlow {
|
||||
exists(IR::ElementTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getIndex() = index and
|
||||
super.getRhs() = rhs
|
||||
@@ -250,11 +257,19 @@ module ControlFlow {
|
||||
* A control-flow node recording the fact that a certain expression has a known
|
||||
* Boolean value at this point in the program.
|
||||
*/
|
||||
class ConditionGuardNode extends IR::Instruction, MkConditionGuardNode {
|
||||
class ConditionGuardNode extends IR::Instruction {
|
||||
Expr cond;
|
||||
boolean outcome;
|
||||
|
||||
ConditionGuardNode() { this = MkConditionGuardNode(cond, outcome) }
|
||||
ConditionGuardNode() {
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterTrue(cond) and
|
||||
outcome = true
|
||||
or
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterFalse(cond) and
|
||||
outcome = false
|
||||
}
|
||||
|
||||
private predicate ensuresAux(Expr expr, boolean b) {
|
||||
expr = cond and b = outcome
|
||||
@@ -320,21 +335,17 @@ module ControlFlow {
|
||||
boolean getOutcome() { result = outcome }
|
||||
|
||||
override Root getRoot() { result.isRootOf(cond) }
|
||||
|
||||
override string toString() { result = cond + " is " + outcome }
|
||||
|
||||
override Location getLocation() { result = cond.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entry node of function or file `root`.
|
||||
* Gets the entry node of function `root`.
|
||||
*/
|
||||
Node entryNode(Root root) { result = MkEntryNode(root) }
|
||||
EntryNode entryNode(Root root) { result.getEnclosingCallable() = root }
|
||||
|
||||
/**
|
||||
* Gets the exit node of function or file `root`.
|
||||
* Gets the exit node of function `root`.
|
||||
*/
|
||||
Node exitNode(Root root) { result = MkExitNode(root) }
|
||||
ExitNode exitNode(Root root) { result.getEnclosingCallable() = root }
|
||||
|
||||
/**
|
||||
* Holds if the function `f` may return without panicking, exiting the process, or looping forever.
|
||||
@@ -342,20 +353,40 @@ module ControlFlow {
|
||||
* This is defined conservatively, and so may also hold of a function that in fact
|
||||
* cannot return normally, but never fails to hold of a function that can return normally.
|
||||
*/
|
||||
predicate mayReturnNormally(FuncDecl f) { CFG::mayReturnNormally(f.getBody()) }
|
||||
predicate mayReturnNormally(FuncDecl f) {
|
||||
exists(GoCfg::ControlFlow::NormalExitNode exit |
|
||||
exit.getEnclosingCallable() = f and
|
||||
exists(exit.getAPredecessor())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is the node for the case `testExpr` in an expression
|
||||
* switch statement which is switching on `switchExpr`, and `succ` is the
|
||||
* node to be executed next if the case test succeeds.
|
||||
* Holds if `pred` is the node reached when a case of the expression switch
|
||||
* statement switching on `switchExpr` matches, `testExpr` is one of that
|
||||
* case's test expressions, and `succ` is the node to be executed next when
|
||||
* the case matches.
|
||||
*
|
||||
* In the control-flow graph the individual case test expressions of a case
|
||||
* clause all funnel into a single "matched" node for the clause, from which
|
||||
* control transfers to the case body. Hence `pred` is that shared matched
|
||||
* node, and the same `(pred, succ)` pair is reported once per test
|
||||
* expression `testExpr` of the clause.
|
||||
*/
|
||||
predicate isSwitchCaseTestPassingEdge(
|
||||
ControlFlow::Node pred, ControlFlow::Node succ, Expr switchExpr, Expr testExpr
|
||||
) {
|
||||
CFG::isSwitchCaseTestPassingEdge(pred, succ, switchExpr, testExpr)
|
||||
exists(ExpressionSwitchStmt ess, CaseClause cc, int i |
|
||||
ess.getExpr() = switchExpr and
|
||||
cc = ess.getACase() and
|
||||
testExpr = cc.getExpr(i) and
|
||||
pred.isAfter(cc) and
|
||||
succ.isFirstNodeOf(cc.getStmt(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ControlFlowNode = ControlFlow::Node;
|
||||
|
||||
class CfgScope = GoCfg::CfgScope;
|
||||
|
||||
class Write = ControlFlow::WriteNode;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1763
go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll
Normal file
1763
go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -200,7 +200,7 @@ private ControlFlow::Node mostRecentSideEffect(ControlFlow::Node entry, ControlF
|
||||
|
||||
cached
|
||||
private ControlFlow::Node mostRecentSideEffectUnique(ControlFlow::Node node) {
|
||||
result = unique( | | mostRecentSideEffect(_, node))
|
||||
result = unique( | | mostRecentSideEffect(getControlFlowEntry(node), node))
|
||||
}
|
||||
|
||||
/** Used to represent the "global value number" of an expression. */
|
||||
|
||||
@@ -9,6 +9,7 @@ module;
|
||||
import go
|
||||
private import codeql.ssa.Ssa as SsaImplCommon
|
||||
private import semmle.go.controlflow.BasicBlocks as BasicBlocks
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
|
||||
private class BasicBlock = BasicBlocks::BasicBlock;
|
||||
|
||||
@@ -38,7 +39,7 @@ private module Internal {
|
||||
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
|
||||
private predicate entryNode(FuncDef f, BasicBlock bb, int i) {
|
||||
f = bb.getScope() and
|
||||
bb.getNode(i).isEntryNode()
|
||||
bb.getNode(i).(ControlFlow::Node).isEntryNode()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +111,7 @@ private module Internal {
|
||||
v.isCaptured() and
|
||||
exists(FuncDef f |
|
||||
f = bb.getScope() and
|
||||
bb.getLastNode().isExitNode() and
|
||||
bb.getLastNode().(ControlFlow::Node).isExitNode() and
|
||||
i = bb.length() - 1 and
|
||||
certain = false
|
||||
|
|
||||
@@ -126,7 +127,7 @@ private module Internal {
|
||||
}
|
||||
|
||||
import Internal
|
||||
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
|
||||
import SsaImplCommon::Make<Location, GoCfg::Cfg, SsaInput> as Impl
|
||||
|
||||
final class Definition = Impl::Definition;
|
||||
|
||||
|
||||
@@ -341,10 +341,22 @@ private ControlFlow::Node getANonTestPassingPredecessor(
|
||||
) {
|
||||
isPossibleInputNode(inputNode, succ.getRoot()) and
|
||||
result = succ.getAPredecessor() and
|
||||
not exists(Expr testExpr, DataFlow::Node switchExprNode |
|
||||
not exists(DataFlow::Node switchExprNode |
|
||||
flowsToSwitchExpression(inputNode, switchExprNode) and
|
||||
ControlFlow::isSwitchCaseTestPassingEdge(result, succ, switchExprNode.asExpr(), testExpr) and
|
||||
testExpr.isConst()
|
||||
// The case body is reachable only by matching a constant: at least one of
|
||||
// the case's test expressions is constant, and none of them is
|
||||
// non-constant. (All test expressions of a case share the same matched
|
||||
// edge `result -> succ`, so a case mixing constant and non-constant tests
|
||||
// must not be treated as a constant-only match.)
|
||||
exists(Expr testExpr |
|
||||
ControlFlow::isSwitchCaseTestPassingEdge(result, succ, switchExprNode.asExpr(), testExpr) and
|
||||
testExpr.isConst()
|
||||
) and
|
||||
not exists(Expr nonConstTestExpr |
|
||||
ControlFlow::isSwitchCaseTestPassingEdge(result, succ, switchExprNode.asExpr(),
|
||||
nonConstTestExpr) and
|
||||
not nonConstTestExpr.isConst()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ module Glog {
|
||||
/** Holds if this function takes a format string. */
|
||||
predicate formatter() { format = "f" }
|
||||
|
||||
override predicate mayReturnNormally() { level != "Fatal" and level != "Exit" }
|
||||
override predicate mustNotReturnNormally() { level = "Fatal" or level = "Exit" }
|
||||
}
|
||||
|
||||
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
|
||||
|
||||
@@ -29,8 +29,8 @@ module Logrus {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() {
|
||||
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||
override predicate mustNotReturnNormally() {
|
||||
exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||
this.getName() = level + suffix
|
||||
)
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ module Revel {
|
||||
|
||||
private IR::EvalInstruction skipImplicitFieldReads(IR::Instruction insn) {
|
||||
result = insn or
|
||||
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBase())
|
||||
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBaseInstruction())
|
||||
}
|
||||
|
||||
/** A call to `Controller.Render`. */
|
||||
|
||||
@@ -54,7 +54,7 @@ module Zap {
|
||||
this.hasQualifiedName(packagePath(), "SugaredLogger", "Fatal" + getSuffix())
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
}
|
||||
|
||||
/** A Zap logging function which always panics. */
|
||||
|
||||
@@ -44,7 +44,7 @@ module Log {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
}
|
||||
|
||||
/** A log function which must panic. */
|
||||
|
||||
@@ -12,7 +12,7 @@ module Os {
|
||||
private class Exit extends Function {
|
||||
Exit() { this.hasQualifiedName("os", "Exit") }
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
}
|
||||
|
||||
// These models are not implemented using Models-as-Data because they represent reverse flow.
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
## 1.6.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The query `go/unhandled-writable-file-close` ("Writable file handle closed without error handling") now produces fewer false positives. A deferred call to `Close` that is preceded on every execution path by a handled call to `Sync` on the same file handle is no longer flagged.
|
||||
|
||||
## 1.6.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -14,11 +14,36 @@
|
||||
|
||||
import go
|
||||
|
||||
ControlFlow::Node nonGuardPredecessor(ControlFlow::Node nd) {
|
||||
exists(ControlFlow::Node pred | pred = nd.getAPredecessor() |
|
||||
if pred instanceof ControlFlow::ConditionGuardNode
|
||||
then result = nonGuardPredecessor(pred)
|
||||
else result = pred
|
||||
/**
|
||||
* Holds if `s` is reachable, that is, the control-flow graph contains a node for it.
|
||||
*
|
||||
* The shared control-flow library does not create control-flow nodes for dead code, so an
|
||||
* unreachable statement has no first control-flow node.
|
||||
*/
|
||||
predicate isReachable(Stmt s) { exists(s.getFirstControlFlowNode()) }
|
||||
|
||||
/** Gets the statement immediately preceding `s` in a statement list, if any. */
|
||||
Stmt getPreviousStmt(Stmt s) {
|
||||
exists(BlockStmt b, int i | s = b.getStmt(i) and result = b.getStmt(i - 1))
|
||||
or
|
||||
exists(CaseClause c, int i | s = c.getStmt(i) and result = c.getStmt(i - 1))
|
||||
or
|
||||
exists(CommClause c, int i | s = c.getStmt(i) and result = c.getStmt(i - 1))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `s` is unreachable but the code that would precede it in the control-flow graph is
|
||||
* reachable, so that `s` is the first unreachable statement in a run of dead code.
|
||||
*/
|
||||
predicate firstUnreachableStmt(Stmt s) {
|
||||
not isReachable(s) and
|
||||
not s instanceof EmptyStmt and
|
||||
(
|
||||
// a statement whose preceding statement in the same list is reachable
|
||||
isReachable(getPreviousStmt(s))
|
||||
or
|
||||
// the post statement of a `for` loop whose body is entered
|
||||
exists(ForStmt f | s = f.getPost() and isReachable(f.getBody().getAStmt()))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,18 +88,13 @@ predicate allowlist(Stmt s) {
|
||||
forall(Expr retval | retval = ret.getAnExpr() | isAllowedReturnValue(retval))
|
||||
)
|
||||
or
|
||||
// statements in an `if false { ... }` and similar
|
||||
exists(IfStmt is, ControlFlow::ConditionGuardNode iffalse, Expr cond, boolean b |
|
||||
iffalse.getCondition() = is.getCond() and
|
||||
iffalse = s.getFirstControlFlowNode().getAPredecessor() and
|
||||
cond.getBoolValue() = b and
|
||||
iffalse.ensures(DataFlow::exprNode(cond), b.booleanNot())
|
||||
)
|
||||
// statements deliberately made unreachable by a constant condition, such as the code
|
||||
// following `if true { return }`
|
||||
exists(getPreviousStmt(s).(IfStmt).getCond().getBoolValue())
|
||||
}
|
||||
|
||||
from Stmt s, ControlFlow::Node fst
|
||||
from Stmt s
|
||||
where
|
||||
fst = s.getFirstControlFlowNode() and
|
||||
not exists(nonGuardPredecessor(fst)) and
|
||||
firstUnreachableStmt(s) and
|
||||
not allowlist(s)
|
||||
select s, "This statement is unreachable."
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
## 1.6.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query `go/unhandled-writable-file-close` ("Writable file handle closed without error handling") now produces fewer false positives. A deferred call to `Close` that is preceded on every execution path by a handled call to `Sync` on the same file handle is no longer flagged.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.6.5
|
||||
lastReleaseVersion: 1.6.4
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-queries
|
||||
version: 1.6.5
|
||||
version: 1.6.5-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -1 +1 @@
|
||||
| main.go:23:3:23:13 | assignment to field Status | main.go:23:17:23:21 | "200" |
|
||||
| main.go:23:3:23:21 | assign:0 ... = ... | main.go:23:17:23:21 | "200" |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
| file://:0:0:0:0 | [summary param] -1 in Clone |
|
||||
| file://:0:0:0:0 | [summary param] -1 in Write |
|
||||
| file://:0:0:0:0 | [summary param] -1 in WriteProxy |
|
||||
| main.go:18:12:18:14 | SSA def(req) |
|
||||
| main.go:18:12:18:14 | argument corresponding to req |
|
||||
| main.go:18:103:26:1 | SSA def(req) |
|
||||
| main.go:18:103:26:1 | arg:0 block statement |
|
||||
| main.go:20:5:20:7 | req |
|
||||
| main.go:20:5:20:7 | req [postupdate] |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| main.go:29:2:29:4 | assignment to err | main.go:29:9:29:31 | call to test1 |
|
||||
| main.go:29:2:29:31 | assign:0 ... := ... | main.go:29:9:29:31 | call to test1 |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| main.go:10:2:12:3 | ... := ...[0] | This Pam transaction may not be secure. |
|
||||
| main.go:10:2:12:3 | extract:0 ... := ... | This Pam transaction may not be secure. |
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
edges
|
||||
| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:10:12:10:24 | call to Query | DivideByZero.go:11:27:11:32 | param1 | provenance | |
|
||||
| DivideByZero.go:11:2:11:33 | ... := ...[0] | DivideByZero.go:12:16:12:20 | value | provenance | |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | DivideByZero.go:12:16:12:20 | value | provenance | |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:17:12:17:24 | call to Query | DivideByZero.go:18:11:18:24 | type conversion | provenance | |
|
||||
| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | provenance | |
|
||||
| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:24:12:24:24 | call to Query | DivideByZero.go:25:31:25:36 | param1 | provenance | |
|
||||
| DivideByZero.go:25:2:25:45 | ... := ...[0] | DivideByZero.go:26:16:26:20 | value | provenance | |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | DivideByZero.go:26:16:26:20 | value | provenance | |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:31:12:31:24 | call to Query | DivideByZero.go:32:33:32:38 | param1 | provenance | |
|
||||
| DivideByZero.go:32:2:32:43 | ... := ...[0] | DivideByZero.go:33:16:33:20 | value | provenance | |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | DivideByZero.go:33:16:33:20 | value | provenance | |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:38:12:38:24 | call to Query | DivideByZero.go:39:32:39:37 | param1 | provenance | |
|
||||
| DivideByZero.go:39:2:39:46 | ... := ...[0] | DivideByZero.go:40:16:40:20 | value | provenance | |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | DivideByZero.go:40:16:40:20 | value | provenance | |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:54:12:54:24 | call to Query | DivideByZero.go:55:11:55:24 | type conversion | provenance | |
|
||||
| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | provenance | |
|
||||
@@ -34,7 +34,7 @@ models
|
||||
nodes
|
||||
| DivideByZero.go:10:12:10:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:10:12:10:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:11:2:11:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:12:16:12:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:17:12:17:16 | selection of URL | semmle.label | selection of URL |
|
||||
@@ -43,17 +43,17 @@ nodes
|
||||
| DivideByZero.go:19:16:19:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:24:12:24:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:24:12:24:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:25:2:25:45 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:26:16:26:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:31:12:31:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:31:12:31:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:32:2:32:43 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:33:16:33:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:38:12:38:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:38:12:38:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:39:2:39:46 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:40:16:40:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:54:12:54:16 | selection of URL | semmle.label | selection of URL |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user