Compare commits

..

41 Commits

Author SHA1 Message Date
Owen Mansel-Chan
cae623d669 Test changes to be checked 2026-06-22 23:09:27 +01:00
Owen Mansel-Chan
326fa74b21 Update query for unreachable statements 2026-06-22 23:09:25 +01:00
Owen Mansel-Chan
138a1c3c99 Fix calls for defer statements 2026-06-22 23:09:23 +01:00
Owen Mansel-Chan
13bf978f64 Go CFG: run deferred calls at function exit in LIFO order
Model `defer`ed calls so the call runs at function exit rather than inline
at the `defer` statement, reproducing the previous control-flow semantics:

- Add a per-defer "defer-invoke" node for the deferred call.
- deferExitStep wires normal-exit predecessors (return nodes and body
  fall-through) through the active deferred-call invocations in
  last-in-first-out order, then on to the normal exit target (the
  result-read epilogue for named results, or the normal exit node).
- The chain is reachability-gated using the defer-free successor relation
  (succIgnoringDeferExit / isInOrderNode), so only deferred calls that were
  actually registered on a path are run on that path.
- overridesCallableBodyExit / overridesCallableEndAbruptCompletion suppress
  the default body-exit and return routing for functions containing
  `defer`, so the epilogue is interposed instead.
2026-06-22 23:09:21 +01:00
Owen Mansel-Chan
449732a5fe Shared CFG: add hooks for reachability-gated exit epilogue
Add opt-in InputSig2 predicates to support a function-exit epilogue whose
placement depends on reachability (such as Go's deferred calls, run at
exit in last-in-first-out order):

- deferExitStep: language-provided exit-epilogue edges, wired into
  explicitStep but excluded from the defer-free reachability.
- overridesCallableBodyExit: suppresses the default fall-through edge from
  a body's "after" node to the normal exit, so the epilogue can be
  interposed on fall-through paths.

To let a language compute the reachability gate for those edges without
observing them (and without a non-monotonic cycle through reachable):

- explicitStep is split into explicitStepCommon (defer-free) plus
  deferExitStep, and defaultCfg now negates explicitStepCommon so default
  evaluation does not depend on deferExitStep.
- succIgnoringDeferExit exposes the defer-free successor relation, typed
  over PreControlFlowNode so it does not depend on reachable.
- getASuccessorIgnoringDeferredExit exposes the same relation as a
  ControlFlowNode member for general use.
- isInOrderNode exposes a structural, reachability-free node-identity test
  for use inside the negations a language needs when computing its gate.
- EntryNodeImpl is no longer private, so a language can identify the entry
  node over PreControlFlowNode.

All InputSig2 additions default to none(), leaving other languages
unchanged.
2026-06-22 23:09:19 +01:00
Owen Mansel-Chan
f5eef7d3d7 Go CFG: anchor result-read epilogue on Normal Exit via new hooks 2026-06-22 23:09:17 +01:00
Owen Mansel-Chan
28afda1726 Shared CFG: add callableExitStep hook for routing epilogue tails to exit nodes 2026-06-22 23:09:15 +01:00
Owen Mansel-Chan
db8b2cff07 Allow overriding endAbruptCompletion for callables 2026-06-22 23:09:13 +01:00
Owen Mansel-Chan
3cd6a279d0 Include implicit type switch var in CFG 2026-06-22 23:09:11 +01:00
Owen Mansel-Chan
0f6bccf208 accept test changes 2026-06-22 23:09:10 +01:00
Owen Mansel-Chan
7039942a66 Fix CFG for expressionless switch statements 2026-06-22 23:09:08 +01:00
Owen Mansel-Chan
2453482003 Accept changes 2026-06-22 23:09:06 +01:00
Owen Mansel-Chan
de96f6ceac Fix ConditionGuardNode 2026-06-22 23:09:04 +01:00
Owen Mansel-Chan
c37f235031 Accept test output change names 2026-06-22 23:09:02 +01:00
Owen Mansel-Chan
8908dc4a6e Restore ConditionGuardNode 2026-06-22 23:09:00 +01:00
Owen Mansel-Chan
53a6afa218 Fix treatment of ParenExpr 2026-06-22 23:08:58 +01:00
Owen Mansel-Chan
0dfa9d72b1 Add Go CFG consistency query 2026-06-22 23:08:56 +01:00
Owen Mansel-Chan
6997936a83 Go: update expected node names 2026-06-22 23:08:54 +01:00
Owen Mansel-Chan
8debf965ac Use shared CFG getIfInit 2026-06-22 23:08:52 +01:00
Owen Mansel-Chan
8099b255af Fix lit-init nodes
There was a loop in the definitions which meant nothing ever got made
2026-06-22 23:08:51 +01:00
Owen Mansel-Chan
68a4131523 Fix range loop CFG 2026-06-22 23:08:49 +01:00
Owen Mansel-Chan
b56342533e update function-entry additional nodes 2026-06-22 23:08:47 +01:00
Owen Mansel-Chan
134cc48c75 Restore ExprNode for FuncLit 2026-06-22 23:08:45 +01:00
Owen Mansel-Chan
016c53ccbd Accept change in test output
To determine that test9 can't return normally, you have to use the fact
that test5 can't return normally. This would make CFG construction
recursive, which would be bad for performance. Therefore we accept the
limitation that we cannot detect that test9 can't return normally, and
we change the test output.
2026-06-22 23:08:43 +01:00
Owen Mansel-Chan
9b63398874 Fix empty switch statements 2026-06-22 23:08:41 +01:00
Owen Mansel-Chan
0244d809d1 Control flow shouldn't enter another callable 2026-06-22 23:08:39 +01:00
Owen Mansel-Chan
d582d68afd Fix CFG for return instructions 2026-06-22 23:08:37 +01:00
Owen Mansel-Chan
9b35117475 Produce CFG nodes for more reference expressions, like selector bases 2026-06-22 23:08:35 +01:00
Owen Mansel-Chan
642e567e48 Fix global value numbering calculation 2026-06-22 23:08:33 +01:00
Owen Mansel-Chan
8a62e874ca Include receivers in parameter init 2026-06-22 23:08:31 +01:00
Owen Mansel-Chan
13d4eb6933 Fix CFG for range loop 2026-06-22 23:08:29 +01:00
Owen Mansel-Chan
22ca59d190 Fix CFG for select statements 2026-06-22 23:08:27 +01:00
Owen Mansel-Chan
32a6187434 Use shared CFG implementation of for loops 2026-06-22 23:08:26 +01:00
Owen Mansel-Chan
f9953630a7 Do not include comments in the CFG 2026-06-22 23:08:24 +01:00
Owen Mansel-Chan
0deb94ac2d Fix edges to function exit with result variables 2026-06-22 23:08:22 +01:00
Owen Mansel-Chan
f8c2f2cbd9 Tweak getEnclosingCallable 2026-06-22 23:08:20 +01:00
Owen Mansel-Chan
984a880089 Model non-returning functions in CFG 2026-06-22 23:08:18 +01:00
Owen Mansel-Chan
1c62580835 Create cfg node for child of ParenExpr 2026-06-22 23:08:16 +01:00
Owen Mansel-Chan
99330a65a7 Add go/print-cfg 2026-06-22 23:08:14 +01:00
Owen Mansel-Chan
fc055a8699 Initial shared CFG library instantiation for Go 2026-06-22 23:08:12 +01:00
Owen Mansel-Chan
65513b8cd2 Incidental fix to CaseClause.getAnExpr() 2026-06-22 23:08:09 +01:00
2873 changed files with 64354 additions and 38802 deletions

