mirror of
https://github.com/github/codeql.git
synced 2026-05-20 22:27:18 +02:00
Compare commits
1 Commits
rb/data-fl
...
tiferet/at
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7162f28641 |
13
.github/workflows/atm-check-queries-run.yml
vendored
13
.github/workflows/atm-check-queries-run.yml
vendored
@@ -1,13 +0,0 @@
|
||||
name: ATM Check Queries Run
|
||||
|
||||
# This check is required, therefore we must run it on all PRs, even if only Markdown has changed.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
hello-world:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: foo
|
||||
run: echo "Hello world"
|
||||
2
.github/workflows/qhelp-pr-preview.yml
vendored
2
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
id: changes
|
||||
run: |
|
||||
(git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.qhelp$' | grep -z -v '.inc.qhelp';
|
||||
git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename -z | xargs --null -rn1 git grep -z -l) |
|
||||
git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename | xargs --null -rn1 git grep -z -l) |
|
||||
grep -z '.qhelp$' | grep -z -v '^-' | sort -z -u > "${RUNNER_TEMP}/paths.txt"
|
||||
|
||||
- name: QHelp preview
|
||||
|
||||
27
.github/workflows/swift-autobuilder.yml
vendored
27
.github/workflows/swift-autobuilder.yml
vendored
@@ -1,27 +0,0 @@
|
||||
name: "Swift: Build and test Xcode autobuilder"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "swift/xcode-autobuilder/**"
|
||||
- "misc/bazel/**"
|
||||
- "*.bazel*"
|
||||
- .github/workflows/swift-autobuilder.yml
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
autobuilder:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- name: Build the Xcode autobuilder
|
||||
run: |
|
||||
bazel build //swift/xcode-autobuilder
|
||||
- name: Test the Xcode autobuilder
|
||||
run: |
|
||||
bazel test //swift/xcode-autobuilder/tests
|
||||
7
.github/workflows/swift-codegen.yml
vendored
7
.github/workflows/swift-codegen.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
branches:
|
||||
- main
|
||||
defaults:
|
||||
run:
|
||||
working-directory: swift
|
||||
|
||||
jobs:
|
||||
codegen:
|
||||
@@ -21,9 +18,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- uses: actions/setup-python@v3
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
name: Check that python code is properly formatted
|
||||
with:
|
||||
|
||||
@@ -28,9 +28,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- uses: actions/setup-python@v3
|
||||
- name: Build Swift extractor
|
||||
run: |
|
||||
bazel run //swift:create-extractor-pack
|
||||
|
||||
16
.github/workflows/swift-qltest.yml
vendored
16
.github/workflows/swift-qltest.yml
vendored
@@ -23,30 +23,16 @@ jobs:
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check QL formatting
|
||||
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
|
||||
qltest-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- name: Test qltest.sh
|
||||
run: |
|
||||
bazel test //swift/tools/test/qltest
|
||||
qltest:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-20.04, macos-latest ]
|
||||
os : [ubuntu-20.04, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: bazelbuild/setup-bazelisk@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: 'swift/.python-version'
|
||||
- name: Build Swift extractor
|
||||
run: |
|
||||
bazel run //swift:create-extractor-pack
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @github/codeql-java @github/codeql-go
|
||||
|
||||
# CodeQL tools and associated docs
|
||||
/docs/codeql/codeql-cli/ @github/codeql-cli-reviewers
|
||||
/docs/codeql/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
|
||||
/docs/codeql/ql-language-reference/ @github/codeql-frontend-reviewers
|
||||
/docs/codeql-cli/ @github/codeql-cli-reviewers
|
||||
/docs/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
|
||||
/docs/ql-language-reference/ @github/codeql-frontend-reviewers
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
|
||||
# QL for QL reviewers
|
||||
|
||||
@@ -33,9 +33,8 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForLibraries.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Common": [
|
||||
@@ -70,6 +69,7 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforlibraries/TaintTrackingImpl.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Consistency checks": [
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
## 0.4.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.4.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.4.2
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.2
|
||||
lastReleaseVersion: 0.4.0
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -137,7 +137,7 @@ private newtype TReturnKind =
|
||||
exists(IndirectReturnNode return, ReturnIndirectionInstruction returnInd |
|
||||
returnInd.hasIndex(argumentIndex) and
|
||||
return.getAddressOperand() = returnInd.getSourceAddressOperand() and
|
||||
indirectionIndex = return.getIndirectionIndex()
|
||||
indirectionIndex = return.getIndirectionIndex() - 1 // We subtract one because the return loads the value.
|
||||
)
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ class ReturnIndirectionNode extends IndirectReturnNode, ReturnNode {
|
||||
exists(int argumentIndex, ReturnIndirectionInstruction returnInd |
|
||||
returnInd.hasIndex(argumentIndex) and
|
||||
this.getAddressOperand() = returnInd.getSourceAddressOperand() and
|
||||
result = TIndirectReturnKind(argumentIndex, this.getIndirectionIndex()) and
|
||||
result = TIndirectReturnKind(argumentIndex, this.getIndirectionIndex() - 1) and
|
||||
hasNonInitializeParameterDef(returnInd.getIRVariable())
|
||||
)
|
||||
or
|
||||
@@ -241,7 +241,7 @@ private Instruction getANonConversionUse(Operand operand) {
|
||||
|
||||
/**
|
||||
* Gets the operand that represents the first use of the value of `call` following
|
||||
* a sequence of conversion-like instructions.
|
||||
* a sequnce of conversion-like instructions.
|
||||
*/
|
||||
predicate operandForfullyConvertedCall(Operand operand, CallInstruction call) {
|
||||
exists(getANonConversionUse(operand)) and
|
||||
@@ -254,7 +254,7 @@ predicate operandForfullyConvertedCall(Operand operand, CallInstruction call) {
|
||||
|
||||
/**
|
||||
* Gets the instruction that represents the first use of the value of `call` following
|
||||
* a sequence of conversion-like instructions.
|
||||
* a sequnce of conversion-like instructions.
|
||||
*
|
||||
* This predicate only holds if there is no suitable operand (i.e., no operand of a non-
|
||||
* conversion instruction) to use to represent the value of `call` after conversions.
|
||||
@@ -365,7 +365,7 @@ predicate jumpStep(Node n1, Node n2) {
|
||||
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
|
||||
exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store |
|
||||
nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and
|
||||
node2.getIndirectionIndex() = 1 and
|
||||
node2.getIndirectionIndex() = 0 and
|
||||
numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(),
|
||||
numberOfLoads)
|
||||
|
|
||||
@@ -465,20 +465,20 @@ predicate clearsContent(Node n, Content c) {
|
||||
predicate expectsContent(Node n, ContentSet c) { none() }
|
||||
|
||||
/** Gets the type of `n` used for type pruning. */
|
||||
DataFlowType getNodeType(Node n) {
|
||||
IRType getNodeType(Node n) {
|
||||
suppressUnusedNode(n) and
|
||||
result instanceof VoidType // stub implementation
|
||||
result instanceof IRVoidType // stub implementation
|
||||
}
|
||||
|
||||
/** Gets a string representation of a type returned by `getNodeType`. */
|
||||
string ppReprType(DataFlowType t) { none() } // stub implementation
|
||||
string ppReprType(IRType t) { none() } // stub implementation
|
||||
|
||||
/**
|
||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||
* a node of type `t1` to a node of type `t2`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||
predicate compatibleTypes(IRType t1, IRType t2) {
|
||||
any() // stub implementation
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ class DataFlowCallable = Cpp::Declaration;
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
class DataFlowType = Type;
|
||||
class DataFlowType = IRType;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends CallInstruction {
|
||||
|
||||
@@ -38,12 +38,13 @@ private module Cached {
|
||||
TVariableNode(Variable var) or
|
||||
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
|
||||
indirectionIndex =
|
||||
[1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())]
|
||||
[0 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType()) -
|
||||
1]
|
||||
} or
|
||||
TSsaPhiNode(Ssa::PhiNode phi) or
|
||||
TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) {
|
||||
Ssa::isModifiableByCall(operand) and
|
||||
indirectionIndex = [1 .. Ssa::countIndirectionsForCppType(operand.getLanguageType())]
|
||||
indirectionIndex = [0 .. Ssa::countIndirectionsForCppType(operand.getLanguageType()) - 1]
|
||||
} or
|
||||
TIndirectOperand(Operand op, int indirectionIndex) {
|
||||
Ssa::hasIndirectOperand(op, indirectionIndex)
|
||||
@@ -112,7 +113,7 @@ class Node extends TIRDataFlowNode {
|
||||
Declaration getFunction() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the type of this node. */
|
||||
DataFlowType getType() { none() } // overridden in subclasses
|
||||
IRType getType() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the instruction corresponding to this node, if any. */
|
||||
Instruction asInstruction() { result = this.(InstructionNode).getInstruction() }
|
||||
@@ -229,13 +230,7 @@ class Node extends TIRDataFlowNode {
|
||||
Expr asIndirectArgument() { result = this.asIndirectArgument(_) }
|
||||
|
||||
/** Gets the positional parameter corresponding to this node, if any. */
|
||||
Parameter asParameter() { result = this.asParameter(0) }
|
||||
|
||||
/**
|
||||
* Gets the uninitialized local variable corresponding to this node, if
|
||||
* any.
|
||||
*/
|
||||
LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() }
|
||||
Parameter asParameter() { result = asParameter(0) }
|
||||
|
||||
/**
|
||||
* Gets the positional parameter corresponding to the node that represents
|
||||
@@ -278,7 +273,7 @@ class Node extends TIRDataFlowNode {
|
||||
/**
|
||||
* Gets an upper bound on the type of this node.
|
||||
*/
|
||||
DataFlowType getTypeBound() { result = this.getType() }
|
||||
IRType getTypeBound() { result = this.getType() }
|
||||
|
||||
/** Gets the location of this element. */
|
||||
cached
|
||||
@@ -327,7 +322,7 @@ class InstructionNode extends Node, TInstructionNode {
|
||||
|
||||
override Declaration getFunction() { result = instr.getEnclosingFunction() }
|
||||
|
||||
override DataFlowType getType() { result = instr.getResultType() }
|
||||
override IRType getType() { result = instr.getResultIRType() }
|
||||
|
||||
final override Location getLocationImpl() { result = instr.getLocation() }
|
||||
|
||||
@@ -353,32 +348,13 @@ class OperandNode extends Node, TOperandNode {
|
||||
|
||||
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
|
||||
|
||||
override DataFlowType getType() { result = op.getType() }
|
||||
override IRType getType() { result = op.getIRType() }
|
||||
|
||||
final override Location getLocationImpl() { result = op.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = this.getOperand().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `t`, but stripped of the `n` outermost pointers, references, etc.
|
||||
*
|
||||
* For example, `stripPointers(int*&, 2)` is `int` and `stripPointers(int*, 0)` is `int*`.
|
||||
*/
|
||||
private Type stripPointers(Type t, int n) {
|
||||
result = t and n = 0
|
||||
or
|
||||
result = stripPointers(t.(PointerType).getBaseType(), n - 1)
|
||||
or
|
||||
result = stripPointers(t.(ArrayType).getBaseType(), n - 1)
|
||||
or
|
||||
result = stripPointers(t.(ReferenceType).getBaseType(), n - 1)
|
||||
or
|
||||
result = stripPointers(t.(PointerToMemberType).getBaseType(), n - 1)
|
||||
or
|
||||
result = stripPointers(t.(FunctionPointerIshType).getBaseType(), n - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: do not use.
|
||||
*
|
||||
@@ -394,6 +370,8 @@ class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override IRType getType() { result = fieldAddress.getIRType() }
|
||||
|
||||
FieldAddress getFieldAddress() { result = fieldAddress }
|
||||
|
||||
Field getUpdatedField() { result = fieldAddress.getField() }
|
||||
@@ -401,8 +379,10 @@ class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode {
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Node getPreUpdateNode() {
|
||||
// + 1 because we're storing into an lvalue, and the original node should be the rvalue of
|
||||
// the same address.
|
||||
hasOperandAndIndex(result, pragma[only_bind_into](fieldAddress).getObjectAddressOperand(),
|
||||
indirectionIndex)
|
||||
indirectionIndex + 1)
|
||||
}
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
@@ -431,7 +411,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||
|
||||
override DataFlowType getType() { result = this.getAnInput().getType() }
|
||||
override IRType getType() { result instanceof IRVoidType }
|
||||
|
||||
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
|
||||
|
||||
@@ -474,6 +454,8 @@ class SideEffectOperandNode extends Node, IndirectOperand {
|
||||
|
||||
override Function getFunction() { result = call.getEnclosingFunction() }
|
||||
|
||||
override IRType getType() { result instanceof IRVoidType }
|
||||
|
||||
Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() }
|
||||
}
|
||||
|
||||
@@ -496,6 +478,8 @@ class IndirectParameterNode extends Node, IndirectInstruction {
|
||||
|
||||
override Function getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||
|
||||
override IRType getType() { result instanceof IRVoidType }
|
||||
|
||||
override string toStringImpl() {
|
||||
result = this.getParameter().toString() + " indirection"
|
||||
or
|
||||
@@ -520,6 +504,8 @@ class IndirectReturnNode extends IndirectOperand {
|
||||
Operand getAddressOperand() { result = operand }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override IRType getType() { result instanceof IRVoidType }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,7 +536,9 @@ class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PostUpdate
|
||||
|
||||
override Function getFunction() { result = this.getCallInstruction().getEnclosingFunction() }
|
||||
|
||||
override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex) }
|
||||
override IRType getType() { result instanceof IRVoidType }
|
||||
|
||||
override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex + 1) }
|
||||
|
||||
override string toStringImpl() {
|
||||
// This string should be unique enough to be helpful but common enough to
|
||||
@@ -606,38 +594,6 @@ class IndirectReturnOutNode extends Node {
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
}
|
||||
|
||||
private PointerType getGLValueType(Type t, int indirectionIndex) {
|
||||
result.getBaseType() = stripPointers(t, indirectionIndex - 1)
|
||||
}
|
||||
|
||||
bindingset[isGLValue]
|
||||
private DataFlowType getTypeImpl(Type t, int indirectionIndex, boolean isGLValue) {
|
||||
if isGLValue = true
|
||||
then
|
||||
result = getGLValueType(t, indirectionIndex)
|
||||
or
|
||||
// Ideally, the above case would cover all glvalue cases. However, consider the case where
|
||||
// the database consists only of:
|
||||
// ```
|
||||
// void test() {
|
||||
// int* x;
|
||||
// x = nullptr;
|
||||
// }
|
||||
// ```
|
||||
// and we want to compute the type of `*x` in the assignment `x = nullptr`. Here, `x` is an lvalue
|
||||
// of type int* (which morally is an int**). So when we call `getTypeImpl` it will be with the
|
||||
// parameters:
|
||||
// - t = int*
|
||||
// - indirectionIndex = 1 (when we want to model the dataflow node corresponding to *x)
|
||||
// - isGLValue = true
|
||||
// In this case, `getTypeImpl(t, indirectionIndex, isGLValue)` should give back `int**`. In this
|
||||
// case, however, `int**` does not exist in the database. So instead we return int* (which is
|
||||
// wrong, but at least we have a type).
|
||||
not exists(getGLValueType(t, indirectionIndex)) and
|
||||
result = stripPointers(t, indirectionIndex - 1)
|
||||
else result = stripPointers(t, indirectionIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
@@ -659,11 +615,7 @@ class IndirectOperand extends Node, TIndirectOperand {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(boolean isGLValue | if operand.isGLValue() then isGLValue = true else isGLValue = false |
|
||||
result = getTypeImpl(operand.getType().getUnspecifiedType(), indirectionIndex, isGLValue)
|
||||
)
|
||||
}
|
||||
override IRType getType() { result = this.getOperand().getIRType() }
|
||||
|
||||
final override Location getLocationImpl() { result = this.getOperand().getLocation() }
|
||||
|
||||
@@ -672,25 +624,6 @@ class IndirectOperand extends Node, TIndirectOperand {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of an uninitialized local variable, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class UninitializedNode extends Node {
|
||||
LocalVariable v;
|
||||
|
||||
UninitializedNode() {
|
||||
exists(Ssa::Def def |
|
||||
def.getDefiningInstruction() instanceof UninitializedInstruction and
|
||||
Ssa::nodeToDefOrUse(this, def) and
|
||||
v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the uninitialized local variable corresponding to this node. */
|
||||
LocalVariable getLocalVariable() { result = v }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
@@ -712,11 +645,7 @@ class IndirectInstruction extends Node, TIndirectInstruction {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(boolean isGLValue | if instr.isGLValue() then isGLValue = true else isGLValue = false |
|
||||
result = getTypeImpl(instr.getResultType().getUnspecifiedType(), indirectionIndex, isGLValue)
|
||||
)
|
||||
}
|
||||
override IRType getType() { result = this.getInstruction().getResultIRType() }
|
||||
|
||||
final override Location getLocationImpl() { result = this.getInstruction().getLocation() }
|
||||
|
||||
@@ -746,7 +675,7 @@ predicate exprNodeShouldBeOperand(Node node, Expr e) {
|
||||
|
||||
/**
|
||||
* Holds if `load` is a `LoadInstruction` that is the result of evaluating `e`
|
||||
* and `node` is an `IndirectOperandNode` that should map `node.asExpr()` to `e`.
|
||||
* and `node` is an `IndirctOperandNode` that should map `node.asExpr()` to `e`.
|
||||
*
|
||||
* We map `e` to `node.asExpr()` when `node` semantically represents the
|
||||
* same value as `load`. A subsequent flow step will flow `node` to
|
||||
@@ -930,8 +859,6 @@ abstract class PostUpdateNode extends Node {
|
||||
* Gets the node before the state update.
|
||||
*/
|
||||
abstract Node getPreUpdateNode();
|
||||
|
||||
final override DataFlowType getType() { result = this.getPreUpdateNode().getType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -995,7 +922,7 @@ class VariableNode extends Node, TVariableNode {
|
||||
result = v
|
||||
}
|
||||
|
||||
override DataFlowType getType() { result = v.getType() }
|
||||
override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) }
|
||||
|
||||
final override Location getLocationImpl() { result = v.getLocation() }
|
||||
|
||||
@@ -1148,7 +1075,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
store.getDestinationAddressOperand() = address
|
||||
)
|
||||
or
|
||||
Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex)
|
||||
Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex - 1)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ Node callOutput(CallInstruction call, FunctionOutput output) {
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
exists(int index, int indirectionIndex |
|
||||
result.(IndirectArgumentOutNode).getArgumentIndex() = index and
|
||||
result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and
|
||||
result.(IndirectArgumentOutNode).getIndirectionIndex() + 1 = indirectionIndex and
|
||||
result.(IndirectArgumentOutNode).getCallInstruction() = call and
|
||||
output.isParameterDerefOrQualifierObject(index, indirectionIndex)
|
||||
)
|
||||
|
||||
@@ -100,7 +100,7 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
or
|
||||
// Is there partial flow from a source to this node?
|
||||
// This property will only be emitted if partial flow is enabled by overriding
|
||||
// `DataFlow::Configuration::explorationLimit()`.
|
||||
// `DataFlow::Configration::explorationLimit()`.
|
||||
key = "pflow" and
|
||||
result =
|
||||
strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
|
||||
@@ -11,9 +11,7 @@ private import DataFlowUtil
|
||||
* corresponding `(Indirect)OperandNode`.
|
||||
*/
|
||||
predicate ignoreOperand(Operand operand) {
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or
|
||||
operand instanceof MemoryOperand
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,7 @@ private module SourceVariables {
|
||||
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
override DataFlowType getType() { result = var.getType() }
|
||||
override DataFlowType getType() { result = var.getIRType() }
|
||||
}
|
||||
|
||||
class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable {
|
||||
@@ -48,7 +48,7 @@ private module SourceVariables {
|
||||
|
||||
override string toString() { result = call.toString() }
|
||||
|
||||
override DataFlowType getType() { result = call.getResultType() }
|
||||
override DataFlowType getType() { result = call.getResultIRType() }
|
||||
}
|
||||
|
||||
private newtype TSourceVariable =
|
||||
|
||||
@@ -71,7 +71,7 @@ abstract class CustomSignDef extends SignDef {
|
||||
* Concrete implementations extend one of the following subclasses:
|
||||
* - `ConstantSignExpr`, for expressions with a compile-time constant value.
|
||||
* - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands.
|
||||
* - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific
|
||||
* - `CustomsignExpr`, for expressions shose sign can be computed by a language-specific
|
||||
* implementation.
|
||||
*
|
||||
* If the same expression matches more than one of the above subclasses, the sign is computed as
|
||||
|
||||
@@ -11,7 +11,7 @@ private import experimental.semmle.code.cpp.semantic.Semantic
|
||||
predicate ignoreTypeRestrictions(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Workaround to track the sign of certain expressions even if the type of the expression is not
|
||||
* Workaround to track the sign of cetain expressions even if the type of the expression is not
|
||||
* numeric.
|
||||
*/
|
||||
predicate trackUnknownNonNumericExpr(SemExpr e) { none() }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.4.3-dev
|
||||
version: 0.4.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides the `LinkTarget` class representing linker invocations during the build process.
|
||||
* Proivdes the `LinkTarget` class representing linker invocations during the build process.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Class
|
||||
|
||||
@@ -144,7 +144,7 @@ class Variable extends Declaration, @variable {
|
||||
* `Variable.getInitializer()` to get the variable's initializer,
|
||||
* or use `Variable.getAnAssignedValue()` to get an expression that
|
||||
* is the right-hand side of an assignment or an initialization of
|
||||
* the variable.
|
||||
* the varible.
|
||||
*/
|
||||
Assignment getAnAssignment() { result.getLValue() = this.getAnAccess() }
|
||||
|
||||
@@ -173,7 +173,7 @@ class Variable extends Declaration, @variable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this variable is declared as part of a structured binding
|
||||
* Holds if this variable is declated as part of a structured binding
|
||||
* declaration. For example, `x` in `auto [x, y] = ...`.
|
||||
*/
|
||||
predicate isStructuredBinding() { is_structured_binding(underlyingElement(this)) }
|
||||
|
||||
@@ -76,7 +76,7 @@ class TypeBoundsAnalysis extends BufferWriteEstimationReason, TTypeBoundsAnalysi
|
||||
|
||||
/**
|
||||
* The estimation comes from non trivial bounds found via actual flow analysis,
|
||||
* but a widening approximation might have been used for variables in loops.
|
||||
* but a widening aproximation might have been used for variables in loops.
|
||||
* For example
|
||||
* ```
|
||||
* for (int i = 0; i < 10; ++i) {
|
||||
@@ -141,7 +141,7 @@ class AttributeFormattingFunction extends FormattingFunction {
|
||||
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
|
||||
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
|
||||
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
|
||||
* - `"?"` if the type cannot be determined. `outputParamIndex` is `-1`.
|
||||
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
|
||||
*/
|
||||
predicate primitiveVariadicFormatter(
|
||||
TopLevelFunction f, string type, int formatParamIndex, int outputParamIndex
|
||||
@@ -198,7 +198,7 @@ private predicate callsVariadicFormatter(
|
||||
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
|
||||
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
|
||||
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
|
||||
* - `"?"` if the type cannot be determined. `outputParamIndex` is `-1`.
|
||||
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
|
||||
*/
|
||||
predicate variadicFormatter(Function f, string type, int formatParamIndex, int outputParamIndex) {
|
||||
primitiveVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
|
||||
|
||||
@@ -12,7 +12,7 @@ private import internal.ConstantExprs
|
||||
* relation). The refinement manifests itself in two changes:
|
||||
*
|
||||
* - The successor relation on `BasicBlock`s uses `successors_adapted`
|
||||
* (instead of `successors_extended` used by `PrimitiveBasicBlock`s). Consequently,
|
||||
* (instead of `successors_extended` used by `PrimtiveBasicBlock`s). Consequently,
|
||||
* some edges between `BasicBlock`s may be removed. Example:
|
||||
* ```
|
||||
* x = 1; // s1
|
||||
|
||||
@@ -149,7 +149,7 @@ private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, Control
|
||||
/**
|
||||
* Basic block `pred` contains all or part of the condition belonging to a loop,
|
||||
* and there is an edge from `pred` to `succ` that concludes the condition.
|
||||
* If the edge corresponds with the loop condition being found to be `true`, then
|
||||
* If the edge corrseponds with the loop condition being found to be `true`, then
|
||||
* `skipsLoop` is `false`. Otherwise the edge corresponds with the loop condition
|
||||
* being found to be `false` and `skipsLoop` is `true`. Non-concluding edges
|
||||
* within a complex loop condition are not matched by this predicate.
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -1137,7 +1137,7 @@ class BuiltInOperationIsArray extends BuiltInOperation, @isarray {
|
||||
* A C++ `__array_rank` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
*
|
||||
* If known, returns the number of dimensions of an arrary type.
|
||||
* If known, returns the number of dimentsions of an arrary type.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct rank
|
||||
|
||||
@@ -494,7 +494,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
|
||||
* An initialization of a base class or member variable performed as part
|
||||
* of a constructor's explicit initializer list or implicit actions.
|
||||
*
|
||||
* This is a QL root class for representing various types of constructor
|
||||
* This is a QL root class for reprenting various types of constructor
|
||||
* initializations.
|
||||
*/
|
||||
class ConstructorInit extends Expr, @ctorinit {
|
||||
|
||||
@@ -779,7 +779,7 @@ class AlignofExprOperator extends AlignofOperator {
|
||||
/**
|
||||
* A C++11 `alignof` expression whose operand is a type name.
|
||||
* ```
|
||||
* bool proper_alignment = (alignof(T) == alignof(T[0]);
|
||||
* bool proper_alignment = (alingof(T) == alignof(T[0]);
|
||||
* ```
|
||||
*/
|
||||
class AlignofTypeOperator extends AlignofOperator {
|
||||
|
||||
@@ -451,7 +451,7 @@ class Expr extends StmtParent, @expr {
|
||||
// For performance, we avoid a full transitive closure over `getConversion`.
|
||||
// Since there can be several implicit conversions before and after an
|
||||
// explicit conversion, use `getImplicitlyConverted` to step over them
|
||||
// cheaply. Then, if there is an explicit conversion following the implicit
|
||||
// cheaply. Then, if there is an explicit conversion following the implict
|
||||
// conversion sequence, recurse to handle multiple explicit conversions.
|
||||
if this.getImplicitlyConverted().hasExplicitConversion()
|
||||
then result = this.getImplicitlyConverted().getConversion().getExplicitlyConverted()
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -163,9 +163,7 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) {
|
||||
sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode()
|
||||
}
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
@@ -838,13 +836,13 @@ private module Stage1 implements StageSig {
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableReturnPosOutNodeCandFwd1(
|
||||
predicate viableReturnPosOutNodeCandFwd1(
|
||||
DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
|
||||
) {
|
||||
fwdFlowReturnPosition(pos, _, config) and
|
||||
@@ -860,7 +858,7 @@ private module Stage1 implements StageSig {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate viableParamArgNodeCandFwd1(
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
|
||||
) {
|
||||
viableParamArgEx(call, p, arg) and
|
||||
@@ -907,7 +905,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlowState(FlowState state, Configuration config) {
|
||||
predicate revFlowState(FlowState state, Configuration config) {
|
||||
exists(NodeEx node |
|
||||
sinkNode(node, state, config) and
|
||||
revFlow(node, _, pragma[only_bind_into](config)) and
|
||||
@@ -999,7 +997,7 @@ private module Stage1 implements StageSig {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -1260,7 +1258,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* argument.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate fwdFlow(
|
||||
predicate fwdFlow(
|
||||
NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
fwdFlow0(node, state, cc, argAp, ap, config) and
|
||||
@@ -1484,7 +1482,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
* the access path of the returned value.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
additional predicate revFlow(
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow0(node, state, toReturn, returnAp, ap, config) and
|
||||
@@ -1662,7 +1660,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
predicate revFlow(NodeEx node, FlowState state, Configuration config) {
|
||||
revFlow(node, state, _, _, _, config)
|
||||
}
|
||||
|
||||
@@ -1675,13 +1673,11 @@ private module MkStage<StageSig PrevStage> {
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, Configuration config) {
|
||||
revFlow(node, _, _, _, _, config)
|
||||
}
|
||||
predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
revFlow(node, state, ap, config)
|
||||
}
|
||||
|
||||
@@ -1702,7 +1698,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
predicate consCand(TypedContent tc, Ap ap, Configuration config) {
|
||||
revConsCand(tc, ap, config) and
|
||||
validAp(ap, config)
|
||||
}
|
||||
@@ -1744,7 +1740,7 @@ private module MkStage<StageSig PrevStage> {
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate stats(
|
||||
predicate stats(
|
||||
boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
|
||||
) {
|
||||
fwd = true and
|
||||
@@ -2929,15 +2925,10 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = this.getASuccessorImpl()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathNodeImpl getANonHiddenSuccessor0() {
|
||||
result = this.getASuccessorIfHidden*() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
final PathNodeImpl getANonHiddenSuccessor() {
|
||||
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
|
||||
not this.isHidden()
|
||||
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
}
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
@@ -100,7 +100,7 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
or
|
||||
// Is there partial flow from a source to this node?
|
||||
// This property will only be emitted if partial flow is enabled by overriding
|
||||
// `DataFlow::Configuration::explorationLimit()`.
|
||||
// `DataFlow::Configration::explorationLimit()`.
|
||||
key = "pflow" and
|
||||
result =
|
||||
strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -64,7 +64,7 @@ private module Cached {
|
||||
or
|
||||
instr = reusedPhiInstruction(_) and
|
||||
// Check that the phi instruction is *not* degenerate, but we can't use
|
||||
// getDegeneratePhiOperand in the first stage with phi instructions
|
||||
// getDegeneratePhiOperand in the first stage with phi instyructions
|
||||
not exists(
|
||||
unique(OldIR::PhiInputOperand operand |
|
||||
operand = instr.(OldIR::PhiInstruction).getAnInputOperand() and
|
||||
@@ -718,7 +718,7 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hypothetical use one instruction past the end of
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
|
||||
@@ -172,7 +172,7 @@ deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
|
||||
* aliased SSA stage.
|
||||
* asliased SSA stage.
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -542,7 +542,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
* The IR translation of an argument side effect for `*this` on a call, where there is no `Expr`
|
||||
* object that represents the `this` argument.
|
||||
*
|
||||
* The applies only to constructor calls, as the AST has exploit qualifier `Expr`s for all other
|
||||
* The applies only to constructor calls, as the AST has explioit qualifier `Expr`s for all other
|
||||
* calls to non-static member functions.
|
||||
*/
|
||||
class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect,
|
||||
|
||||
@@ -2177,7 +2177,7 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
/**
|
||||
* The IR translation of the ternary conditional operator (`a ? b : c`).
|
||||
* For this version, we expand the condition as a `TranslatedCondition`, rather than a
|
||||
* `TranslatedExpr`, to simplify the control flow in the presence of short-circuit logical operators.
|
||||
* `TranslatedExpr`, to simplify the control flow in the presence of short-ciruit logical operators.
|
||||
*/
|
||||
class TranslatedTernaryConditionalExpr extends TranslatedConditionalExpr, ConditionContext {
|
||||
TranslatedTernaryConditionalExpr() { not expr.isTwoOperand() }
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -64,7 +64,7 @@ private module Cached {
|
||||
or
|
||||
instr = reusedPhiInstruction(_) and
|
||||
// Check that the phi instruction is *not* degenerate, but we can't use
|
||||
// getDegeneratePhiOperand in the first stage with phi instructions
|
||||
// getDegeneratePhiOperand in the first stage with phi instyructions
|
||||
not exists(
|
||||
unique(OldIR::PhiInputOperand operand |
|
||||
operand = instr.(OldIR::PhiInstruction).getAnInputOperand() and
|
||||
@@ -718,7 +718,7 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hypothetical use one instruction past the end of
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
|
||||
@@ -12,7 +12,7 @@ private Type getDecayedType(Type type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the specified variable is a structured binding with a non-reference
|
||||
* Holds if the sepcified variable is a structured binding with a non-reference
|
||||
* type.
|
||||
*/
|
||||
predicate isNonReferenceStructuredBinding(Variable v) {
|
||||
|
||||
@@ -209,7 +209,7 @@ private predicate aClassFile(Class c, File file) { c.getDefinitionLocation().get
|
||||
|
||||
pragma[noopt]
|
||||
private predicate dependsOnFileSimple(MetricFile source, MetricFile dest) {
|
||||
// class derives from another class
|
||||
// class derives from classs
|
||||
exists(Class fromClass, Class toClass |
|
||||
aClassFile(fromClass, source) and
|
||||
fromClass.derivesFrom(toClass) and
|
||||
|
||||
@@ -173,7 +173,7 @@ predicate eqOpWithSwapAndNegate(EqualityOperation cmp, Expr a, Expr b, boolean i
|
||||
|
||||
/**
|
||||
* Holds if `cmp` is an unconverted conversion of `a` to a Boolean that
|
||||
* evaluates to `isEQ` iff `a` is 0.
|
||||
* evalutes to `isEQ` iff `a` is 0.
|
||||
*
|
||||
* Note that `a` can be `cmp` itself or a conversion thereof.
|
||||
*/
|
||||
|
||||
@@ -51,14 +51,14 @@ string getInsecureAlgorithmRegex() {
|
||||
|
||||
/**
|
||||
* Holds if `name` looks like it might be related to operations with an
|
||||
* insecure encryption algorithm.
|
||||
* insecure encyption algorithm.
|
||||
*/
|
||||
bindingset[name]
|
||||
predicate isInsecureEncryption(string name) { name.regexpMatch(getInsecureAlgorithmRegex()) }
|
||||
|
||||
/**
|
||||
* Holds if there is additional evidence that `name` looks like it might be
|
||||
* related to operations with an encryption algorithm, besides the name of a
|
||||
* related to operations with an encyption algorithm, besides the name of a
|
||||
* specific algorithm. This can be used in conjunction with
|
||||
* `isInsecureEncryption` to produce a stronger heuristic.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: we now use `semmle.code.cpp.ir.dataflow.DefaultTaintTracking`,
|
||||
* which is based on the IR but designed to behave similarly to this old
|
||||
* library.
|
||||
* libarary.
|
||||
*
|
||||
* Provides the implementation of `semmle.code.cpp.security.TaintTracking`. Do
|
||||
* not import this file directly.
|
||||
|
||||
@@ -104,7 +104,7 @@ private newtype HC_Alloc =
|
||||
HC_HasAlloc(HashCons hc) { mk_HasAlloc(hc, _) }
|
||||
|
||||
/**
|
||||
* Used to implement optional extent expression on `new[]` expressions
|
||||
* Used to implement optional extent expression on `new[]` exprtessions
|
||||
*/
|
||||
private newtype HC_Extent =
|
||||
HC_NoExtent() or
|
||||
@@ -116,7 +116,7 @@ private newtype HC_Args =
|
||||
HC_ArgCons(HashCons hc, int i, HC_Args list) { mk_ArgCons(hc, i, list, _) }
|
||||
|
||||
/**
|
||||
* Used to implement hash-consing of struct initializers.
|
||||
* Used to implement hash-consing of struct initizializers.
|
||||
*/
|
||||
private newtype HC_Fields =
|
||||
HC_EmptyFields(Class c) { exists(ClassAggregateLiteral cal | c = cal.getUnspecifiedType()) } or
|
||||
|
||||
@@ -35,4 +35,4 @@ from LocalVariableOrParameter lv, GlobalVariable gv
|
||||
where
|
||||
lv.getName() = gv.getName() and
|
||||
lv.getFile() = gv.getFile()
|
||||
select lv, lv.type() + gv.getName() + " hides a $@ with the same name.", gv, "global variable"
|
||||
select lv, lv.type() + gv.getName() + " hides $@ with the same name.", gv, "a global variable"
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* In this example, the developer intended to use a semicolon but accidentally used a comma:
|
||||
*/
|
||||
|
||||
enum privileges entitlements = NONE;
|
||||
|
||||
if (is_admin)
|
||||
entitlements = FULL, // BAD
|
||||
|
||||
restrict_privileges(entitlements);
|
||||
|
||||
/*
|
||||
* The use of a comma means that the first example is equivalent to this second example:
|
||||
*/
|
||||
|
||||
enum privileges entitlements = NONE;
|
||||
|
||||
if (is_admin) {
|
||||
entitlements = FULL;
|
||||
restrict_privileges(entitlements);
|
||||
}
|
||||
|
||||
/*
|
||||
* The indentation of the first example suggests that the developer probably intended the following code:
|
||||
*/
|
||||
|
||||
enum privileges entitlements = NONE;
|
||||
|
||||
if (is_admin)
|
||||
entitlements = FULL; // GOOD
|
||||
|
||||
restrict_privileges(entitlements);
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
If the expression after the comma operator starts at an earlier column than the expression before the comma, then
|
||||
this suspicious indentation possibly indicates a logic error, caused by a typo that may escape visual inspection.
|
||||
</p>
|
||||
<warning>
|
||||
This query has medium precision because CodeQL currently does not distinguish between tabs and spaces in whitespace.
|
||||
If a file contains mixed tabs and spaces, alerts may highlight code that is correctly indented for one value of tab size but not for other tab sizes.
|
||||
</warning>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
To ensure that your code is easy to read and review, use standard indentation around the comma operator. Always begin the right-hand-side operand at the same level of
|
||||
indentation (column number) as the left-hand-side operand. This makes it easier for other developers to see the intended behavior of your code.
|
||||
</p>
|
||||
<p>
|
||||
Use whitespace consistently to communicate your coding intentions. Where possible, avoid mixing tabs and spaces within a file. If you need to mix them, use them consistently.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
This example shows three different ways of writing the same code. The first example contains a comma instead of a semicolon which means that the final line is part of the <code>if</code> statement, even though the indentation suggests that it is intended to be separate. The second example looks different but is functionally the same as the first example. It is more likely that the developer intended to write the third example.
|
||||
</p>
|
||||
<sample src="CommaBeforeMisleadingIndentation.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Comma_operator">Comma operator</a></li>
|
||||
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Indentation_style#Tabs,_spaces,_and_size_of_indentations">Indentation style — Tabs, spaces, and size of indentations</a></li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* @name Comma before misleading indentation
|
||||
* @description If expressions before and after a comma operator use different indentation, it is easy to misread the purpose of the code.
|
||||
* @kind problem
|
||||
* @id cpp/comma-before-misleading-indentation
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.8
|
||||
* @precision medium
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* security
|
||||
* external/cwe/cwe-1078
|
||||
* external/cwe/cwe-670
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
/** Gets the sub-expression of 'e' with the earliest-starting Location */
|
||||
Expr normalizeExpr(Expr e) {
|
||||
result =
|
||||
min(Expr child |
|
||||
child.getParentWithConversions*() = e.getFullyConverted() and
|
||||
not child.getParentWithConversions*() = any(Call c).getAnArgument()
|
||||
|
|
||||
child order by child.getLocation().getStartColumn(), count(child.getParentWithConversions*())
|
||||
)
|
||||
}
|
||||
|
||||
predicate isParenthesized(CommaExpr ce) {
|
||||
ce.getParent*().(Expr).isParenthesised()
|
||||
or
|
||||
ce.isUnevaluated() // sizeof(), decltype(), alignof(), noexcept(), typeid()
|
||||
or
|
||||
ce.getParent*() = [any(IfStmt i).getCondition(), any(SwitchStmt s).getExpr()]
|
||||
or
|
||||
ce.getParent*() = [any(Loop l).getCondition(), any(ForStmt f).getUpdate()]
|
||||
or
|
||||
ce.getEnclosingStmt() = any(ForStmt f).getInitialization()
|
||||
}
|
||||
|
||||
from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc
|
||||
where
|
||||
ce.fromSource() and
|
||||
not isFromMacroDefinition(ce) and
|
||||
left = normalizeExpr(ce.getLeftOperand()) and
|
||||
right = normalizeExpr(ce.getRightOperand()) and
|
||||
leftLoc = left.getLocation() and
|
||||
rightLoc = right.getLocation() and
|
||||
not isParenthesized(ce) and
|
||||
leftLoc.getEndLine() < rightLoc.getStartLine() and
|
||||
leftLoc.getStartColumn() > rightLoc.getStartColumn()
|
||||
select right, "The indentation level may be misleading for some tab sizes."
|
||||
@@ -13,32 +13,16 @@
|
||||
|
||||
import cpp
|
||||
|
||||
pragma[noinline]
|
||||
predicate possiblyIncompleteFile(File f) {
|
||||
exists(Diagnostic d | d.getFile() = f and d.getSeverity() >= 3)
|
||||
}
|
||||
|
||||
predicate immediatelyReachableFunction(Function f) {
|
||||
not f.isStatic()
|
||||
or
|
||||
exists(BlockExpr be | be.getFunction() = f)
|
||||
or
|
||||
f instanceof MemberFunction
|
||||
or
|
||||
f instanceof TemplateFunction
|
||||
or
|
||||
f.getFile() instanceof HeaderFile
|
||||
or
|
||||
f.getAnAttribute().hasName("constructor")
|
||||
or
|
||||
f.getAnAttribute().hasName("destructor")
|
||||
or
|
||||
f.getAnAttribute().hasName("used")
|
||||
or
|
||||
not f.isStatic() or
|
||||
exists(BlockExpr be | be.getFunction() = f) or
|
||||
f instanceof MemberFunction or
|
||||
f instanceof TemplateFunction or
|
||||
f.getFile() instanceof HeaderFile or
|
||||
f.getAnAttribute().hasName("constructor") or
|
||||
f.getAnAttribute().hasName("destructor") or
|
||||
f.getAnAttribute().hasName("used") or
|
||||
f.getAnAttribute().hasName("unused")
|
||||
or
|
||||
// a compiler error in the same file suggests we may be missing data
|
||||
possiblyIncompleteFile(f.getFile())
|
||||
}
|
||||
|
||||
predicate immediatelyReachableVariable(Variable v) {
|
||||
|
||||
@@ -11,7 +11,7 @@ caused by an unhandled case.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Check that the unused static variable does not indicate a defect, for example, an unhandled case. If the static variable is genuinely not needed,
|
||||
<p>Check that the unused static variable does not indicate a defect, for example, an unhandled case. If the static variable is genuinuely not needed,
|
||||
then removing it will make code more readable. If the static variable is needed then you should update the code to fix the defect.</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
@@ -1,20 +1,3 @@
|
||||
## 0.4.2
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new medium-precision query, `cpp/comma-before-misleading-indentation`, which detects instances of whitespace that have readability issues.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "Unterminated variadic call" (`cpp/unterminated-variadic-call`) query has been tuned to produce fewer false positive results.
|
||||
* Fixed false positives from the "Unused static function" (`cpp/unused-static-function`) query in files that had errors during compilation.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### New Queries
|
||||
@@ -136,7 +119,7 @@
|
||||
|
||||
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
|
||||
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
|
||||
* A new `cpp/very-likely-overrunning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overrunning-write`.
|
||||
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ This can occur when an operation performed on the open descriptor fails, and the
|
||||
|
||||
<example>
|
||||
<p>In the example below, the <code>sockfd</code> socket may remain open if an error is triggered.
|
||||
The code should be updated to ensure that the socket is always closed when the function ends.
|
||||
The code should be updated to ensure that the socket is always closed when when the function ends.
|
||||
</p>
|
||||
<sample src="DescriptorMayNotBeClosed.cpp" />
|
||||
</example>
|
||||
|
||||
@@ -63,7 +63,7 @@ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode
|
||||
node.(AnalysedExpr).getNonNullSuccessor(newV) = verified and
|
||||
// note: this case uses naive flow logic (getAnAssignedValue).
|
||||
// special case: if the result of the 'realloc' is assigned to the
|
||||
// same variable, we don't discriminate properly between the old
|
||||
// same variable, we don't descriminate properly between the old
|
||||
// and the new allocation; better to not consider this a free at
|
||||
// all in that case.
|
||||
newV != v
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* @description Lists all files in the source code directory that were extracted without encountering a problem in the file.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/successfully-extracted-files
|
||||
* @tags successfully-extracted-files
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -15,7 +15,7 @@ As an exception, because their purpose is usually obvious, it is not necessary t
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Add comments to document the purpose of the function. In particular, ensure that the public API of the function is carefully documented. This reduces the chance that a future change to the function will introduce a defect by changing the API and breaking the expectations of the calling functions.
|
||||
Add comments to document the purpose of the function. In particular, ensure that the public API of the function is carefully documented. This reduces the chance that a future change to the function will introduce a defect by changing the API and breaking the expections of the calling functions.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
This rule finds comparison expressions that use 2 or more comparison operators and are not completely parenthesized.
|
||||
This rule finds comparison expressions that use 2 or more comparison operators and are not completely paranthesized.
|
||||
It is best to fully parenthesize complex comparison expressions to explicitly define the order of the comparison operators.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ DoStmt getAFalseLoop() {
|
||||
/**
|
||||
* Gets a `do` ... `while` loop surrounding a statement. This is blocked by a
|
||||
* `switch` statement, since a `continue` inside a `switch` inside a loop may be
|
||||
* justified (`continue` breaks out of the loop whereas `break` only escapes the
|
||||
* jusitifed (`continue` breaks out of the loop whereas `break` only escapes the
|
||||
* `switch`).
|
||||
*/
|
||||
DoStmt enclosingLoop(Stmt s) {
|
||||
|
||||
@@ -25,11 +25,8 @@ class CastToPointerArithFlow extends DataFlow::Configuration {
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
not node.asExpr() instanceof Conversion and
|
||||
exists(Type baseType1, Type baseType2 |
|
||||
hasBaseType(node.asExpr(), baseType1) and
|
||||
hasBaseType(node.asExpr().getConversion*(), baseType2) and
|
||||
introducesNewField(baseType1, baseType2)
|
||||
)
|
||||
introducesNewField(node.asExpr().getType().(DerivedType).getBaseType(),
|
||||
node.asExpr().getConversion*().getType().(DerivedType).getBaseType())
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
@@ -38,17 +35,6 @@ class CastToPointerArithFlow extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type of `e` is a `DerivedType` with `base` as its base type.
|
||||
*
|
||||
* This predicate ensures that joins go from `e` to `base` instead
|
||||
* of the other way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate hasBaseType(Expr e, Type base) {
|
||||
pragma[only_bind_into](base) = e.getType().(DerivedType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
* `derived` has a (possibly indirect) base class of `base`, and at least one new
|
||||
* field has been introduced in the inheritance chain after `base`.
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<overview>
|
||||
<p>This rule finds logical-not operator usage as an operator for in a bit-wise operation.</p>
|
||||
|
||||
<p>Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise operations. Violations are often indicative of a typo, using a logical-not (<code>!</code>) operator instead of the bit-wise not (<code>~</code>) operator. </p>
|
||||
<p>Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise opeartions. Violations are often indicative of a typo, using a logical-not (<code>!</code>) opeartor instead of the bit-wise not (<code>~</code>) operator. </p>
|
||||
<p>This rule is restricted to analyze bit-wise and (<code>&</code>) and bit-wise or (<code>|</code>) operation in order to provide better precision.</p>
|
||||
<p>This rule ignores instances where a double negation (<code>!!</code>) is explicitly used as the operator of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0.</p>
|
||||
<p>This rule ignores instances where a double negation (<code>!!</code>) is explicitly used as the opeartor of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0.</p>
|
||||
<p>NOTE: It is not recommended to use this rule in kernel code or older C code as it will likely find several false positive instances.</p>
|
||||
|
||||
</overview>
|
||||
|
||||
@@ -17,7 +17,7 @@ import cpp
|
||||
/**
|
||||
* It's common in some projects to use "a double negation" to normalize the boolean
|
||||
* result to either 1 or 0.
|
||||
* This predicate is intended to filter explicit usage of a double negation as it typically
|
||||
* This predciate is intended to filter explicit usage of a double negation as it typically
|
||||
* indicates the explicit purpose to normalize the result for bit-wise or arithmetic purposes.
|
||||
*/
|
||||
predicate doubleNegationNormalization(NotExpr notexpr) { notexpr.getAnOperand() instanceof NotExpr }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @name Untrusted network-to-host usage
|
||||
* @description Using the result of a network-to-host byte order function, such as ntohl, as an
|
||||
* array bound or length value without checking it may result in buffer overflows or
|
||||
* other vulnerabilities.
|
||||
* other vulnerabilties.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,7 @@ pointer overflow.
|
||||
|
||||
<p>
|
||||
While it's not the subject of this query, the expression <code>ptr + i <
|
||||
ptr_end</code> is also an invalid range check. It's undefined behavior in
|
||||
ptr_end</code> is also an invalid range check. It's undefined behavor in
|
||||
C/C++ to create a pointer that points more than one past the end of an
|
||||
allocation.
|
||||
</p>
|
||||
|
||||
@@ -44,7 +44,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
// Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in
|
||||
// a `ReturnValueInstruction`.
|
||||
// We use the `StoreInstruction` instead of the instruction that defines the
|
||||
// `ReturnValueInstruction`'s source value operand because the former has better location information.
|
||||
// `ReturnValueInstruction`'s source value oprand because the former has better location information.
|
||||
exists(StoreInstruction store |
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getIRVariable() instanceof
|
||||
IRReturnVariable and
|
||||
|
||||
@@ -12,7 +12,7 @@ the third argument to the entire size of the destination buffer.
|
||||
Executing a call of this type may cause a buffer overflow unless the buffer is known to be empty.</p>
|
||||
|
||||
<p>Similarly, calls of the form <code>strncat(dest, src, sizeof (dest) - strlen (dest))</code> allow one
|
||||
byte to be written outside the <code>dest</code> buffer.</p>
|
||||
byte to be written ouside the <code>dest</code> buffer.</p>
|
||||
|
||||
<p>Buffer overflows can lead to anything from a segmentation fault to a security vulnerability.</p>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
* Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and
|
||||
* destination arguments, respectively.
|
||||
*/
|
||||
predicate interestingCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
exists(StrcatFunction strcat |
|
||||
strcat = call.getTarget() and
|
||||
sizeArg = call.getArgument(strcat.getParamSize()) and
|
||||
@@ -37,7 +37,7 @@ predicate interestingCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
* argument `destArg`, and `destArg` is the size of the buffer pointed to by `destArg`.
|
||||
*/
|
||||
predicate case1(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
interestingCallWithArgs(fc, sizeArg, destArg) and
|
||||
interestringCallWithArgs(fc, sizeArg, destArg) and
|
||||
exists(VariableAccess va |
|
||||
va = sizeArg.(BufferSizeExpr).getArg() and
|
||||
destArg.getTarget() = va.getTarget()
|
||||
@@ -49,7 +49,7 @@ predicate case1(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
* argument `destArg`, and `sizeArg` computes the value `sizeof (dest) - strlen (dest)`.
|
||||
*/
|
||||
predicate case2(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
interestingCallWithArgs(fc, sizeArg, destArg) and
|
||||
interestringCallWithArgs(fc, sizeArg, destArg) and
|
||||
exists(SubExpr sub, int n |
|
||||
// The destination buffer is an array of size n
|
||||
destArg.getUnspecifiedType().(ArrayType).getSize() = n and
|
||||
|
||||
@@ -48,5 +48,5 @@ where
|
||||
not coordinatePair(iterationVar, innerVar)
|
||||
select iterationVar,
|
||||
"Iteration variable " + iterationVar.getName() +
|
||||
" for $@ should have a descriptive name, since there is a $@.", outer, "this loop", inner,
|
||||
"nested loop"
|
||||
" for $@ should have a descriptive name, since there is $@.", outer, "this loop", inner,
|
||||
"a nested loop"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* '#include <stdlib.h>' was forgotten */
|
||||
/* '#include <stdlib.h>' was forgotton */
|
||||
|
||||
int main(void) {
|
||||
/* 'int malloc()' assumed */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p>
|
||||
This metric provides an indication of the lack of cohesion of a class,
|
||||
using a method proposed by Chidamber and Kemerer in 1994. The idea
|
||||
behind measuring a class's cohesion is that most functions in well-designed
|
||||
behind measuring a class's cohesion is that most funcions in well-designed
|
||||
classes will access the same fields. Types that exhibit a lack of cohesion
|
||||
are often trying to take on multiple responsibilities, and should be split
|
||||
into several smaller classes.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
by changes to other packages. If this metric value is high, a package is easily
|
||||
influenced. If the values is low, the impact of changes to other packages is likely to be minimal. Instability
|
||||
is estimated as the number of outgoing dependencies relative to the total
|
||||
number of dependencies.</p>
|
||||
number of depencies.</p>
|
||||
</overview>
|
||||
|
||||
<references>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
by changes to other packages. If this metric value is high, a package is easily
|
||||
influenced. If the values is low, the impact of changes to other packages is likely to be minimal. Instability
|
||||
is estimated as the number of outgoing dependencies relative to the total
|
||||
number of dependencies.</p>
|
||||
number of depencies.</p>
|
||||
</overview>
|
||||
|
||||
<references>
|
||||
|
||||
@@ -26,7 +26,7 @@ where
|
||||
dest = bw.getDest() and
|
||||
destSize = getBufferSize(dest, _) and
|
||||
estimated = bw.getMaxDataLimited(reason) and
|
||||
// we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overrunning-write
|
||||
// we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overruning-write
|
||||
not reason instanceof ValueFlowAnalysis and
|
||||
// we can deduce that too much data may be copied (even without
|
||||
// long '%f' conversions)
|
||||
|
||||
@@ -56,26 +56,29 @@ class VarargsFunction extends Function {
|
||||
result = strictcount(FunctionCall fc | fc = this.getACallToThisFunction())
|
||||
}
|
||||
|
||||
string normalTerminator(int cnt, int totalCount) {
|
||||
// the terminator is 0 or -1
|
||||
string normalTerminator(int cnt) {
|
||||
result = ["0", "-1"] and
|
||||
// at least 80% of calls have the terminator
|
||||
cnt = this.trailingArgValueCount(result) and
|
||||
totalCount = this.totalCount() and
|
||||
100 * cnt / totalCount >= 80 and
|
||||
// terminator value is not used in a non-terminating position
|
||||
not exists(FunctionCall fc, int index | this.nonTrailingVarArgValue(fc, index) = result)
|
||||
2 * cnt > this.totalCount() and
|
||||
not exists(FunctionCall fc, int index |
|
||||
// terminator value is used in a non-terminating position
|
||||
this.nonTrailingVarArgValue(fc, index) = result
|
||||
)
|
||||
}
|
||||
|
||||
predicate isWhitelisted() { this.hasGlobalName(["open", "fcntl", "ptrace", "mremap"]) }
|
||||
predicate isWhitelisted() {
|
||||
this.hasGlobalName("open") or
|
||||
this.hasGlobalName("fcntl") or
|
||||
this.hasGlobalName("ptrace")
|
||||
}
|
||||
}
|
||||
|
||||
from VarargsFunction f, FunctionCall fc, string terminator, int cnt, int totalCount
|
||||
from VarargsFunction f, FunctionCall fc, string terminator, int cnt
|
||||
where
|
||||
terminator = f.normalTerminator(cnt, totalCount) and
|
||||
terminator = f.normalTerminator(cnt) and
|
||||
fc = f.getACallToThisFunction() and
|
||||
not normalisedExprValue(f.trailingArgumentIn(fc)) = terminator and
|
||||
not f.isWhitelisted()
|
||||
select fc,
|
||||
"Calls to $@ should use the value " + terminator + " as a terminator (" + cnt + " of " +
|
||||
totalCount + " calls do).", f, f.getQualifiedName()
|
||||
"Calls to $@ should use the value " + terminator + " as a terminator (" + cnt + " calls do).", f,
|
||||
f.getQualifiedName()
|
||||
|
||||
@@ -135,5 +135,5 @@ where
|
||||
sink.getNode().asExpr() = va and
|
||||
missingGuard(va, effect)
|
||||
select sink.getNode(), source, sink,
|
||||
"This arithmetic expression depends on an $@, potentially causing an " + effect + ".",
|
||||
"Arithmetic expression depends on an $@, potentially causing an " + effect + ".",
|
||||
getExpr(source.getNode()), "uncontrolled value"
|
||||
|
||||
@@ -31,7 +31,7 @@ predicate bounded(Expr e) {
|
||||
) and
|
||||
not convertedExprMightOverflow(e)
|
||||
or
|
||||
// Optimistically assume that a remainder expression always yields a much smaller value.
|
||||
// Optimitically assume that a remainder expression always yields a much smaller value.
|
||||
e = any(RemExpr rem).getLeftOperand()
|
||||
or
|
||||
e = any(AssignRemExpr rem).getLValue()
|
||||
@@ -44,7 +44,7 @@ predicate bounded(Expr e) {
|
||||
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
|
||||
)
|
||||
or
|
||||
// Optimistically assume that a division always yields a much smaller value.
|
||||
// Optimitically assume that a division always yields a much smaller value.
|
||||
e = any(DivExpr div).getLeftOperand()
|
||||
or
|
||||
e = any(AssignDivExpr div).getLValue()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<overview>
|
||||
<p>This query indicates that a call is setting the DACL field in a <code>SECURITY_DESCRIPTOR</code> to null.</p>
|
||||
<p>When using <code>SetSecurityDescriptorDacl</code> to set a discretionary access control (DACL), setting the <code>bDaclPresent</code> argument to <code>TRUE</code> indicates the presence of a DACL in the security description in the argument <code>pDacl</code>.</p>
|
||||
<p>When using <code>SetSecurityDescriptorDacl</code> to set a discretionary access control (DACL), setting the <code>bDaclPresent</code> argument to <code>TRUE</code> indicates the prescence of a DACL in the security description in the argument <code>pDacl</code>.</p>
|
||||
<p>When the <code>pDacl</code> parameter does not point to a DACL (i.e. it is <code>NULL</code>) and the <code>bDaclPresent</code> flag is <code>TRUE</code>, a <code>NULL DACL</code> is specified.</p>
|
||||
<p>A <code>NULL DACL</code> grants full access to any user who requests it; normal security checking is not performed with respect to the object.</p>
|
||||
</overview>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
## 0.4.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages.
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages.
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
|
||||
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
|
||||
* A new `cpp/very-likely-overrunning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overrunning-write`.
|
||||
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
## 0.4.2
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new medium-precision query, `cpp/comma-before-misleading-indentation`, which detects instances of whitespace that have readability issues.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "Unterminated variadic call" (`cpp/unterminated-variadic-call`) query has been tuned to produce fewer false positive results.
|
||||
* Fixed false positives from the "Unused static function" (`cpp/unused-static-function`) query in files that had errors during compilation.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.2
|
||||
lastReleaseVersion: 0.4.0
|
||||
|
||||
@@ -13,6 +13,6 @@ where
|
||||
def = definitionOf(e, kind) and
|
||||
// We need to exclude definitions for elements inside template instantiations,
|
||||
// as these often lead to multiple links to definitions from the same source location.
|
||||
// LGTM does not support this behaviour.
|
||||
// LGTM does not support this bevaviour.
|
||||
not e.isFromTemplateInstantiation(_)
|
||||
select e, def, kind
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @id cpp/wrong-uint-access
|
||||
* @name Wrong Uint
|
||||
* @description Access an array of size lower than 256 with a uint16.
|
||||
* @descripion Acess an array of size lower than 256 with a uint16.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @tags efficiency
|
||||
@@ -21,5 +21,5 @@ where
|
||||
) and
|
||||
defLine.getArraySize() <= 256
|
||||
select useExpr,
|
||||
"Using a " + useExpr.getArrayOffset().getType() + " to access the array $@ of size " +
|
||||
"Using a " + useExpr.getArrayOffset().getType() + " to acess the array $@ of size " +
|
||||
defLine.getArraySize() + ".", var, var.getName()
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char *filePath = argv[2];
|
||||
|
||||
{
|
||||
// BAD: the user-controlled string is injected
|
||||
// directly into `wordexp` which performs command substitution
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, 0);
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: command substitution is disabled
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, WRDE_NOCMD);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The code passes user input to <code>wordexp</code>. This leaves the code
|
||||
vulnerable to attack by command injection, because <code>wordexp</code> performs command substitution.
|
||||
Command substitution is a feature that replaces <code>$(command)</code> or <code>`command`</code> with the
|
||||
output of the given command, allowing the user to run arbitrary code on the system.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>When calling <code>wordexp</code>, pass the <code>WRDE_NOCMD</code> flag to prevent command substitution.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example passes a user-supplied file path to <code>wordexp</code> in two ways. The
|
||||
first way uses <code>wordexp</code> with no specified flags. As such, it is vulnerable to command
|
||||
injection.
|
||||
The second way uses <code>wordexp</code> with the <code>WRDE_NOCMD</code> flag. As such, no command substitution
|
||||
is performed, making this safe from command injection.</p>
|
||||
<sample src="WordexpTainted.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard:
|
||||
<a href="https://www.securecoding.cert.org/confluence/display/c/STR02-C.+Sanitize+data+passed+to+complex+subsystems">STR02-C.
|
||||
Sanitize data passed to complex subsystems</a>.</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
|
||||
<!-- LocalWords: CWE STR
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* @name Uncontrolled data used in `wordexp` command
|
||||
* @description Using user-supplied data in a `wordexp` command, without
|
||||
* disabling command substitution, can make code vulnerable
|
||||
* to command injection.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/wordexp-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* The `wordexp` function, which can perform command substitution.
|
||||
*/
|
||||
private class WordexpFunction extends Function {
|
||||
WordexpFunction() { hasGlobalName("wordexp") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` disables command substitution by containing `WRDE_NOCMD` as a flag argument.
|
||||
*/
|
||||
private predicate isCommandSubstitutionDisabled(FunctionCall fc) {
|
||||
fc.getArgument(2).getValue().toInt().bitAnd(4) = 4
|
||||
/* 4 = WRDE_NOCMD. Check whether the flag is set. */
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to track user-supplied data to the `wordexp` function.
|
||||
*/
|
||||
class WordexpTaintConfiguration extends TaintTracking::Configuration {
|
||||
WordexpTaintConfiguration() { this = "WordexpTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
|
||||
fc.getArgument(0) = sink.asExpr() and
|
||||
not isCommandSubstitutionDisabled(fc)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
}
|
||||
|
||||
from WordexpTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode
|
||||
where conf.hasFlowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
"Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection."
|
||||
@@ -1,17 +0,0 @@
|
||||
#define MAX_SIZE 1024
|
||||
|
||||
struct FixedArray {
|
||||
int buf[MAX_SIZE];
|
||||
};
|
||||
|
||||
int main(){
|
||||
FixedArray arr;
|
||||
|
||||
for(int i = 0; i <= MAX_SIZE; i++) {
|
||||
arr.buf[i] = 0; // BAD
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_SIZE; i++) {
|
||||
arr.buf[i] = 0; // GOOD
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The program performs an out-of-bounds read or write operation. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Ensure that pointer dereferences are properly guarded to ensure that they cannot be used to read or write past the end of the allocation.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The first example uses a for loop which is improperly bounded by a non-strict less-than operation and will write one position past the end of the array. The second example bounds the for loop properly with a strict less-than operation.</p>
|
||||
<sample src="ConstantSizeArrayOffByOne.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts</a>.</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://owasp.org/www-community/vulnerabilities/Buffer_Overflow">Buffer Overflow</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user