2
.github/labeler.yml vendored
View File

@@ -20,7 +20,7 @@ JS:
Kotlin:
- java/kotlin-extractor/**/*
- java/ql/test-kotlin/**/*
- java/ql/test-kotlin*/**/*
Python:
- python/**/*

View File

@@ -28,7 +28,8 @@
/swift/extractor/ @github/codeql-swift @github/code-scanning-language-coverage
/misc/codegen/ @github/codeql-swift
/java/kotlin-extractor/ @github/codeql-kotlin @github/code-scanning-language-coverage
/java/ql/test-kotlin/ @github/codeql-kotlin
/java/ql/test-kotlin1/ @github/codeql-kotlin
/java/ql/test-kotlin2/ @github/codeql-kotlin
# Experimental CodeQL cryptography
**/experimental/**/quantum/ @github/ps-codeql

View File

@@ -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")

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.38
lastReleaseVersion: 0.4.37

View File

@@ -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

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.39-dev
version: 0.4.38-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.30
lastReleaseVersion: 0.6.29

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.31-dev
version: 0.6.30-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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 |

View File

@@ -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

View File

@@ -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.

View File

@@ -1,4 +0,0 @@
---
category: deprecated
---
* Models-as-data flow summaries now use fully qualified field names (for example, `MyNamespace::MyStruct::myField`) instead of unqualified field names such as `myField`. We recommend updating existing flow summaries to use fully qualified field names. Unqualified field names are still supported, but that support will be removed in a future release.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* Removed support for using variables as sources and sinks in models-as-data. Users of this feature should convert such sources and sinks to models defined using the QL language.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 11.0.0
lastReleaseVersion: 10.2.0

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 11.0.1-dev
version: 10.2.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -931,6 +931,31 @@ private Element interpretElement0(
signature = "" and
elementSpec(namespace, type, subtypes, name, signature, _)
)
or
// Member variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
member.getName() = name and
member = classWithMember.getAMember() and
namedClass.hasQualifiedName(namespace, type) and
result = member
|
// field declared in the named type or a subtype of it (or an extension of any)
subtypes = true and
classWithMember = namedClass.getADerivedClass*()
or
// field declared directly in the named type (or an extension of it)
subtypes = false and
classWithMember = namedClass
)
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
subtypes = false and
result = any(GlobalOrNamespaceVariable v | v.hasQualifiedName(namespace, name))
}
cached

View File

@@ -6,7 +6,6 @@ private import cpp as Cpp
private import codeql.dataflow.internal.FlowSummaryImpl
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific as DataFlowImplSpecific
private import semmle.code.cpp.dataflow.ExternalFlow
@@ -21,22 +20,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
class SinkBase = Void;
class FlowSummaryCallBase = CallInstruction;
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) }
FlowSummaryCallBase getASourceCall(SummarizedCallableBase sc) {
result.getStaticCallTarget() = sc
}
DataFlowCallable getSummarizedCallableAsDataFlowCallable(SummarizedCallableBase c) {
result.asSummarizedCallable() = c
}
DataFlowCallable getSourceCallEnclosingCallable(FlowSummaryCallBase call) {
result.asSourceCallable() = call.getEnclosingFunction()
}
ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
@@ -45,10 +30,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex())
}
ParameterPosition getFlowSummaryParameterPosition(ReturnKind rk) {
result = TFlowSummaryPosition(rk)
}
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
string encodeArgumentPosition(ArgumentPosition pos) { result = pos.toString() }
@@ -59,24 +40,12 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(rk.(NormalReturnKind).getIndirectionIndex())
}
bindingset[namespace, type, base]
private string formatQualifiedName(string namespace, string type, string base) {
if namespace = ""
then result = type + "::" + base
else result = namespace + "::" + type + "::" + base
}
string encodeContent(ContentSet cs, string arg) {
exists(FieldContent c, string namespace, string type, string base |
exists(FieldContent c |
cs.isSingleton(c) and
// FieldContent indices have 0 for the address, 1 for content, so we need to subtract one.
result = "Field" and
c.getField().hasQualifiedName(namespace, type, base)
|
arg = repeatStars(c.getIndirectionIndex() - 1) + formatQualifiedName(namespace, type, base)
or
// TODO: This disjunct can be removed once we stop supporting unqualified field names.
arg = repeatStars(c.getIndirectionIndex() - 1) + base
arg = repeatStars(c.getIndirectionIndex() - 1) + c.getField().getName()
)
or
exists(ElementContent ec |
@@ -133,22 +102,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) {
result.getStaticCallTarget().getUnderlyingCallable() = sc
}
Node getSourceOutNode(Input::FlowSummaryCallBase call, ReturnKind rk) {
exists(IndirectReturnOutNode out | result = out |
out.getCallInstruction() = call and
pragma[only_bind_out](rk.(NormalReturnKind).getIndirectionIndex()) =
pragma[only_bind_out](out.getIndirectionIndex())
)
}
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }
@@ -261,11 +218,40 @@ module SourceSinkInterpretationInput implements
/** Provides additional sink specification logic. */
bindingset[c]
predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) { none() }
predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) {
// Allow variables to be picked as output nodes.
exists(Node n, Element ast |
n = node.asNode() and
ast = mid.asElement()
|
c = "" and
n.asExpr().(VariableAccess).getTarget() = ast
)
}
/** Provides additional source specification logic. */
bindingset[c]
predicate interpretInput(string c, InterpretNode mid, InterpretNode node) { none() }
predicate interpretInput(string c, InterpretNode mid, InterpretNode node) {
exists(Node n, Element ast, VariableAccess e |
n = node.asNode() and
ast = mid.asElement() and
e.getTarget() = ast
|
// Allow variables to be picked as input nodes.
// We could simply do this as `e = n.asExpr()`, but that would not allow
// us to pick `x` as a sink in an example such as `x = source()` (but
// only subsequent uses of `x`) since the variable access on `x` doesn't
// actually load the value of `x`. So instead, we pick the instruction
// node corresponding to the generated `StoreInstruction` and use the
// expression associated with the destination instruction. This means
// that the `x` in `x = source()` can be marked as an input.
c = "" and
exists(StoreInstruction store |
store.getDestinationAddress().getUnconvertedResultExpression() = e and
n.asInstruction() = store
)
)
}
}
module Private {

View File

@@ -1534,8 +1534,12 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
result = this.getSummaryNode().getSummarizedCallable()
}
/**
* Gets the enclosing callable. For a `FlowSummaryNode` this is always the
* summarized function this node is part of.
*/
override DataFlowCallable getEnclosingCallable() {
result = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode())
result.asSummarizedCallable() = this.getSummarizedCallable()
}
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }

View File

@@ -561,21 +561,6 @@ class SummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
}
}
/** An argument node that re-enters return output as input to a flow summary. */
private class FlowSummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
private CallInstruction callInstruction;
private ReturnKind rk;
FlowSummaryArgumentNode() {
this.getSummaryNode() = FlowSummaryImpl::Private::summaryArgumentNode(callInstruction, rk)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.asCallInstruction() = callInstruction and
pos = TFlowSummaryPosition(rk)
}
}
/** A parameter position represented by an integer. */
class ParameterPosition = Position;
@@ -631,18 +616,6 @@ class IndirectionPosition extends Position, TIndirectionPosition {
final override int getIndirectionIndex() { result = indirectionIndex }
}
class FlowSummaryPosition extends Position, TFlowSummaryPosition {
ReturnKind rk;
FlowSummaryPosition() { this = TFlowSummaryPosition(rk) }
override string toString() { result = "write to: " + rk.toString() }
override int getArgumentIndex() { none() }
final override int getIndirectionIndex() { result = rk.getIndirectionIndex() }
}
newtype TPosition =
TDirectPosition(int argumentIndex) {
exists(any(CallInstruction c).getArgument(argumentIndex))
@@ -661,8 +634,7 @@ newtype TPosition =
p = f.getParameter(argumentIndex) and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
)
} or
TFlowSummaryPosition(ReturnKind rk) { FlowSummaryImpl::Private::relevantFlowSummaryPosition(rk) }
}
private newtype TReturnKind =
TNormalReturnKind(int indirectionIndex) {
@@ -1406,8 +1378,6 @@ predicate nodeIsHidden(Node n) {
n instanceof InitialGlobalValue
or
n instanceof SsaSynthNode
or
n.(FlowSummaryNode).getSummaryNode().isHidden()
}
predicate neverSkipInPathGraph(Node n) {

View File

@@ -158,7 +158,7 @@ private module Cached {
model = ""
or
// models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
}

View File

@@ -67,7 +67,7 @@ private module Cached {
model = ""
or
// models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
or
// object->field conflation for content that is a `TaintInheritingContent`.

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,3 @@
## 1.6.5
No user-facing changes.
## 1.6.4
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.6.5
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.6.5
lastReleaseVersion: 1.6.4

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.6.6-dev
version: 1.6.5-dev
groups:
- cpp
- queries

View File

@@ -1,2 +1 @@
query: jsf/4.13 Functions/AV Rule 107.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
jsf/4.13 Functions/AV Rule 107.ql

View File

@@ -1,2 +1 @@
query: Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql

View File

@@ -48,7 +48,7 @@ void test1()
void test2()
{
Lock<Mutex> myLock(); // $ Alert[cpp/function-in-block] // BAD (interpreted as a function declaration, this does nothing)
Lock<Mutex> myLock(); // BAD (interpreted as a function declaration, this does nothing)
// ...
}
@@ -62,14 +62,14 @@ void test3()
void test4()
{
Lock<Mutex>(myMutex); // $ Alert[cpp/local-variable-hides-global-variable] // BAD (creates an uninitialized variable called `myMutex`, probably not intended)
Lock<Mutex>(myMutex); // BAD (creates an uninitialized variable called `myMutex`, probably not intended)
// ...
}
void test5()
{
Lock<Mutex> myLock(Mutex); // $ Alert[cpp/function-in-block] // BAD (interpreted as a function declaration, this does nothing)
Lock<Mutex> myLock(Mutex); // BAD (interpreted as a function declaration, this does nothing)
// ...
}
@@ -86,7 +86,7 @@ public:
void test7()
{
Lock<Mutex>(memberMutex); // $ MISSING: Alert // BAD (creates an uninitialized variable called `memberMutex`, probably not intended) [NOT DETECTED]
Lock<Mutex>(memberMutex); // BAD (creates an uninitialized variable called `memberMutex`, probably not intended) [NOT DETECTED]
// ...
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql

View File

@@ -19,7 +19,7 @@ void test1(int p)
{
sys_somesystemcall(&p);
unsafe_put_user(123, &p); // $ MISSING: Alert // BAD [NOT DETECTED]
unsafe_put_user(123, &p); // BAD [NOT DETECTED]
}
void test2(int p)
@@ -40,7 +40,7 @@ void test3()
sys_somesystemcall(&v);
unsafe_put_user(123, &v); // $ MISSING: Alert // BAD [NOT DETECTED]
unsafe_put_user(123, &v); // BAD [NOT DETECTED]
}
void test4()
@@ -68,7 +68,7 @@ void test5()
sys_somesystemcall(&myData);
unsafe_put_user(123, &(myData.x)); // $ MISSING: Alert // BAD [NOT DETECTED]
unsafe_put_user(123, &(myData.x)); // BAD [NOT DETECTED]
}
void test6()

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql

View File

@@ -3,6 +3,6 @@ void workFunction_0(char *s) {
char buf[80], buf1[8];
if(len<0) return;
memset(buf,0,len); //GOOD
memset(buf1,0,len1); // $ Alert //BAD
memset(buf1,0,len1); //BAD
if(len1<0) return;
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-078/WordexpTainted.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-078/WordexpTainted.ql

View File

@@ -19,14 +19,14 @@ enum {
int wordexp(const char *restrict s, wordexp_t *restrict p, int flags);
int main(int argc, char** argv) { // $ Source
int main(int argc, char** argv) {
char *filePath = argv[2];
{
// BAD: the user string is injected directly into `wordexp` which performs command substitution
wordexp_t we;
wordexp(filePath, &we, 0); // $ Alert
wordexp(filePath, &we, 0);
}
{

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql

View File

@@ -20,7 +20,7 @@ void myFclose(FILE * fmy)
int main(int argc, char *argv[])
{
fe = fopen("myFile.txt", "wt");
fclose(fe); // $ Alert // BAD
fclose(fe); // BAD
fe = fopen("myFile.txt", "wt");
myFclose(fe); // GOOD
return 0;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql

View File

@@ -11,7 +11,7 @@ void workFunction_0(char *s) {
while(intIndex > 2)
{
buf[intIndex] = 1;
int intIndex; // $ Alert // BAD
int intIndex; // BAD
intIndex--;
}
intIndex = 10;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-1240/CustomCryptographicPrimitive.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-1240/CustomCryptographicPrimitive.ql

View File

@@ -8,7 +8,7 @@ int strlen(const char *string);
// the following function is homebrew crypto written for this test. This is a bad algorithm
// on multiple levels and should never be used in cryptography.
void encryptString(char *string, unsigned int key) { // $ Alert
void encryptString(char *string, unsigned int key) {
char *ptr = string;
int len = strlen(string);
@@ -27,7 +27,7 @@ void encryptString(char *string, unsigned int key) { // $ Alert
// the following function is homebrew crypto written for this test. This is a bad algorithm
// on multiple levels and should never be used in cryptography.
void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int dataSize, unsigned int key[2]) { // $ Alert
void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int dataSize, unsigned int key[2]) {
unsigned int state[2];
unsigned int t;
@@ -48,7 +48,7 @@ void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int d
// the following function resembles an implementation of the AES "mix columns"
// step. It is not accurate, efficient or safe and should never be used in
// cryptography.
void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) { // $ Alert
void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) {
// The "mix columns" step takes four bytes as inputs. Each byte represents a
// polynomial with 8 one-bit coefficients, e.g. input bits 00001101
// represent the polynomial x^3 + x^2 + 1. Arithmetic is reduced modulo
@@ -80,7 +80,7 @@ void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) { // $ Alert
// the following function resembles initialization of an S-box as may be done
// in an implementation of DES, AES and other encryption algorithms. It is not
// accurate, efficient or safe and should never be used in cryptography.
void init_aes_sbox(unsigned char data[256]) { // $ Alert
void init_aes_sbox(unsigned char data[256]) {
// initialize `data` in a loop using lots of ^, ^= and << operations and
// a few fixed constants.
unsigned int state = 0x12345678;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql

View File

@@ -63,7 +63,7 @@ static void badTest1(const char* ptr)
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 4)) > 0; len-=ret) { // $ Alert // BAD:we can get unpredictable results
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 4)) > 0; len-=ret) { // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
@@ -73,7 +73,7 @@ static void badTest2(const char* ptr)
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, sizeof(wchar_t))) > 0; len-=ret) { // $ Alert // BAD:we can get unpredictable results
for (wchar_t wc; (ret = mbtowc(&wc, ptr, sizeof(wchar_t))) > 0; len-=ret) { // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
@@ -103,7 +103,7 @@ static void badTest3(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, MB_CUR_MAX); // $ Alert // BAD
ret = mbtowc(wc, ptr, MB_CUR_MAX); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -120,7 +120,7 @@ static void badTest4(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, 16); // $ Alert // BAD
ret = mbtowc(wc, ptr, 16); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -137,7 +137,7 @@ static void badTest5(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, sizeof(wchar_t)); // $ Alert // BAD
ret = mbtowc(wc, ptr, sizeof(wchar_t)); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -155,7 +155,7 @@ static void badTest6(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, wc_len); // $ Alert // BAD
ret = mbtowc(wc, ptr, wc_len); // BAD
if (ret <0)
if (checkErrors()) {
++ptr;
@@ -178,7 +178,7 @@ static void badTest7(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, len); // $ Alert // BAD
ret = mbtowc(wc, ptr, len); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -194,7 +194,7 @@ static void badTest8(const char* ptr,wchar_t *wc)
int len;
len = strlen(ptr);
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, len); // $ Alert // BAD
ret = mbtowc(wc, ptr, len); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)

View File

@@ -25,8 +25,8 @@ void* calloc (size_t num, size_t size);
void* malloc (size_t size);
static void badTest1(void *src, int size) {
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // $ Alert // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // $ Alert // BAD
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // BAD
}
void goodTest2(){
wchar_t src[] = L"0123456789ABCDEF";
@@ -42,7 +42,7 @@ void goodTest2(){
static void badTest2(){
wchar_t src[] = L"0123456789ABCDEF";
char dst[16];
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // $ Alert // BAD
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // BAD
printf("%s\n", dst);
}
static void goodTest3(){
@@ -55,7 +55,7 @@ static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // $ Alert // BAD
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
static void goodTest4(){
char src[] = "0123456789ABCDEF";
@@ -67,13 +67,13 @@ static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc(size + 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // $ Alert // BAD
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
static int goodTest5(void *src){
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 0, 0, 0); // GOOD
}
static int badTest5 (void *src) {
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // $ Alert // BAD
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // BAD
}
static void goodTest6(WCHAR *src)
{
@@ -90,6 +90,6 @@ static void goodTest6(WCHAR *src)
static void badTest6(WCHAR *src)
{
char dst[5] ="";
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // $ Alert // BAD
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // BAD
printf("%s\n", dst);
}

View File

@@ -12,11 +12,11 @@ size_t mbsrtowcs(wchar_t *wcstr,const char *mbstr,size_t count, mbstate_t *mbsta
static void badTest1(void *src, int size) {
mbstowcs((wchar_t*)src,(char*)src,size); // $ Alert // BAD
mbstowcs((wchar_t*)src,(char*)src,size); // BAD
_locale_t locale;
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // $ Alert // BAD
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // BAD
mbstate_t *mbstate;
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // $ Alert // BAD
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // BAD
}
static void goodTest2(){
char src[] = "0123456789ABCDEF";
@@ -32,7 +32,7 @@ static void goodTest2(){
static void badTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
mbstowcs(dst, src,16); // $ Alert // BAD
mbstowcs(dst, src,16); // BAD
printf("%s\n", dst);
}
static void goodTest3(){
@@ -45,7 +45,7 @@ static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
mbstowcs(dst, src,size+1); // $ Alert // BAD
mbstowcs(dst, src,size+1); // BAD
}
static void goodTest4(){
char src[] = "0123456789ABCDEF";
@@ -57,13 +57,13 @@ static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc(size + 1);
mbstowcs(dst, src,size+1); // $ Alert // BAD
mbstowcs(dst, src,size+1); // BAD
}
static int goodTest5(void *src){
return mbstowcs(NULL, (char*)src,NULL); // GOOD
}
static int badTest5 (void *src) {
return mbstowcs(NULL, (char*)src,3); // $ Alert // BAD
return mbstowcs(NULL, (char*)src,3); // BAD
}
static void goodTest6(void *src){
wchar_t dst[5];
@@ -77,6 +77,6 @@ static void goodTest6(void *src){
}
static void badTest6(void *src){
wchar_t dst[5];
mbstowcs(dst, (char*)src,260); // $ Alert // BAD
mbstowcs(dst, (char*)src,260); // BAD
printf("%s\n", dst);
}

View File

@@ -13,7 +13,7 @@ static size_t badTest1(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( cb < sizeof(dst) )
dst[cb++]=*src++; // $ Alert // BAD
dst[cb++]=*src++; // BAD
return _mbclen(dst);
}
static void goodTest2(unsigned char *src){
@@ -33,7 +33,7 @@ static void badTest2(unsigned char *src){
unsigned char dst[50];
while( cb < sizeof(dst) )
{
_mbccpy(dst+cb,src); // $ Alert // BAD
_mbccpy(dst+cb,src); // BAD
cb+=_mbclen(src);
src=_mbsinc(src);
}
@@ -44,5 +44,5 @@ static void goodTest3(){
}
static void badTest3(){
wchar_t name[50];
name[sizeof(name) - 1] = L'\0'; // $ Alert // BAD
name[sizeof(name) - 1] = L'\0'; // BAD
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql

View File

@@ -10,31 +10,31 @@ void test()
int y = getAnInt();
char *buffer1 = (char *)malloc(x + y); // GOOD
char *buffer2 = (char *)malloc(x * y); // $ Alert // BAD
char *buffer2 = (char *)malloc(x * y); // BAD
int *buffer3 = (int *)malloc(x * sizeof(int)); // GOOD
int *buffer4 = (int *)malloc(x * y * sizeof(int)); // $ Alert // BAD
int *buffer4 = (int *)malloc(x * y * sizeof(int)); // BAD
if ((x <= 1000) && (y <= 1000))
{
char *buffer5 = (char *)malloc(x * y); // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]
char *buffer5 = (char *)malloc(x * y); // GOOD [FALSE POSITIVE]
}
size_t size1 = x * y; // $ Source
char *buffer5 = (char *)malloc(size1); // $ Alert // BAD
size_t size1 = x * y;
char *buffer5 = (char *)malloc(size1); // BAD
size_t size2 = x;
size2 *= y;
char *buffer6 = (char *)malloc(size2); // $ MISSING: Alert // BAD [NOT DETECTED]
char *buffer6 = (char *)malloc(size2); // BAD [NOT DETECTED]
char *buffer7 = new char[x * 10]; // GOOD
char *buffer8 = new char[x * y]; // $ Alert // BAD
char *buffer9 = new char[x * x]; // $ Alert // BAD
char *buffer8 = new char[x * y]; // BAD
char *buffer9 = new char[x * x]; // BAD
}
// --- custom allocators ---
void *MyMalloc1(size_t size) { return malloc(size); } // $ Alert // [additional detection here]
void *MyMalloc1(size_t size) { return malloc(size); } // [additional detection here]
void *MyMalloc2(size_t size);
void customAllocatorTests()
@@ -42,6 +42,6 @@ void customAllocatorTests()
int x = getAnInt();
int y = getAnInt();
char *buffer1 = (char *)MyMalloc1(x * y); // $ Alert Source // BAD
char *buffer2 = (char *)MyMalloc2(x * y); // $ Alert // BAD
char *buffer1 = (char *)MyMalloc1(x * y); // BAD
char *buffer2 = (char *)MyMalloc2(x * y); // BAD
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-190/DangerousUseOfTransformationAfterOperation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-190/DangerousUseOfTransformationAfterOperation.ql

View File

@@ -6,17 +6,17 @@ void functionWork(char aA[10],unsigned int aUI) {
int aI;
aI = (aUI*8)/10; // GOOD
aI = aUI*8; // $ Alert // BAD
aI = aUI*8; // BAD
aP = aA+aI;
aI = (int)aUI*8; // GOOD
aL = (unsigned long)(aI*aI); // $ Alert // BAD
aL = (unsigned long)(aI*aI); // BAD
aL = ((unsigned long)aI*aI); // GOOD
testCall((unsigned long)(aI*aI)); // $ Alert // BAD
testCall((unsigned long)(aI*aI)); // BAD
testCall(((unsigned long)aI*aI)); // GOOD
if((unsigned long)(aI*aI) > aL) // $ Alert // BAD
if((unsigned long)(aI*aI) > aL) // BAD
return;
if(((unsigned long)aI*aI) > aL) // GOOD
return;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql

View File

@@ -15,49 +15,49 @@ void test()
unsigned short b1 = getAnUnsignedShort();
unsigned short c1 = getAnUnsignedShort();
if (a+b>c) a = c-b; // $ Alert // BAD
if (a+b>c) { a = c-b; } // $ Alert // BAD
if (b+a>c) a = c-b; // $ Alert // BAD
if (b+a>c) { a = c-b; } // $ Alert // BAD
if (c>a+b) a = c-b; // $ Alert // BAD
if (c>a+b) { a = c-b; } // $ Alert // BAD
if (c>b+a) a = c-b; // $ Alert // BAD
if (c>b+a) { a = c-b; } // $ Alert // BAD
if (a+b>c) a = c-b; // BAD
if (a+b>c) { a = c-b; } // BAD
if (b+a>c) a = c-b; // BAD
if (b+a>c) { a = c-b; } // BAD
if (c>a+b) a = c-b; // BAD
if (c>a+b) { a = c-b; } // BAD
if (c>b+a) a = c-b; // BAD
if (c>b+a) { a = c-b; } // BAD
if (a+b>=c) a = c-b; // $ Alert // BAD
if (a+b>=c) { a = c-b; } // $ Alert // BAD
if (b+a>=c) a = c-b; // $ Alert // BAD
if (b+a>=c) { a = c-b; } // $ Alert // BAD
if (c>=a+b) a = c-b; // $ Alert // BAD
if (c>=a+b) { a = c-b; } // $ Alert // BAD
if (c>=b+a) a = c-b; // $ Alert // BAD
if (c>=b+a) { a = c-b; } // $ Alert // BAD
if (a+b>=c) a = c-b; // BAD
if (a+b>=c) { a = c-b; } // BAD
if (b+a>=c) a = c-b; // BAD
if (b+a>=c) { a = c-b; } // BAD
if (c>=a+b) a = c-b; // BAD
if (c>=a+b) { a = c-b; } // BAD
if (c>=b+a) a = c-b; // BAD
if (c>=b+a) { a = c-b; } // BAD
if (a+b<c) a = c-b; // $ Alert // BAD
if (a+b<c) { a = c-b; } // $ Alert // BAD
if (b+a<c) a = c-b; // $ Alert // BAD
if (b+a<c) { a = c-b; } // $ Alert // BAD
if (c<a+b) a = c-b; // $ Alert // BAD
if (c<a+b) { a = c-b; } // $ Alert // BAD
if (c<b+a) a = c-b; // $ Alert // BAD
if (c<b+a) { a = c-b; } // $ Alert // BAD
if (a+b<c) a = c-b; // BAD
if (a+b<c) { a = c-b; } // BAD
if (b+a<c) a = c-b; // BAD
if (b+a<c) { a = c-b; } // BAD
if (c<a+b) a = c-b; // BAD
if (c<a+b) { a = c-b; } // BAD
if (c<b+a) a = c-b; // BAD
if (c<b+a) { a = c-b; } // BAD
if (a+b<=c) a = c-b; // $ Alert // BAD
if (a+b<=c) { a = c-b; } // $ Alert // BAD
if (b+a<=c) a = c-b; // $ Alert // BAD
if (b+a<=c) { a = c-b; } // $ Alert // BAD
if (c<=a+b) a = c-b; // $ Alert // BAD
if (c<=a+b) { a = c-b; } // $ Alert // BAD
if (c<=b+a) a = c-b; // $ Alert // BAD
if (c<=b+a) { a = c-b; } // $ Alert // BAD
if (a+b<=c) a = c-b; // BAD
if (a+b<=c) { a = c-b; } // BAD
if (b+a<=c) a = c-b; // BAD
if (b+a<=c) { a = c-b; } // BAD
if (c<=a+b) a = c-b; // BAD
if (c<=a+b) { a = c-b; } // BAD
if (c<=b+a) a = c-b; // BAD
if (c<=b+a) { a = c-b; } // BAD
if (a+b>d) a = d-b; // $ Alert // BAD
if (a+b>d) a = d-b; // BAD
if (a+(double)b>c) a = c-b; // GOOD
if (a+(-x)>c) a = c-(-y); // GOOD
if (a+b>c) { b++; a = c-b; } // GOOD
if (a+d>c) a = c-d; // GOOD
if (a1+b1>c1) a1 = c1-b1; // GOOD
if (a+b<=c) { /* ... */ } else { a = c-b; } // $ Alert // BAD
if (a+b<=c) { return; } a = c-b; // $ Alert // BAD
if (a+b<=c) { /* ... */ } else { a = c-b; } // BAD
if (a+b<=c) { return; } a = c-b; // BAD
}

View File

@@ -1,2 +1 @@
query: experimental/Likely Bugs/ArrayAccessProductFlow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Likely Bugs/ArrayAccessProductFlow.ql

View File

@@ -1,13 +1,13 @@
char *malloc(int size);
void test1(int size) {
char *arr = malloc(size); // $ Source
char *arr = malloc(size);
for (int i = 0; i < size; i++) {
arr[i] = 0; // GOOD
}
for (int i = 0; i <= size; i++) {
arr[i] = i; // $ Alert // BAD
arr[i] = i; // BAD
}
}
@@ -18,7 +18,7 @@ typedef struct {
array_t mk_array(int size) {
array_t arr;
arr.p = malloc(size); // $ Source
arr.p = malloc(size);
arr.size = size;
return arr;
@@ -32,7 +32,7 @@ void test2(int size) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // $ Alert // BAD
arr.p[i] = i; // BAD
}
}
@@ -42,7 +42,7 @@ void test3_callee(array_t arr) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // $ Alert // BAD
arr.p[i] = i; // BAD
}
}
@@ -52,7 +52,7 @@ void test3(int size) {
void test4(int size) {
array_t arr;
arr.p = malloc(size); // $ Source
arr.p = malloc(size);
arr.size = size;
for (int i = 0; i < arr.size; i++) {
@@ -60,13 +60,13 @@ void test4(int size) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // $ Alert // BAD
arr.p[i] = i; // BAD
}
}
array_t *mk_array_p(int size) {
array_t *arr = (array_t*) malloc(sizeof(array_t));
arr->p = malloc(size); // $ Source
arr->p = malloc(size);
arr->size = size;
return arr;
@@ -80,7 +80,7 @@ void test5(int size) {
}
for (int i = 0; i <= arr->size; i++) {
arr->p[i] = i; // $ Alert // BAD
arr->p[i] = i; // BAD
}
}
@@ -90,7 +90,7 @@ void test6_callee(array_t *arr) {
}
for (int i = 0; i <= arr->size; i++) {
arr->p[i] = i; // $ Alert // BAD
arr->p[i] = i; // BAD
}
}
@@ -105,6 +105,6 @@ void test7(int size) {
}
for (char *p = arr; p <= arr + size; p++) {
*p = 0; // $ MISSING: Alert // BAD [NOT DETECTED]
*p = 0; // BAD [NOT DETECTED]
}
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql

View File

@@ -32,60 +32,60 @@ void testOneArray(OneArray *arr) {
void testBig(BigArray *arr) {
arr->buf[MAX_SIZE-1] = 0; // GOOD
arr->buf[MAX_SIZE] = 0; // $ Alert // BAD
arr->buf[MAX_SIZE+1] = 0; // $ Alert // BAD
arr->buf[MAX_SIZE] = 0; // BAD
arr->buf[MAX_SIZE+1] = 0; // BAD
for(int i = 0; i < MAX_SIZE; i++) {
arr->buf[i] = 0; // GOOD
}
for(int i = 0; i <= MAX_SIZE; i++) {
arr->buf[i] = 0; // $ Alert // BAD
arr->buf[i] = 0; // BAD
}
}
void testFields(ArrayAndFields *arr) {
arr->buf[MAX_SIZE-1] = 0; // GOOD
arr->buf[MAX_SIZE] = 0; // $ Alert // BAD?
arr->buf[MAX_SIZE+1] = 0; // $ Alert // BAD?
arr->buf[MAX_SIZE] = 0; // BAD?
arr->buf[MAX_SIZE+1] = 0; // BAD?
for(int i = 0; i < MAX_SIZE; i++) {
arr->buf[i] = 0; // GOOD
}
for(int i = 0; i <= MAX_SIZE; i++) {
arr->buf[i] = 0; // $ Alert // BAD?
arr->buf[i] = 0; // BAD?
}
for(int i = 0; i < MAX_SIZE+2; i++) {
arr->buf[i] = 0; // $ Alert // BAD?
arr->buf[i] = 0; // BAD?
}
// is this different if it's a memcpy?
}
void assignThroughPointer(int *p) { // $ Sink
void assignThroughPointer(int *p) {
*p = 0; // ??? should the result go at a flow source?
}
void addToPointerAndAssign(int *p) {
p[MAX_SIZE-1] = 0; // GOOD
p[MAX_SIZE] = 0; // $ Alert // BAD
p[MAX_SIZE] = 0; // BAD
}
void testInterproc(BigArray *arr) {
assignThroughPointer(&arr->buf[MAX_SIZE-1]); // GOOD
assignThroughPointer(&arr->buf[MAX_SIZE]); // $ Alert // BAD
assignThroughPointer(&arr->buf[MAX_SIZE]); // BAD
addToPointerAndAssign(arr->buf); // $ Source
addToPointerAndAssign(arr->buf);
}
#define MAX_SIZE_BYTES 4096
void testCharIndex(BigArray *arr) {
char *charBuf = (char*) arr->buf; // $ Source
char *charBuf = (char*) arr->buf;
charBuf[MAX_SIZE_BYTES - 1] = 0; // GOOD
charBuf[MAX_SIZE_BYTES] = 0; // $ Alert // BAD
charBuf[MAX_SIZE_BYTES] = 0; // BAD
}
void testEqRefinement() {
@@ -125,7 +125,7 @@ void testStackAllocated() {
char *arr[MAX_SIZE];
for(int i = 0; i <= MAX_SIZE; i++) {
arr[i] = 0; // $ Alert // BAD
arr[i] = 0; // BAD
}
}
@@ -133,18 +133,18 @@ int strncmp(const char*, const char*, int);
char testStrncmp2(char *arr) {
if(strncmp(arr, "<test>", 6) == 0) {
arr += 6; // $ Alert
arr += 6;
}
return *arr; // $ SPURIOUS: Sink // GOOD [FALSE POSITIVE]
return *arr; // GOOD [FALSE POSITIVE]
}
void testStrncmp1() {
char asdf[5];
testStrncmp2(asdf); // $ Source
testStrncmp2(asdf);
}
void countdownBuf1(int **p) {
*--(*p) = 1; // $ SPURIOUS: Sink // GOOD [FALSE POSITIVE]
*--(*p) = 1; // GOOD [FALSE POSITIVE]
*--(*p) = 2; // GOOD
*--(*p) = 3; // GOOD
*--(*p) = 4; // GOOD
@@ -153,7 +153,7 @@ void countdownBuf1(int **p) {
void countdownBuf2() {
int buf[4];
int *x = buf + 4; // $ Alert
int *x = buf + 4;
countdownBuf1(&x);
}
@@ -182,7 +182,7 @@ int countdownLength1(int *p, int len) {
}
int callCountdownLength() {
int buf[6];
return countdownLength1(buf, 6);
@@ -192,7 +192,7 @@ int countdownLength2() {
int buf[6];
int len = 6;
int *p = buf;
if(len % 8) {
return -1;
}
@@ -215,10 +215,10 @@ int countdownLength2() {
void pointer_size_larger_than_array_element_size() {
unsigned char buffer[100]; // getByteSize() = 100
int *ptr = (int *)buffer; // $ Source // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
int *ptr = (int *)buffer; // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
ptr[24] = 0; // GOOD: writes bytes 96, 97, 98, 99
ptr[25] = 0; // $ Alert // BAD: writes bytes 100, 101, 102, 103
ptr[25] = 0; // BAD: writes bytes 100, 101, 102, 103
}
struct vec2 { int x, y; };
@@ -226,10 +226,10 @@ struct vec3 { int x, y, z; };
void pointer_size_smaller_than_array_element_size_but_does_not_divide_it() {
vec3 array[3]; // getByteSize() = 9 * sizeof(int)
vec2 *ptr = (vec2 *)array; // $ Source // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
vec2 *ptr = (vec2 *)array; // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
ptr[3] = vec2{}; // GOOD: writes ints 6, 7
ptr[4] = vec2{}; // $ Alert // BAD: writes ints 8, 9
ptr[4] = vec2{}; // BAD: writes ints 8, 9
}
void pointer_size_larger_than_array_element_size_and_does_not_divide_it() {
@@ -258,7 +258,7 @@ void call_use(unsigned char* p, int n) {
if(n == 3) {
unsigned char x = p[0];
unsigned char y = p[1];
unsigned char z = p[2]; // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
unsigned char z = p[2]; // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
use(x, y, z);
}
}
@@ -283,7 +283,7 @@ void test_call_use2() {
call_call_use(buffer1,1);
unsigned char buffer2[2];
call_call_use(buffer2,2); // $ Source
call_call_use(buffer2,2);
unsigned char buffer3[3];
call_call_use(buffer3,3);
@@ -296,7 +296,7 @@ int guardingCallee(int *arr, int size) {
int sum;
for (int i = 0; i < size; i++) {
sum += arr[i]; // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE] - guarded by size
sum += arr[i]; // GOOD [FALSE POSITIVE] - guarded by size
}
return sum;
}
@@ -304,9 +304,9 @@ int guardingCallee(int *arr, int size) {
int guardingCaller() {
int arr1[MAX_SIZE];
guardingCallee(arr1, MAX_SIZE);
int arr2[10];
guardingCallee(arr2, 10); // $ Source
guardingCallee(arr2, 10);
}
// simplified md5 padding
@@ -319,10 +319,10 @@ void correlatedCondition(int num) {
end = temp + 56;
}
else if (num < 64) {
end = temp + 64; // $ SPURIOUS: Alert // GOOD [FALSE POSITVE]
end = temp + 64; // GOOD [FALSE POSITVE]
}
char *temp2 = temp + num;
while(temp2 != end) { // $ Sink
while(temp2 != end) {
*temp2 = 0;
temp2++;
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql

View File

@@ -9,7 +9,7 @@ int main(int argc, char *argv[])
{
//umask(0022);
FILE *fp;
fp = fopen("myFile.txt","w"); // $ Alert // BAD
fp = fopen("myFile.txt","w"); // BAD
//chmod("myFile.txt",0644);
fprintf(fp,"%s\n","data to file");
fclose(fp);

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql

View File

@@ -10,8 +10,8 @@ int main(int argc, char *argv[])
{
FILE *fp;
char buf[128];
fp = fopen("myFile.txt","r+"); // $ MISSING: Alert // BAD [NOT DETECTED]
fgets(buf,128,fp);
fp = fopen("myFile.txt","r+"); // BAD [NOT DETECTED]
fgets(buf,128,fp);
fprintf(fp,"%s\n","data to file");
fclose(fp);
return 0;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-243/IncorrectChangingWorkingDirectory.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-243/IncorrectChangingWorkingDirectory.ql

View File

@@ -9,13 +9,13 @@ int chdir(char *path);
void exit(int status);
int funTest1(){
if (chroot("/myFold/myTmp") == -1) { // $ Alert // BAD
if (chroot("/myFold/myTmp") == -1) { // BAD
exit(-1);
}
return 0;
}
int funTest2(){
int funTest2(){
if (chdir("/myFold/myTmp") == -1) { // GOOD
exit(-1);
}
@@ -25,8 +25,8 @@ int funTest2(){
return 0;
}
int funTest3(){
chdir("/myFold/myTmp"); // $ Alert // BAD
int funTest3(){
chdir("/myFold/myTmp"); // BAD
return 0;
}
int main(int argc, char *argv[])

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql

View File

@@ -6,7 +6,7 @@ int fclose(FILE *stream);
void funcTest1()
{
umask(0666); // $ Alert // BAD
umask(0666); // BAD
FILE *fe;
fe = fopen("myFile.txt", "wt");
fclose(fe);
@@ -27,7 +27,7 @@ void funcTest2(int mode)
FILE *fe;
fe = fopen("myFile.txt", "wt");
fclose(fe);
chmod("myFile.txt",0555-mode); // $ Alert // BAD
chmod("myFile.txt",0555-mode); // BAD
}
void funcTest2g(int mode)

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-285/PamAuthorization.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-285/PamAuthorization.ql

View File

@@ -26,7 +26,7 @@ bool PamAuthBad(const std::string &username_in,
return false;
}
err = pam_authenticate(pamh, 0); // $ Alert
err = pam_authenticate(pamh, 0);
if (err != PAM_SUCCESS)
return err;

View File

@@ -7,7 +7,7 @@ namespace std{
CURLOPT_URL,
CURLOPT_SSL_VERIFYHOST,
CURLOPT_SSL_VERIFYPEER
};
};
CURL *curl_easy_init();
void curl_easy_cleanup(CURL *handle);
@@ -22,8 +22,8 @@ char host[] = "codeql.com";
void bad(void) {
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0); // $ Alert
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0); // $ Alert
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
curl_easy_perform(curl.get());
}
@@ -31,7 +31,7 @@ void bad(void) {
void good(void) {
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 2);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
curl_easy_perform(curl.get());
}
@@ -40,3 +40,4 @@ int main(int c, char** argv){
bad();
good();
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-295/CurlSSL.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-295/CurlSSL.ql

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql

View File

@@ -54,7 +54,7 @@ void file()
FILE *file;
// BAD: write zipcode to file in cleartext
fputs(theZipcode, file); // $ Alert
fputs(theZipcode, file);
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);
@@ -71,15 +71,15 @@ int main(int argc, char **argv)
char *buff4;
// BAD: write medical to buffer in cleartext
sprintf(buff1, "%s", medical); // $ Alert Source
sprintf(buff1, "%s", medical);
// BAD: write medical to buffer in cleartext
char *temp = medical; // $ Source
sprintf(buff2, "%s", temp); // $ Alert
char *temp = medical;
sprintf(buff2, "%s", temp);
// BAD: write medical to buffer in cleartext
char *buff5 = func(medical); // $ Source
sprintf(buff3, "%s", buff5); // $ Alert
char *buff5 = func(medical);
sprintf(buff3, "%s", buff5);
char *buff6 = encrypt(medical);
// GOOD: encrypt first
@@ -93,10 +93,10 @@ void stream()
ofstream mystream;
// BAD: write zipcode to file in cleartext
mystream << "the zipcode is: " << theZipcode; // $ Alert Source
mystream << "the zipcode is: " << theZipcode;
// BAD: write zipcode to file in cleartext
(mystream << "the zipcode is: ").write(theZipcode, strlen(theZipcode)); // $ Alert
(mystream << "the zipcode is: ").write(theZipcode, strlen(theZipcode));
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql

View File

@@ -44,13 +44,13 @@ int getSize2(int type) {
int badTestf1(int type, int met) {
int is = getSize(type);
if (met == 1) return 123 / is; // $ Alert // BAD
else return 123 / getSize2(type); // $ Alert // BAD
if (met == 1) return 123 / is; // BAD
else return 123 / getSize2(type); // BAD
}
int badTestf2(int type) {
int is;
is = getSize(type);
return 123 / is; // $ Alert // BAD
return 123 / is; // BAD
}
int badTestf3(int type, int met) {
@@ -58,31 +58,31 @@ int badTestf3(int type, int met) {
is = getSize(type);
switch (met) {
case 1:
if (is >= 0) return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
if (is >= 0) return 123 / is; // BAD [NOT DETECTED]
case 2:
if (0 == is) return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
if (0 == is) return 123 / is; // BAD [NOT DETECTED]
case 3:
if (!is & 123 / is) // $ Alert // BAD
if (!is & 123 / is) // BAD
return 123;
case 4:
if (!is | 123 / is) // $ Alert // BAD
if (!is | 123 / is) // BAD
return 123;
case 5:
if (123 / is || !is) // $ Alert // BAD
if (123 / is || !is) // BAD
return 123;
case 6:
if (123 / is && !is) // $ Alert // BAD
if (123 / is && !is) // BAD
return 123;
case 7:
if (!is) return 123 / is; // $ Alert // BAD
if (!is) return 123 / is; // BAD
case 8:
if (is > -1) return 123 / is; // $ Alert // BAD
if (is > -1) return 123 / is; // BAD
case 9:
if (is < 2) return 123 / is; // $ Alert // BAD
if (is < 2) return 123 / is; // BAD
}
if (is != 0) return -1;
if (is == 0) type += 1;
return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
return 123 / is; // BAD [NOT DETECTED]
}
int goodTestf3(int type, int met) {
@@ -92,7 +92,7 @@ int goodTestf3(int type, int met) {
case 1:
if (is < 0) return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
@@ -112,10 +112,10 @@ int goodTestf3a(int type, int met) {
if (is < 0)
return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
if (!is || 123 / is) // GOOD
return 123;
}
return 1;
@@ -125,20 +125,20 @@ int badTestf4(int type) {
int is = getSize(type);
int d;
d = type * is;
return 123 / d; // $ Alert // BAD
return 123 / d; // BAD
}
int badTestf5(int type) {
int is = getSize(type);
int d;
d = is / type;
return 123 / d; // $ Alert // BAD
return 123 / d; // BAD
}
int badTestf6(int type) {
int is = getSize(type);
int d;
d = is / type;
return type * 123 / d; // $ Alert // BAD
return type * 123 / d; // BAD
}
int badTestf7(int type, int met) {
@@ -150,7 +150,7 @@ int badTestf7(int type, int met) {
return 123 / is; // GOOD
}
quit:
return 123 / is; // $ Alert // BAD
return 123 / is; // BAD
}
int goodTestf7(int type, int met) {
@@ -169,8 +169,8 @@ int goodTestf7(int type, int met) {
int badTestf8(int type) {
int is = getSize(type);
type /= is; // $ Alert // BAD
type %= is; // $ Alert // BAD
type /= is; // BAD
type %= is; // BAD
return type;
}
@@ -184,7 +184,7 @@ float getSizeFloat(float type) {
}
float badTestf9(float type) {
float is = getSizeFloat(type);
return 123 / is; // $ Alert // BAD
return 123 / is; // BAD
}
float goodTestf9(float type) {
float is = getSizeFloat(type);
@@ -196,18 +196,18 @@ int badTestf10(int type) {
int out = type;
int is = getSize(type);
if (is > -2) {
out /= 123 / (is + 1); // $ Alert // BAD
out /= 123 / (is + 1); // BAD
}
if (is > 0) {
return 123 / (is - 1); // $ Alert // BAD
return 123 / (is - 1); // BAD
}
if (is <= 0) return 0;
return 123 / (is - 1); // $ Alert // BAD
return 123 / (is - 1); // BAD
return 0;
}
int badTestf11(int type) {
int is = getSize(type);
return 123 / (is - 3); // $ Alert // BAD
return 123 / (is - 3); // BAD
}
int goodTestf11(int type) {
@@ -223,7 +223,7 @@ int badTestf12(FILE * f) {
int a;
int ret = -1;
a = getc(f);
if (a == 0) ret = 123 / a; // $ MISSING: Alert // BAD [NOT DETECTED]
if (a == 0) ret = 123 / a; // BAD [NOT DETECTED]
return ret;
}
@@ -255,14 +255,14 @@ int badMySubDiv(int type, int is) {
void badTestf13(int type) {
int is = getSize(type);
badMyDiv(type, is); // $ Alert // BAD
badMyDiv(type, is - 2); // $ Alert // BAD
badMySubDiv(type, is); // $ Alert // BAD
badMyDiv(type, is); // BAD
badMyDiv(type, is - 2); // BAD
badMySubDiv(type, is); // BAD
goodMyDiv(type, is); // GOOD
if (is < 5)
badMySubDiv(type, is); // $ Alert // BAD
badMySubDiv(type, is); // BAD
if (is < 0)
badMySubDiv(type, is); // $ MISSING: Alert // BAD [NOT DETECTED]
badMySubDiv(type, is); // BAD [NOT DETECTED]
if (is > 5)
badMySubDiv(type, is); // GOOD
if (is == 0)
@@ -270,9 +270,9 @@ void badTestf13(int type) {
if (is > 0)
badMyDiv(type, is); // GOOD
if (is < 5)
badMyDiv(type, is - 3); // $ Alert // BAD
badMyDiv(type, is - 3); // BAD
if (is < 0)
badMyDiv(type, is + 1); // $ Alert // BAD
badMyDiv(type, is + 1); // BAD
if (is > 5)
badMyDiv(type, is - 3); // GOOD
}

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql

View File

@@ -13,7 +13,7 @@ int fclose(FILE *stream);
int funcTest1()
{
FILE *fp;
char *filename = tmpnam(NULL); // $ Alert // BAD
char *filename = tmpnam(NULL); // BAD
fp = fopen(filename,"w");
fprintf(fp,"%s\n","data to file");
fclose(fp);
@@ -39,7 +39,7 @@ int funcTest3()
FILE *fp;
char filename[80];
strcat(filename, "/tmp/tmp.name");
fp = fopen(filename,"w"); // $ MISSING: Alert // BAD [NOT DETECTED]
fp = fopen(filename,"w"); // BAD [NOT DETECTED]
fprintf(fp,"%s\n","data to file");
fclose(fp);
return 0;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql

View File

@@ -31,7 +31,7 @@ unsigned char * badResize_0(unsigned char * buffer,size_t currentSize,size_t new
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
}
return buffer;
}
@@ -60,7 +60,7 @@ unsigned char * badResize_1_0(unsigned char * buffer,size_t currentSize,size_t n
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
}
return buffer;
}
@@ -136,7 +136,7 @@ unsigned char * badResize_1_1(unsigned char * buffer,size_t currentSize,size_t n
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
}
if(!buffer)
aFakeFailed_1(1, 1);
@@ -183,7 +183,7 @@ unsigned char * badResize_2_0(unsigned char * buffer,size_t currentSize,size_t n
assert(buffer!=0);
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
}
return buffer;
}
@@ -279,7 +279,7 @@ unsigned char *goodResize_3_1(unsigned char *buffer, size_t currentSize, size_t
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
if (buffer == NULL)
{
free(tmp);
@@ -296,7 +296,7 @@ unsigned char *goodResize_3_2(unsigned char *buffer, size_t currentSize, size_t
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
tmp = (unsigned char *)realloc(tmp, newSize); // $ Alert
tmp = (unsigned char *)realloc(tmp, newSize);
if (tmp != 0)
{
buffer = tmp;
@@ -325,7 +325,7 @@ unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
}
if (cond)
{
@@ -339,7 +339,7 @@ unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
buffer = (unsigned char *)realloc(buffer, newSize);
assert(cond); // irrelevant
}
return buffer;

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-409/DecompressionBombs.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
experimental/Security/CWE/CWE-409/DecompressionBombs.ql

View File

@@ -15,12 +15,12 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
void brotli_test(int argc, const char **argv) {
uint8_t output[1024];
size_t output_size = sizeof(output);
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // $ Alert // BAD
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // BAD
size_t input_size = 1024;
const uint8_t *input_p = (const uint8_t*)argv[2];
uint8_t *output_p = output;
size_t out_size;
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // $ Alert // BAD
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // BAD
&output_p, &out_size);
}

View File

@@ -19,7 +19,7 @@ static int read_data(archive *ar) {
size_t size;
la_int64_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset); // $ Alert // BAD
int r = archive_read_data_block(ar, &buff, &size, &offset); // BAD
if (r == ARCHIVE_EOF)
return ARCHIVE_OK;
if (r < ARCHIVE_OK)

View File

@@ -4,7 +4,7 @@ void minizip_test(int argc, const char **argv);
void zlib_test(int argc, const char **argv);
void zstd_test(int argc, const char **argv);
int main(int argc, const char **argv) { // $ Source
int main(int argc, const char **argv) {
brotli_test(argc, argv);
libarchive_test(argc, argv);
minizip_test(argc, argv);

View File

@@ -14,7 +14,7 @@ void minizip_test(int argc, const char **argv) {
int32_t bytes_read;
char buf[4096];
while(true) {
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // $ Alert // BAD
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // BAD
if (bytes_read <= 0) {
break;
}
@@ -23,7 +23,7 @@ void minizip_test(int argc, const char **argv) {
void *zip_reader = mz_zip_reader_create();
mz_zip_reader_open_file(zip_reader, argv[1]);
mz_zip_reader_goto_first_entry(zip_reader);
mz_zip_reader_entry_save(zip_reader, 0, 0); // $ Alert // BAD
mz_zip_reader_entry_save(zip_reader, 0, 0); // BAD
UnzOpen(argv[3]); // $ Alert // BAD
UnzOpen(argv[3]); // BAD
}

Some files were not shown because too many files have changed in this diff Show More