mirror of
https://github.com/github/codeql.git
synced 2026-05-24 16:17:07 +02:00
Compare commits
284 Commits
dbartol/in
...
fossjunkie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7736c324 | ||
|
|
79cd7615b7 | ||
|
|
d258a1c728 | ||
|
|
b17a71674a | ||
|
|
07f8780541 | ||
|
|
d0732a765b | ||
|
|
eed8c72ce6 | ||
|
|
271e41c6dd | ||
|
|
71c37dba32 | ||
|
|
bcca18d5b2 | ||
|
|
081d97ff72 | ||
|
|
a4e9d38abb | ||
|
|
0aa90d6f09 | ||
|
|
cbe5243c89 | ||
|
|
915efffe21 | ||
|
|
59f2c75186 | ||
|
|
3f40e3863f | ||
|
|
0f267e012a | ||
|
|
65d129dee1 | ||
|
|
5f8d6c3c07 | ||
|
|
82daf50ed4 | ||
|
|
974f4bc371 | ||
|
|
ea626a03b6 | ||
|
|
536bc9ac89 | ||
|
|
dc6729d0bf | ||
|
|
663d4e8e3b | ||
|
|
bed5eeb372 | ||
|
|
5dc5c8e683 | ||
|
|
b000b9b5c0 | ||
|
|
a93c2ec20b | ||
|
|
5a3ddcfca6 | ||
|
|
4bc6a0927d | ||
|
|
53d9e4d4eb | ||
|
|
bdab57b9d3 | ||
|
|
71d184e8c0 | ||
|
|
46ef954d5c | ||
|
|
6c0c06c963 | ||
|
|
5fcc0d3e28 | ||
|
|
a328d8c93b | ||
|
|
b2d436ccc1 | ||
|
|
b7600c6022 | ||
|
|
6cb1348988 | ||
|
|
4fc5742a62 | ||
|
|
5db3ec8f5b | ||
|
|
0408e9dc2d | ||
|
|
e91165bc01 | ||
|
|
6a2a351929 | ||
|
|
81e3b8badb | ||
|
|
62a47ce18b | ||
|
|
12b75e7be1 | ||
|
|
91c324ea4f | ||
|
|
29f7862466 | ||
|
|
288e9206c7 | ||
|
|
834511bd78 | ||
|
|
b102ddac30 | ||
|
|
218ed8ad37 | ||
|
|
c023af7308 | ||
|
|
070468ab68 | ||
|
|
34fe1a8f5e | ||
|
|
92a31608a2 | ||
|
|
5c607b81fd | ||
|
|
e21e630316 | ||
|
|
89d9d65755 | ||
|
|
574b2201cb | ||
|
|
0d6dd7d25a | ||
|
|
56288eb3d2 | ||
|
|
5260d9815a | ||
|
|
225ed1e220 | ||
|
|
caa25f78d9 | ||
|
|
a865f1666d | ||
|
|
98dc73c6dd | ||
|
|
6d665da4dc | ||
|
|
719708cb89 | ||
|
|
da96ed1ff9 | ||
|
|
41becfe2ba | ||
|
|
219031f62b | ||
|
|
2ce0d2b7ee | ||
|
|
eab43973b7 | ||
|
|
4e6b93e239 | ||
|
|
40cc2e7891 | ||
|
|
4d2a1ea149 | ||
|
|
8623d8eb8e | ||
|
|
b37bb660c5 | ||
|
|
2876b4aa5d | ||
|
|
956f991b8d | ||
|
|
346086524b | ||
|
|
1f991807d4 | ||
|
|
2fdfa0808a | ||
|
|
1f75c3836e | ||
|
|
4e752369c5 | ||
|
|
cc46d7fef3 | ||
|
|
7420e90a46 | ||
|
|
6598cc44ee | ||
|
|
7cdd2b69c9 | ||
|
|
43b3f379e9 | ||
|
|
b64ca5dcaa | ||
|
|
c7816ea180 | ||
|
|
8856730843 | ||
|
|
de6959c688 | ||
|
|
73a17536f5 | ||
|
|
ae57807359 | ||
|
|
e6e974a752 | ||
|
|
c1ee2dce61 | ||
|
|
ac58299d9e | ||
|
|
1258812428 | ||
|
|
f685b93379 | ||
|
|
a66b7ed54a | ||
|
|
0cab45e4b9 | ||
|
|
8802fbdfe7 | ||
|
|
bc227179c7 | ||
|
|
bc99a44f3a | ||
|
|
12bb0d98c0 | ||
|
|
4761c3a328 | ||
|
|
bd21dc9460 | ||
|
|
b7ce0c2d96 | ||
|
|
2236db43ec | ||
|
|
74e261738f | ||
|
|
ec1762e015 | ||
|
|
fa60fa0ae2 | ||
|
|
aaea976cf2 | ||
|
|
3876e4335f | ||
|
|
be163cfc38 | ||
|
|
17b3383043 | ||
|
|
a9d40d39d9 | ||
|
|
0f813ce2e8 | ||
|
|
c56c1cbb62 | ||
|
|
6639e5a97b | ||
|
|
6a5db750c4 | ||
|
|
17c9ba9872 | ||
|
|
ed15cce31f | ||
|
|
8c738b77a3 | ||
|
|
b042c60ca3 | ||
|
|
39726a54ec | ||
|
|
72e97918e9 | ||
|
|
bbe95367d6 | ||
|
|
a19579d21b | ||
|
|
2968c12e12 | ||
|
|
9997326804 | ||
|
|
5f438e433d | ||
|
|
1d2f1b6ae6 | ||
|
|
83b0d073f0 | ||
|
|
1c661fd3ac | ||
|
|
e0e3a1d621 | ||
|
|
9b7a20f4ad | ||
|
|
84fd5f7ee0 | ||
|
|
fcf1f6a6f9 | ||
|
|
60a4a79537 | ||
|
|
9aa83d78e1 | ||
|
|
1c06afffe5 | ||
|
|
166902bfa0 | ||
|
|
ef498020c2 | ||
|
|
1f8a165611 | ||
|
|
029d924e6d | ||
|
|
2270d6fa61 | ||
|
|
4b1171ce64 | ||
|
|
27fc14236f | ||
|
|
bff8bbfe33 | ||
|
|
91b069603d | ||
|
|
01ade878ea | ||
|
|
ba711ab849 | ||
|
|
ae12510d8d | ||
|
|
9039a468cb | ||
|
|
e86f1e4961 | ||
|
|
a9ef3f95a2 | ||
|
|
e78af3e66c | ||
|
|
37484a415f | ||
|
|
0ec56203f9 | ||
|
|
9a3c2d3fbe | ||
|
|
abd9f673e1 | ||
|
|
352bb5a29a | ||
|
|
8457d45edc | ||
|
|
9630feb5e4 | ||
|
|
540542ceb5 | ||
|
|
af98ceb3c3 | ||
|
|
a131966066 | ||
|
|
5f14af5db0 | ||
|
|
9b3b6632fc | ||
|
|
0d36a5a733 | ||
|
|
c852d3a541 | ||
|
|
2d5944fb0e | ||
|
|
d743b31ab6 | ||
|
|
b0f803759c | ||
|
|
00267637eb | ||
|
|
7eb3fd2ff7 | ||
|
|
d317de14c9 | ||
|
|
310af99843 | ||
|
|
a9561a97c3 | ||
|
|
271d50ba99 | ||
|
|
80012b190d | ||
|
|
481d1f9b15 | ||
|
|
7bd7ecd9e6 | ||
|
|
4a202b430f | ||
|
|
d34dbbc96f | ||
|
|
ac223ea57f | ||
|
|
7aecefc4aa | ||
|
|
07fdcf2d04 | ||
|
|
e60e1a2ba9 | ||
|
|
4dd7dbc73b | ||
|
|
dce81cf0ae | ||
|
|
1e8404c954 | ||
|
|
8f565f5023 | ||
|
|
726f99975e | ||
|
|
981e171525 | ||
|
|
e84b08409c | ||
|
|
c12a85b07b | ||
|
|
76ed56d2b6 | ||
|
|
ee6288173f | ||
|
|
60f313863a | ||
|
|
940e492766 | ||
|
|
1aecc64327 | ||
|
|
5332344e5d | ||
|
|
2abb03304d | ||
|
|
c447e125bb | ||
|
|
d4020ad305 | ||
|
|
37e42bb05b | ||
|
|
a229f7a832 | ||
|
|
66b03dbd1d | ||
|
|
e7079b35bc | ||
|
|
880632f536 | ||
|
|
fe4d27e8cc | ||
|
|
f718d78a9a | ||
|
|
b208988675 | ||
|
|
54ec047433 | ||
|
|
8bc8342c7c | ||
|
|
0eb0c26b72 | ||
|
|
7b81fe3109 | ||
|
|
e7ead76fe9 | ||
|
|
907fbeaae8 | ||
|
|
01a85164ee | ||
|
|
45fdf69461 | ||
|
|
5bc606753e | ||
|
|
3b4980ba2f | ||
|
|
c5a1905302 | ||
|
|
341590f9ad | ||
|
|
e0c852c0b8 | ||
|
|
cc3efcd35e | ||
|
|
2133d1a5ab | ||
|
|
a72436f6f1 | ||
|
|
623e39031c | ||
|
|
fe1cc405eb | ||
|
|
44f239f4a4 | ||
|
|
cbc0ba6ac6 | ||
|
|
7455c27086 | ||
|
|
6aa9726223 | ||
|
|
db9e305a56 | ||
|
|
267c341965 | ||
|
|
31667b4478 | ||
|
|
720cf0ab7a | ||
|
|
3db95f3ac9 | ||
|
|
d54abddab1 | ||
|
|
2e7ad99059 | ||
|
|
452b9d11db | ||
|
|
cad5cd4037 | ||
|
|
db83fe6f42 | ||
|
|
8cc2686a2f | ||
|
|
1b85e8b706 | ||
|
|
ccf7d9beec | ||
|
|
984a589954 | ||
|
|
4307889b1f | ||
|
|
b4b7507fe4 | ||
|
|
8b99e8af88 | ||
|
|
25a6d496d9 | ||
|
|
d4e3f7f738 | ||
|
|
bbb43a53e5 | ||
|
|
b941d54f1f | ||
|
|
50fac3060c | ||
|
|
5a9a90d00b | ||
|
|
d9d63bbdc6 | ||
|
|
3e1808d92e | ||
|
|
cd49175fae | ||
|
|
cbb031ee14 | ||
|
|
6cd4cd332d | ||
|
|
31336b09c4 | ||
|
|
36b33765a5 | ||
|
|
b0797a2559 | ||
|
|
44997d6b5f | ||
|
|
61fe3704c0 | ||
|
|
dd1f7cc1d2 | ||
|
|
ff50513441 | ||
|
|
17f7ba2a8f | ||
|
|
d2bd70dc33 | ||
|
|
c2e8206090 | ||
|
|
962465f77a | ||
|
|
a4c42aa14b |
1
.github/workflows/check-change-note.yml
vendored
1
.github/workflows/check-change-note.yml
vendored
@@ -8,6 +8,7 @@ on:
|
||||
- "*/ql/src/**/*.qll"
|
||||
- "*/ql/lib/**/*.ql"
|
||||
- "*/ql/lib/**/*.qll"
|
||||
- "*/ql/lib/**/*.yml"
|
||||
- "!**/experimental/**"
|
||||
- "!ql/**"
|
||||
- "!swift/**"
|
||||
|
||||
63
.github/workflows/ruby-build.yml
vendored
63
.github/workflows/ruby-build.yml
vendored
@@ -48,6 +48,9 @@ jobs:
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Install cargo-cross
|
||||
if: runner.os == 'Linux'
|
||||
run: cargo install cross --version 0.2.1
|
||||
- uses: ./.github/actions/os-version
|
||||
id: os_version
|
||||
- name: Cache entire extractor
|
||||
@@ -78,8 +81,13 @@ jobs:
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo test --verbose
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
# On linux, build the extractor via cross in a centos7 container.
|
||||
# This ensures we don't depend on glibc > 2.17.
|
||||
- name: Release build (linux)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||
run: cd extractor && cross build --release
|
||||
- name: Release build (windows and macos)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os != 'Linux'
|
||||
run: cd extractor && cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
@@ -227,3 +235,54 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
# This is a copy of the 'test' job that runs in a centos7 container.
|
||||
# This tests that the extractor works correctly on systems with an old glibc.
|
||||
test-centos7:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: centos:centos7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- name: Install gh cli
|
||||
run: |
|
||||
yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
|
||||
# fetch-codeql requires unzip and jq
|
||||
# jq is available in epel-release (https://docs.fedoraproject.org/en-US/epel/)
|
||||
yum install -y gh unzip epel-release
|
||||
yum install -y jq
|
||||
- uses: actions/checkout@v3
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
# Due to a bug in Actions, we can't use runner.temp in the run blocks here.
|
||||
# https://github.com/actions/runner/issues/2185
|
||||
|
||||
- name: Download Ruby bundle
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: codeql-ruby-bundle
|
||||
path: ${{ runner.temp }}
|
||||
- name: Unzip Ruby bundle
|
||||
shell: bash
|
||||
run: unzip -q -d "$RUNNER_TEMP"/ruby-bundle "$RUNNER_TEMP"/codeql-ruby-bundle.zip
|
||||
|
||||
- name: Run QL test
|
||||
shell: bash
|
||||
run: |
|
||||
codeql test run --search-path "$RUNNER_TEMP"/ruby-bundle --additional-packs "$RUNNER_TEMP"/ruby-bundle ruby/ql/test/library-tests/ast/constants/
|
||||
- name: Create database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database create --search-path "$RUNNER_TEMP"/ruby-bundle --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database
|
||||
- name: Analyze database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "$RUNNER_TEMP"/ruby-bundle --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
@@ -279,6 +279,11 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRBlockImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRBlockImports.qll"
|
||||
],
|
||||
"C++ IR IRConsistencyImports": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConsistencyImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRConsistencyImports.qll"
|
||||
],
|
||||
"C++ IR IRFunctionImports": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRFunctionImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRFunctionImports.qll",
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
## 0.6.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `semmle.code.cpp.commons.Buffer` and `semmle.code.cpp.commons.NullTermination` libraries no longer expose `semmle.code.cpp.dataflow.DataFlow`. Please import `semmle.code.cpp.dataflow.DataFlow` directly.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `WriteConfig` taint tracking configuration has been deprecated. Please use `WriteFlow`.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* A new C/C++ dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) has been added.
|
||||
The new library behaves much more like the dataflow library of other CodeQL supported
|
||||
languages by following use-use dataflow paths instead of def-use dataflow paths.
|
||||
The new library also better supports dataflow through indirections, and new predicates
|
||||
such as `Node::asIndirectExpr` have been added to facilitate working with indirections.
|
||||
|
||||
The `semmle.code.cpp.ir.dataflow.DataFlow` library is now identical to the new
|
||||
`semmle.code.cpp.dataflow.new.DataFlow` library.
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `hasGeneratedCopyConstructor` and `hasGeneratedCopyAssignmentOperator` predicates from the `Folder` class.
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getMustlockFunction`, `getTrylockFunction`, `getLockFunction`, and `getUnlockFunction` predicates from the `MutexType` class.
|
||||
* Deleted the deprecated `getPosInBasicBlock` predicate from the `SubBasicBlock` class.
|
||||
* Deleted the deprecated `getExpr` predicate from the `PointerDereferenceExpr` class.
|
||||
* Deleted the deprecated `getUseInstruction` and `getDefinitionInstruction` predicates from the `Operand` class.
|
||||
* Deleted the deprecated `isInParameter`, `isInParameterPointer`, and `isInQualifier` predicates from the `FunctionInput` class.
|
||||
* Deleted the deprecated `isOutParameterPointer`, `isOutQualifier`, `isOutReturnValue`, and `isOutReturnPointer` predicate from the `FunctionOutput` class.
|
||||
* Deleted the deprecated 3-argument `isGuardPhi` predicate from the `RangeSsaDefinition` class.
|
||||
|
||||
## 0.5.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
4
cpp/ql/lib/change-notes/2013-03-20-ssa-consistency.md
Normal file
4
cpp/ql/lib/change-notes/2013-03-20-ssa-consistency.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The internal `SsaConsistency` module has been moved from `SSAConstruction` to `SSAConsitency`, and the deprecated `SSAConsistency` module has been removed.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The `semmle.code.cpp.commons.Buffer` and `semmle.code.cpp.commons.NullTermination` libraries no longer expose `semmle.code.cpp.dataflow.DataFlow`. Please import `semmle.code.cpp.dataflow.DataFlow` directly.
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Deleted the deprecated `hasGeneratedCopyConstructor` and `hasGeneratedCopyAssignmentOperator` predicates from the `Folder` class.
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getMustlockFunction`, `getTrylockFunction`, `getLockFunction`, and `getUnlockFunction` predicates from the `MutexType` class.
|
||||
* Deleted the deprecated `getPosInBasicBlock` predicate from the `SubBasicBlock` class.
|
||||
* Deleted the deprecated `getExpr` predicate from the `PointerDereferenceExpr` class.
|
||||
* Deleted the deprecated `getUseInstruction` and `getDefinitionInstruction` predicates from the `Operand` class.
|
||||
* Deleted the deprecated `isInParameter`, `isInParameterPointer`, and `isInQualifier` predicates from the `FunctionInput` class.
|
||||
* Deleted the deprecated `isOutParameterPointer`, `isOutQualifier`, `isOutReturnValue`, and `isOutReturnPointer` predicate from the `FunctionOutput` class.
|
||||
* Deleted the deprecated 3-argument `isGuardPhi` predicate from the `RangeSsaDefinition` class.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `WriteConfig` taint tracking configuration has been deprecated. Please use `WriteFlow`.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* A new C/C++ dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) has been added.
|
||||
The new library behaves much more like the dataflow library of other CodeQL supported
|
||||
languages by following use-use dataflow paths instead of def-use dataflow paths.
|
||||
The new library also better supports dataflow through indirections, and new predicates
|
||||
such as `Node::asIndirectExpr` have been added to facilitate working with indirections.
|
||||
|
||||
The `semmle.code.cpp.ir.dataflow.DataFlow` library is now identical to the new
|
||||
`semmle.code.cpp.dataflow.new.DataFlow` library.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `SslContextCallAbstractConfig`, `SslContextCallConfig`, `SslContextCallBannedProtocolConfig`, `SslContextCallTls12ProtocolConfig`, `SslContextCallTls13ProtocolConfig`, `SslContextCallTlsProtocolConfig`, `SslContextFlowsToSetOptionConfig`, `SslOptionConfig` dataflow configurations from `BoostorgAsio` have been deprecated. Please use `SslContextCallConfigSig`, `SslContextCallMake`, `SslContextCallFlow`, `SslContextCallBannedProtocolFlow`, `SslContextCallTls12ProtocolFlow`, `SslContextCallTls13ProtocolFlow`, `SslContextCallTlsProtocolFlow`, `SslContextFlowsToSetOptionFlow`.
|
||||
4
cpp/ql/lib/change-notes/2023-03-21-buffer-access.md
Normal file
4
cpp/ql/lib/change-notes/2023-03-21-buffer-access.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `BufferAccess` library (`semmle.code.cpp.security.BufferAccess`) no longer matches buffer accesses inside unevaluated contexts (such as inside `sizeof` or `decltype` expressions). As a result, queries using this library may see fewer false positives.
|
||||
42
cpp/ql/lib/change-notes/released/0.6.0.md
Normal file
42
cpp/ql/lib/change-notes/released/0.6.0.md
Normal file
@@ -0,0 +1,42 @@
|
||||
## 0.6.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `semmle.code.cpp.commons.Buffer` and `semmle.code.cpp.commons.NullTermination` libraries no longer expose `semmle.code.cpp.dataflow.DataFlow`. Please import `semmle.code.cpp.dataflow.DataFlow` directly.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `WriteConfig` taint tracking configuration has been deprecated. Please use `WriteFlow`.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* A new C/C++ dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) has been added.
|
||||
The new library behaves much more like the dataflow library of other CodeQL supported
|
||||
languages by following use-use dataflow paths instead of def-use dataflow paths.
|
||||
The new library also better supports dataflow through indirections, and new predicates
|
||||
such as `Node::asIndirectExpr` have been added to facilitate working with indirections.
|
||||
|
||||
The `semmle.code.cpp.ir.dataflow.DataFlow` library is now identical to the new
|
||||
`semmle.code.cpp.dataflow.new.DataFlow` library.
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `hasGeneratedCopyConstructor` and `hasGeneratedCopyAssignmentOperator` predicates from the `Folder` class.
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getMustlockFunction`, `getTrylockFunction`, `getLockFunction`, and `getUnlockFunction` predicates from the `MutexType` class.
|
||||
* Deleted the deprecated `getPosInBasicBlock` predicate from the `SubBasicBlock` class.
|
||||
* Deleted the deprecated `getExpr` predicate from the `PointerDereferenceExpr` class.
|
||||
* Deleted the deprecated `getUseInstruction` and `getDefinitionInstruction` predicates from the `Operand` class.
|
||||
* Deleted the deprecated `isInParameter`, `isInParameterPointer`, and `isInQualifier` predicates from the `FunctionInput` class.
|
||||
* Deleted the deprecated `isOutParameterPointer`, `isOutQualifier`, `isOutReturnValue`, and `isOutReturnPointer` predicate from the `FunctionOutput` class.
|
||||
* Deleted the deprecated 3-argument `isGuardPhi` predicate from the `RangeSsaDefinition` class.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.5.4
|
||||
lastReleaseVersion: 0.6.0
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
private import SemanticExpr
|
||||
private import SemanticExprSpecific::SemanticExprConfig as Specific
|
||||
private import SemanticSSA
|
||||
private import SemanticLocation
|
||||
|
||||
/**
|
||||
* A valid base for an expression bound.
|
||||
@@ -14,6 +15,8 @@ private import SemanticSSA
|
||||
class SemBound instanceof Specific::Bound {
|
||||
final string toString() { result = super.toString() }
|
||||
|
||||
final SemLocation getLocation() { result = super.getLocation() }
|
||||
|
||||
final SemExpr getExpr(int delta) { result = Specific::getBoundExpr(this, delta) }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
private import semmle.code.cpp.Location
|
||||
|
||||
class SemLocation instanceof Location {
|
||||
/**
|
||||
* Gets a textual representation of this element.
|
||||
*
|
||||
* The format is "file://filePath:startLine:startColumn:endLine:endColumn".
|
||||
*/
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
@@ -250,16 +250,26 @@ SemType getSemanticType(Specific::Type type) {
|
||||
Specific::unknownType(type) and result = TSemUnknownType()
|
||||
}
|
||||
|
||||
private class SemNumericOrBooleanType extends SemSizedType {
|
||||
SemNumericOrBooleanType() {
|
||||
this instanceof SemNumericType
|
||||
or
|
||||
this instanceof SemBooleanType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the conversion from `fromType` to `toType` can never overflow or underflow.
|
||||
*/
|
||||
predicate conversionCannotOverflow(SemNumericType fromType, SemNumericType toType) {
|
||||
predicate conversionCannotOverflow(SemNumericOrBooleanType fromType, SemNumericOrBooleanType toType) {
|
||||
// Identity cast
|
||||
fromType = toType
|
||||
or
|
||||
// Treat any cast to an FP type as safe. It can lose precision, but not overflow.
|
||||
toType instanceof SemFloatingPointType and fromType = any(SemNumericType n)
|
||||
or
|
||||
fromType instanceof SemBooleanType and toType instanceof SemIntegerType
|
||||
or
|
||||
exists(SemIntegerType fromInteger, SemIntegerType toInteger, int fromSize, int toSize |
|
||||
fromInteger = fromType and
|
||||
toInteger = toType and
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
private import RangeAnalysisStage
|
||||
|
||||
module IntDelta implements DeltaSig {
|
||||
class Delta = int;
|
||||
|
||||
bindingset[d]
|
||||
bindingset[result]
|
||||
float toFloat(Delta d) { result = d }
|
||||
|
||||
bindingset[d]
|
||||
bindingset[result]
|
||||
int toInt(Delta d) { result = d }
|
||||
|
||||
bindingset[n]
|
||||
bindingset[result]
|
||||
Delta fromInt(int n) { result = n }
|
||||
|
||||
bindingset[f]
|
||||
Delta fromFloat(float f) {
|
||||
result =
|
||||
min(float diff, float res |
|
||||
diff = (res - f) and res = f.ceil()
|
||||
or
|
||||
diff = (f - res) and res = f.floor()
|
||||
|
|
||||
res order by diff
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,2 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisSpecific
|
||||
private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
|
||||
private import RangeUtils
|
||||
private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound
|
||||
|
||||
module Bounds implements BoundSig<FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
|
||||
}
|
||||
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
private module CppRangeAnalysis =
|
||||
RangeStage<FloatDelta, Bounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
|
||||
import CppRangeAnalysis
|
||||
import RangeAnalysisImpl
|
||||
import experimental.semmle.code.cpp.semantic.SemanticBound
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisSpecific
|
||||
private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
|
||||
private import RangeUtils
|
||||
private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound
|
||||
private import experimental.semmle.code.cpp.semantic.SemanticLocation
|
||||
private import experimental.semmle.code.cpp.semantic.SemanticSSA
|
||||
|
||||
module ConstantBounds implements BoundSig<FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
SemBound() {
|
||||
this instanceof SemanticBound::SemZeroBound
|
||||
or
|
||||
this.(SemanticBound::SemSsaBound).getAVariable() instanceof SemSsaPhiNode
|
||||
}
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
SemLocation getLocation() { result = super.getLocation() }
|
||||
|
||||
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
|
||||
}
|
||||
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
private module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
SemBound() { not this instanceof SemanticBound::SemZeroBound }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
SemLocation getLocation() { result = super.getLocation() }
|
||||
|
||||
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
|
||||
}
|
||||
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
private module ConstantStage =
|
||||
RangeStage<FloatDelta, ConstantBounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
|
||||
private module RelativeStage =
|
||||
RangeStage<FloatDelta, RelativeBounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
|
||||
private newtype TSemReason =
|
||||
TSemNoReason() or
|
||||
TSemCondReason(SemGuard guard) {
|
||||
guard = any(ConstantStage::SemCondReason reason).getCond()
|
||||
or
|
||||
guard = any(RelativeStage::SemCondReason reason).getCond()
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound. This can either be `CondReason` if the bound
|
||||
* is due to a specific condition, or `NoReason` if the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
abstract class SemReason extends TSemReason {
|
||||
/** Gets a textual representation of this reason. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound that indicates that the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class SemNoReason extends SemReason, TSemNoReason {
|
||||
override string toString() { result = "NoReason" }
|
||||
}
|
||||
|
||||
/** A reason for an inferred bound pointing to a condition. */
|
||||
class SemCondReason extends SemReason, TSemCondReason {
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
SemGuard getCond() { this = TSemCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
}
|
||||
|
||||
private ConstantStage::SemReason constantReason(SemReason reason) {
|
||||
result instanceof ConstantStage::SemNoReason and reason instanceof SemNoReason
|
||||
or
|
||||
result.(ConstantStage::SemCondReason).getCond() = reason.(SemCondReason).getCond()
|
||||
}
|
||||
|
||||
private RelativeStage::SemReason relativeReason(SemReason reason) {
|
||||
result instanceof RelativeStage::SemNoReason and reason instanceof SemNoReason
|
||||
or
|
||||
result.(RelativeStage::SemCondReason).getCond() = reason.(SemCondReason).getCond()
|
||||
}
|
||||
|
||||
predicate semBounded(
|
||||
SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason
|
||||
) {
|
||||
ConstantStage::semBounded(e, b, delta, upper, constantReason(reason))
|
||||
or
|
||||
RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason))
|
||||
}
|
||||
@@ -73,6 +73,7 @@ import experimental.semmle.code.cpp.semantic.SemanticCFG
|
||||
import experimental.semmle.code.cpp.semantic.SemanticType
|
||||
import experimental.semmle.code.cpp.semantic.SemanticOpcode
|
||||
private import ConstantAnalysis
|
||||
import experimental.semmle.code.cpp.semantic.SemanticLocation
|
||||
|
||||
/**
|
||||
* Holds if `typ` is a small integral type with the given lower and upper bounds.
|
||||
@@ -228,6 +229,10 @@ signature module UtilSig<DeltaSig DeltaParam> {
|
||||
|
||||
signature module BoundSig<DeltaSig D> {
|
||||
class SemBound {
|
||||
string toString();
|
||||
|
||||
SemLocation getLocation();
|
||||
|
||||
SemExpr getExpr(D::Delta delta);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.5.5-dev
|
||||
version: 0.6.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -1145,19 +1145,13 @@ module Impl<FullStateConfigSig Config> {
|
||||
import Param
|
||||
|
||||
/* Begin: Stage logic. */
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
private predicate revFlowApAlias(NodeEx node, ApApprox apa) {
|
||||
PrevStage::revFlowAp(node, apa)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallApa(
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
||||
) {
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and
|
||||
revFlowApAlias(arg, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1167,7 +1161,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and
|
||||
revFlowApAlias(ret, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1695,16 +1689,6 @@ module Impl<FullStateConfigSig Config> {
|
||||
pragma[nomagic]
|
||||
predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) {
|
||||
revFlow(node, state, ap)
|
||||
}
|
||||
|
||||
private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) }
|
||||
|
||||
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
||||
@@ -1978,7 +1962,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
||||
Stage2::revFlow(node2) and
|
||||
Stage2::revFlowAlias(node1)
|
||||
Stage2::revFlow(node1)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1987,7 +1971,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
||||
Stage2::revFlow(node2) and
|
||||
Stage2::revFlowAlias(node1)
|
||||
Stage2::revFlow(node1)
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
@@ -2069,11 +2053,11 @@ module Impl<FullStateConfigSig Config> {
|
||||
additionalLocalFlowStepNodeCand1(node1, node2) and
|
||||
state1 = state2 and
|
||||
Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and
|
||||
Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false)
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](state2), false)
|
||||
or
|
||||
additionalLocalStateStep(node1, state1, node2, state2) and
|
||||
Stage2::revFlow(node1, state1, false) and
|
||||
Stage2::revFlowAlias(node2, state2, false)
|
||||
Stage2::revFlow(node2, state2, false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2266,7 +2250,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and
|
||||
exists(lcc)
|
||||
}
|
||||
|
||||
@@ -2277,7 +2261,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2288,7 +2272,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2590,7 +2574,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _)
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -2600,7 +2584,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2611,7 +2595,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -140,10 +140,8 @@ private module LambdaFlow {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TReturnPositionSimple viableReturnPosLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind
|
||||
) {
|
||||
result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind)
|
||||
private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) {
|
||||
result = TReturnPositionSimple0(viableCallableLambda(call, _), kind)
|
||||
}
|
||||
|
||||
private predicate viableReturnPosOutNonLambda(
|
||||
@@ -155,11 +153,12 @@ private module LambdaFlow {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate viableReturnPosOutLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out
|
||||
DataFlowCall call, TReturnPositionSimple pos, OutNode out
|
||||
) {
|
||||
exists(ReturnKind kind |
|
||||
pos = viableReturnPosLambda(call, lastCall, kind) and
|
||||
pos = viableReturnPosLambda(call, kind) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
@@ -188,6 +187,7 @@ private module LambdaFlow {
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlow0(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
|
||||
@@ -274,6 +274,7 @@ private module LambdaFlow {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowOut(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,
|
||||
@@ -285,7 +286,7 @@ private module LambdaFlow {
|
||||
or
|
||||
// non-linear recursion
|
||||
revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and
|
||||
viableReturnPosOutLambda(call, _, pos, out)
|
||||
viableReturnPosOutLambda(call, pos, out)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1145,19 +1145,13 @@ module Impl<FullStateConfigSig Config> {
|
||||
import Param
|
||||
|
||||
/* Begin: Stage logic. */
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
private predicate revFlowApAlias(NodeEx node, ApApprox apa) {
|
||||
PrevStage::revFlowAp(node, apa)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallApa(
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
||||
) {
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and
|
||||
revFlowApAlias(arg, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1167,7 +1161,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and
|
||||
revFlowApAlias(ret, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1695,16 +1689,6 @@ module Impl<FullStateConfigSig Config> {
|
||||
pragma[nomagic]
|
||||
predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) }
|
||||
|
||||
// use an alias as a workaround for bad functionality-induced joins
|
||||
pragma[nomagic]
|
||||
additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) {
|
||||
revFlow(node, state, ap)
|
||||
}
|
||||
|
||||
private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) }
|
||||
|
||||
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
||||
@@ -1978,7 +1962,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
||||
Stage2::revFlow(node2) and
|
||||
Stage2::revFlowAlias(node1)
|
||||
Stage2::revFlow(node1)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1987,7 +1971,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
||||
Stage2::revFlow(node2) and
|
||||
Stage2::revFlowAlias(node1)
|
||||
Stage2::revFlow(node1)
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
@@ -2069,11 +2053,11 @@ module Impl<FullStateConfigSig Config> {
|
||||
additionalLocalFlowStepNodeCand1(node1, node2) and
|
||||
state1 = state2 and
|
||||
Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and
|
||||
Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false)
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](state2), false)
|
||||
or
|
||||
additionalLocalStateStep(node1, state1, node2, state2) and
|
||||
Stage2::revFlow(node1, state1, false) and
|
||||
Stage2::revFlowAlias(node2, state2, false)
|
||||
Stage2::revFlow(node2, state2, false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2266,7 +2250,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and
|
||||
exists(lcc)
|
||||
}
|
||||
|
||||
@@ -2277,7 +2261,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2288,7 +2272,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2590,7 +2574,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _)
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -2600,7 +2584,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2611,7 +2595,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
exists(FlowState state |
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and
|
||||
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _)
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state), _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -140,10 +140,8 @@ private module LambdaFlow {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TReturnPositionSimple viableReturnPosLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind
|
||||
) {
|
||||
result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind)
|
||||
private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) {
|
||||
result = TReturnPositionSimple0(viableCallableLambda(call, _), kind)
|
||||
}
|
||||
|
||||
private predicate viableReturnPosOutNonLambda(
|
||||
@@ -155,11 +153,12 @@ private module LambdaFlow {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate viableReturnPosOutLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out
|
||||
DataFlowCall call, TReturnPositionSimple pos, OutNode out
|
||||
) {
|
||||
exists(ReturnKind kind |
|
||||
pos = viableReturnPosLambda(call, lastCall, kind) and
|
||||
pos = viableReturnPosLambda(call, kind) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
@@ -188,6 +187,7 @@ private module LambdaFlow {
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlow0(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
|
||||
@@ -274,6 +274,7 @@ private module LambdaFlow {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowOut(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,
|
||||
@@ -285,7 +286,7 @@ private module LambdaFlow {
|
||||
or
|
||||
// non-linear recursion
|
||||
revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and
|
||||
viableReturnPosOutLambda(call, _, pos, out)
|
||||
viableReturnPosOutLambda(call, pos, out)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow3
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.ResolveCall
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
@@ -90,65 +89,64 @@ private predicate conflatePointerAndPointee(DataFlow::Node nodeFrom, DataFlow::N
|
||||
)
|
||||
}
|
||||
|
||||
private class DefaultTaintTrackingCfg extends TaintTracking::Configuration {
|
||||
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
||||
private module DefaultTaintTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
|
||||
predicate isSink(DataFlow::Node sink) { exists(adjustedSink(sink)) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { exists(adjustedSink(sink)) }
|
||||
predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
|
||||
override predicate isSanitizerIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
conflatePointerAndPointee(nodeFrom, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
private class ToGlobalVarTaintTrackingCfg extends TaintTracking::Configuration {
|
||||
ToGlobalVarTaintTrackingCfg() { this = "GlobalVarTaintTrackingCfg" }
|
||||
private module DefaultTaintTrackingFlow = TaintTracking::Make<DefaultTaintTrackingConfig>;
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
|
||||
private module ToGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink.asVariable() instanceof GlobalOrNamespaceVariable
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { sink.asVariable() instanceof GlobalOrNamespaceVariable }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable))
|
||||
or
|
||||
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isSanitizerIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private class FromGlobalVarTaintTrackingCfg extends TaintTracking2::Configuration {
|
||||
FromGlobalVarTaintTrackingCfg() { this = "FromGlobalVarTaintTrackingCfg" }
|
||||
private module ToGlobalVarTaintTrackingFlow = TaintTracking::Make<ToGlobalVarTaintTrackingConfig>;
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
private module FromGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// This set of sources should be reasonably small, which is good for
|
||||
// performance since the set of sinks is very large.
|
||||
exists(ToGlobalVarTaintTrackingCfg otherCfg | otherCfg.hasFlowTo(source))
|
||||
ToGlobalVarTaintTrackingFlow::hasFlowTo(source)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { exists(adjustedSink(sink)) }
|
||||
predicate isSink(DataFlow::Node sink) { exists(adjustedSink(sink)) }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
// Additional step for flow out of variables. There is no flow _into_
|
||||
// variables in this configuration, so this step only serves to take flow
|
||||
// out of a variable that's a source.
|
||||
readsVariable(n2.asInstruction(), n1.asVariable())
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isSanitizerIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private module FromGlobalVarTaintTrackingFlow =
|
||||
TaintTracking::Make<FromGlobalVarTaintTrackingConfig>;
|
||||
|
||||
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
@@ -332,8 +330,8 @@ private import Cached
|
||||
*/
|
||||
cached
|
||||
predicate tainted(Expr source, Element tainted) {
|
||||
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
|
||||
cfg.hasFlow(getNodeForSource(source), sink) and
|
||||
exists(DataFlow::Node sink |
|
||||
DefaultTaintTrackingFlow::hasFlow(getNodeForSource(source), sink) and
|
||||
tainted = adjustedSink(sink)
|
||||
)
|
||||
}
|
||||
@@ -359,12 +357,11 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
|
||||
globalVar = ""
|
||||
or
|
||||
exists(
|
||||
ToGlobalVarTaintTrackingCfg toCfg, FromGlobalVarTaintTrackingCfg fromCfg,
|
||||
DataFlow::VariableNode variableNode, GlobalOrNamespaceVariable global, DataFlow::Node sink
|
||||
|
|
||||
global = variableNode.getVariable() and
|
||||
toCfg.hasFlow(getNodeForSource(source), variableNode) and
|
||||
fromCfg.hasFlow(variableNode, sink) and
|
||||
ToGlobalVarTaintTrackingFlow::hasFlow(getNodeForSource(source), variableNode) and
|
||||
FromGlobalVarTaintTrackingFlow::hasFlow(variableNode, sink) and
|
||||
tainted = adjustedSink(sink) and
|
||||
global = globalVarFromId(globalVar)
|
||||
)
|
||||
@@ -422,20 +419,18 @@ module TaintedWithPath {
|
||||
string toString() { result = "TaintTrackingConfiguration" }
|
||||
}
|
||||
|
||||
private class AdjustedConfiguration extends TaintTracking3::Configuration {
|
||||
AdjustedConfiguration() { this = "AdjustedConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
private module AdjustedConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(TaintTrackingConfiguration cfg, Expr e |
|
||||
cfg.isSource(e) and source = getNodeForExpr(e)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(TaintTrackingConfiguration cfg | cfg.isSink(adjustedSink(sink)))
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
conflatePointerAndPointee(n1, n2)
|
||||
or
|
||||
// Steps into and out of global variables
|
||||
@@ -448,13 +443,15 @@ module TaintedWithPath {
|
||||
additionalTaintStep(n1, n2)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(TaintTrackingConfiguration cfg, Expr e | cfg.isBarrier(e) and node = getNodeForExpr(e))
|
||||
}
|
||||
|
||||
override predicate isSanitizerIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private module AdjustedFlow = TaintTracking::Make<AdjustedConfig>;
|
||||
|
||||
/*
|
||||
* A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the
|
||||
* inverse of) `adjustedSink`. For example, an `Expr` maps to all its
|
||||
@@ -470,12 +467,12 @@ module TaintedWithPath {
|
||||
*/
|
||||
|
||||
private newtype TPathNode =
|
||||
TWrapPathNode(DataFlow3::PathNode n) or
|
||||
TWrapPathNode(AdjustedFlow::PathNode n) or
|
||||
// There's a single newtype constructor for both sources and sinks since
|
||||
// that makes it easiest to deal with the case where source = sink.
|
||||
TEndpointPathNode(Element e) {
|
||||
exists(AdjustedConfiguration cfg, DataFlow3::Node sourceNode, DataFlow3::Node sinkNode |
|
||||
cfg.hasFlow(sourceNode, sinkNode)
|
||||
exists(DataFlow::Node sourceNode, DataFlow::Node sinkNode |
|
||||
AdjustedFlow::hasFlow(sourceNode, sinkNode)
|
||||
|
|
||||
sourceNode = getNodeForExpr(e) and
|
||||
exists(TaintTrackingConfiguration ttCfg | ttCfg.isSource(e))
|
||||
@@ -524,7 +521,7 @@ module TaintedWithPath {
|
||||
}
|
||||
|
||||
private class WrapPathNode extends PathNode, TWrapPathNode {
|
||||
DataFlow3::PathNode inner() { this = TWrapPathNode(result) }
|
||||
AdjustedFlow::PathNode inner() { this = TWrapPathNode(result) }
|
||||
|
||||
override string toString() { result = this.inner().toString() }
|
||||
|
||||
@@ -561,25 +558,25 @@ module TaintedWithPath {
|
||||
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) {
|
||||
DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), b.(WrapPathNode).inner())
|
||||
AdjustedFlow::PathGraph::edges(a.(WrapPathNode).inner(), b.(WrapPathNode).inner())
|
||||
or
|
||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||
// of adding an edge out of it.
|
||||
exists(WrapPathNode sinkNode |
|
||||
DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
AdjustedFlow::PathGraph::edges(a.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
or
|
||||
// Same for the first node
|
||||
exists(WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::edges(sourceNode.inner(), b.(WrapPathNode).inner()) and
|
||||
AdjustedFlow::PathGraph::edges(sourceNode.inner(), b.(WrapPathNode).inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner())
|
||||
)
|
||||
or
|
||||
// Finally, handle the case where the path goes directly from a source to a
|
||||
// sink, meaning that they both need to be translated.
|
||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::edges(sourceNode.inner(), sinkNode.inner()) and
|
||||
AdjustedFlow::PathGraph::edges(sourceNode.inner(), sinkNode.inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner()) and
|
||||
b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
@@ -590,20 +587,20 @@ module TaintedWithPath {
|
||||
* from `par` to `ret` within it, in the graph of data flow path explanations.
|
||||
*/
|
||||
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
AdjustedFlow::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner())
|
||||
or
|
||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||
// of adding an edge out of it.
|
||||
exists(WrapPathNode sinkNode |
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
AdjustedFlow::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
or
|
||||
// Same for the first node
|
||||
exists(WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
AdjustedFlow::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner())
|
||||
)
|
||||
@@ -611,7 +608,7 @@ module TaintedWithPath {
|
||||
// Finally, handle the case where the path goes directly from a source to a
|
||||
// sink, meaning that they both need to be translated.
|
||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
AdjustedFlow::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
@@ -634,10 +631,10 @@ module TaintedWithPath {
|
||||
* the computation.
|
||||
*/
|
||||
predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) {
|
||||
exists(AdjustedConfiguration cfg, DataFlow3::Node flowSource, DataFlow3::Node flowSink |
|
||||
exists(DataFlow::Node flowSource, DataFlow::Node flowSink |
|
||||
source = sourceNode.(InitialPathNode).inner() and
|
||||
flowSource = getNodeForExpr(source) and
|
||||
cfg.hasFlow(flowSource, flowSink) and
|
||||
AdjustedFlow::hasFlow(flowSource, flowSink) and
|
||||
tainted = adjustedSink(flowSink) and
|
||||
tainted = sinkNode.(FinalPathNode).inner()
|
||||
)
|
||||
@@ -660,8 +657,8 @@ module TaintedWithPath {
|
||||
* through a global variable.
|
||||
*/
|
||||
predicate taintedWithoutGlobals(Element tainted) {
|
||||
exists(AdjustedConfiguration cfg, PathNode sourceNode, FinalPathNode sinkNode |
|
||||
cfg.isSource(sourceNode.(WrapPathNode).inner().getNode()) and
|
||||
exists(PathNode sourceNode, FinalPathNode sinkNode |
|
||||
AdjustedConfig::isSource(sourceNode.(WrapPathNode).inner().getNode()) and
|
||||
edgesWithoutGlobals+(sourceNode, sinkNode) and
|
||||
tainted = sinkNode.inner()
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import IR
|
||||
import InstructionConsistency // module is below
|
||||
import IRTypeConsistency // module is in IRType.qll
|
||||
import internal.IRConsistencyImports
|
||||
|
||||
module InstructionConsistency {
|
||||
private import internal.InstructionImports as Imports
|
||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||
|
||||
override string toString() {
|
||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
||||
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||
}
|
||||
|
||||
override Language::Location getLocation() {
|
||||
|
||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
||||
|
||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
||||
|
||||
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
|
||||
override string getLabel() {
|
||||
result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction())
|
||||
}
|
||||
|
||||
override int getOrder() {
|
||||
this =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import AliasAnalysis
|
||||
import semmle.code.cpp.Location
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
private import semmle.code.cpp.Print
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.IRConfiguration as IRConfiguration
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
|
||||
@@ -1,2 +1,55 @@
|
||||
private import SSAConstruction as Ssa
|
||||
import Ssa::SsaConsistency
|
||||
import SsaConsistency
|
||||
import SSAConsistencyImports
|
||||
|
||||
module SsaConsistency {
|
||||
/**
|
||||
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
|
||||
*/
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
|
||||
" memory accesses in function '$@': " +
|
||||
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` does not have an associated `VirtualVariable`.
|
||||
*/
|
||||
query predicate missingVirtualVariableForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
not exists(location.getVirtualVariable()) and
|
||||
func = location.getIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message = "Memory location has no virtual variable in function '$@'."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`.
|
||||
*/
|
||||
query predicate multipleVirtualVariablesForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int vvarCount |
|
||||
vvarCount = strictcount(location.getVirtualVariable()) and
|
||||
vvarCount > 1 and
|
||||
func = location.getIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
"Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" +
|
||||
concat(Alias::VirtualVariable vvar |
|
||||
vvar = location.getVirtualVariable()
|
||||
|
|
||||
vvar.toString(), ", "
|
||||
) + ")."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.IR as OldIR
|
||||
import AliasedSSA as Alias
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
@@ -996,7 +996,7 @@ deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSSA` module, which is then imported by PrintSSA.
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
*/
|
||||
module DebugSsa {
|
||||
import PhiInsertion
|
||||
@@ -1063,62 +1063,6 @@ private module CachedForDebugging {
|
||||
int maxValue() { result = 2147483647 }
|
||||
}
|
||||
|
||||
module SsaConsistency {
|
||||
/**
|
||||
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
|
||||
*/
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
|
||||
" memory accesses in function '$@': " +
|
||||
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` does not have an associated `VirtualVariable`.
|
||||
*/
|
||||
query predicate missingVirtualVariableForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
not exists(location.getVirtualVariable()) and
|
||||
func = location.getIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message = "Memory location has no virtual variable in function '$@'."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`.
|
||||
*/
|
||||
query predicate multipleVirtualVariablesForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int vvarCount |
|
||||
vvarCount = strictcount(location.getVirtualVariable()) and
|
||||
vvarCount > 1 and
|
||||
func = location.getIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
"Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" +
|
||||
concat(Alias::VirtualVariable vvar |
|
||||
vvar = location.getVirtualVariable()
|
||||
|
|
||||
vvar.toString(), ", "
|
||||
) + ")."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaConsistency */
|
||||
deprecated module SSAConsistency = SsaConsistency;
|
||||
|
||||
/**
|
||||
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages
|
||||
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import IR
|
||||
import InstructionConsistency // module is below
|
||||
import IRTypeConsistency // module is in IRType.qll
|
||||
import internal.IRConsistencyImports
|
||||
|
||||
module InstructionConsistency {
|
||||
private import internal.InstructionImports as Imports
|
||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||
|
||||
override string toString() {
|
||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
||||
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||
}
|
||||
|
||||
override Language::Location getLocation() {
|
||||
|
||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
||||
|
||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
||||
|
||||
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
|
||||
override string getLabel() {
|
||||
result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction())
|
||||
}
|
||||
|
||||
override int getOrder() {
|
||||
this =
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.IRConfiguration as IRConfiguration
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import IR
|
||||
import InstructionConsistency // module is below
|
||||
import IRTypeConsistency // module is in IRType.qll
|
||||
import internal.IRConsistencyImports
|
||||
|
||||
module InstructionConsistency {
|
||||
private import internal.InstructionImports as Imports
|
||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||
|
||||
override string toString() {
|
||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
||||
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||
}
|
||||
|
||||
override Language::Location getLocation() {
|
||||
|
||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
||||
|
||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
||||
|
||||
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
|
||||
override string getLabel() {
|
||||
result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction())
|
||||
}
|
||||
|
||||
override int getOrder() {
|
||||
this =
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.IRConfiguration as IRConfiguration
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
|
||||
@@ -1,2 +1,55 @@
|
||||
private import SSAConstruction as Ssa
|
||||
import Ssa::SsaConsistency
|
||||
import SsaConsistency
|
||||
import SSAConsistencyImports
|
||||
|
||||
module SsaConsistency {
|
||||
/**
|
||||
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
|
||||
*/
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
|
||||
" memory accesses in function '$@': " +
|
||||
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` does not have an associated `VirtualVariable`.
|
||||
*/
|
||||
query predicate missingVirtualVariableForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
not exists(location.getVirtualVariable()) and
|
||||
func = location.getIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message = "Memory location has no virtual variable in function '$@'."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`.
|
||||
*/
|
||||
query predicate multipleVirtualVariablesForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int vvarCount |
|
||||
vvarCount = strictcount(location.getVirtualVariable()) and
|
||||
vvarCount > 1 and
|
||||
func = location.getIRFunction() and
|
||||
funcText = LanguageDebug::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
"Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" +
|
||||
concat(Alias::VirtualVariable vvar |
|
||||
vvar = location.getVirtualVariable()
|
||||
|
|
||||
vvar.toString(), ", "
|
||||
) + ")."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.IR as OldIR
|
||||
import SimpleSSA as Alias
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||
@@ -996,7 +996,7 @@ deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSSA` module, which is then imported by PrintSSA.
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
*/
|
||||
module DebugSsa {
|
||||
import PhiInsertion
|
||||
@@ -1063,62 +1063,6 @@ private module CachedForDebugging {
|
||||
int maxValue() { result = 2147483647 }
|
||||
}
|
||||
|
||||
module SsaConsistency {
|
||||
/**
|
||||
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
|
||||
*/
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
|
||||
" memory accesses in function '$@': " +
|
||||
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` does not have an associated `VirtualVariable`.
|
||||
*/
|
||||
query predicate missingVirtualVariableForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
not exists(location.getVirtualVariable()) and
|
||||
func = location.getIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message = "Memory location has no virtual variable in function '$@'."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`.
|
||||
*/
|
||||
query predicate multipleVirtualVariablesForMemoryLocation(
|
||||
Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int vvarCount |
|
||||
vvarCount = strictcount(location.getVirtualVariable()) and
|
||||
vvarCount > 1 and
|
||||
func = location.getIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message =
|
||||
"Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" +
|
||||
concat(Alias::VirtualVariable vvar |
|
||||
vvar = location.getVirtualVariable()
|
||||
|
|
||||
vvar.toString(), ", "
|
||||
) + ")."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaConsistency */
|
||||
deprecated module SSAConsistency = SsaConsistency;
|
||||
|
||||
/**
|
||||
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages
|
||||
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.Print
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction::Raw as Raw
|
||||
|
||||
@@ -538,12 +537,14 @@ CppType getCanonicalOpaqueType(Type tag, int byteSize) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string that uniquely identifies an `IROpaqueType` tag. This may be different from the usual
|
||||
* `toString()` of the tag in order to ensure uniqueness.
|
||||
* Gets a string that uniquely identifies an `IROpaqueType` tag. Using `toString` here might
|
||||
* not be sufficient to ensure uniqueness, but suffices for our current debugging purposes.
|
||||
* To ensure uniqueness `getOpaqueTagIdentityString` from `semmle.code.cpp.Print` could be used,
|
||||
* but that comes at the cost of importing all the `Dump` classes defined in that library.
|
||||
*/
|
||||
string getOpaqueTagIdentityString(Type tag) {
|
||||
hasOpaqueType(tag, _) and
|
||||
result = getTypeIdentityString(tag)
|
||||
result = tag.toString()
|
||||
}
|
||||
|
||||
module LanguageTypeConsistency {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
private import cpp as Cpp
|
||||
private import semmle.code.cpp.Print as Print
|
||||
private import IRUtilities
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
@@ -65,8 +64,6 @@ class Expr = Cpp::Expr;
|
||||
|
||||
class Class = Cpp::Class; // Used for inheritance conversions
|
||||
|
||||
predicate getIdentityString = Print::getIdentityString/1;
|
||||
|
||||
predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) }
|
||||
|
||||
predicate hasPositionalArgIndex(int argIndex) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
private import semmle.code.cpp.Print as Print
|
||||
|
||||
predicate getIdentityString = Print::getIdentityString/1;
|
||||
@@ -14,6 +14,8 @@ int getPointedSize(Type t) {
|
||||
* BufferWrite differ.
|
||||
*/
|
||||
abstract class BufferAccess extends Expr {
|
||||
BufferAccess() { not this.isUnevaluated() }
|
||||
|
||||
abstract string getName();
|
||||
|
||||
/**
|
||||
|
||||
@@ -357,7 +357,7 @@ module BoostorgAsio {
|
||||
* Abstract class for flows of protocol values to the first argument of a context
|
||||
* constructor.
|
||||
*/
|
||||
abstract class SslContextCallAbstractConfig extends DataFlow::Configuration {
|
||||
abstract deprecated class SslContextCallAbstractConfig extends DataFlow::Configuration {
|
||||
bindingset[this]
|
||||
SslContextCallAbstractConfig() { any() }
|
||||
|
||||
@@ -369,10 +369,43 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature for flows of protocol values to the first argument of a context
|
||||
* constructor.
|
||||
*/
|
||||
signature module SslContextCallConfigSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
predicate isSource(DataFlow::Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
default predicate isSink(DataFlow::Node sink) {
|
||||
exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() |
|
||||
c.getAContructorCall() = cc and
|
||||
cc.getArgument(0) = e
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a standard data flow computation for protocol values to the first argument
|
||||
* of a context constructor.
|
||||
*/
|
||||
module SslContextCallMake<SslContextCallConfigSig Config> {
|
||||
private module C implements DataFlow::ConfigSig {
|
||||
import Config
|
||||
}
|
||||
|
||||
import DataFlow::Make<C>
|
||||
}
|
||||
|
||||
/**
|
||||
* Any protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
class SslContextCallConfig extends SslContextCallAbstractConfig {
|
||||
deprecated class SslContextCallConfig extends SslContextCallAbstractConfig {
|
||||
SslContextCallConfig() { this = "SslContextCallConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -383,10 +416,24 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Any protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
private module SslContextCallConfig implements SslContextCallConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextCallFlow = SslContextCallMake<SslContextCallConfig>;
|
||||
|
||||
/**
|
||||
* A banned protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig {
|
||||
deprecated class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig {
|
||||
SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -398,10 +445,25 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A banned protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
private module SslContextCallBannedProtocolConfig implements SslContextCallConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
isExprBannedBoostProtocol(e)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextCallBannedProtocolFlow = SslContextCallMake<SslContextCallBannedProtocolConfig>;
|
||||
|
||||
/**
|
||||
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig {
|
||||
deprecated class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig {
|
||||
SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -413,10 +475,25 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
private module SslContextCallTls12ProtocolConfig implements SslContextCallConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
isExprTls12BoostProtocol(e)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextCallTls12ProtocolFlow = SslContextCallMake<SslContextCallTls12ProtocolConfig>;
|
||||
|
||||
/**
|
||||
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig {
|
||||
deprecated class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig {
|
||||
SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -428,10 +505,25 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
private module SslContextCallTls13ProtocolConfig implements SslContextCallConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
isExprTls13BoostProtocol(e)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextCallTls13ProtocolFlow = SslContextCallMake<SslContextCallTls13ProtocolConfig>;
|
||||
|
||||
/**
|
||||
* A generic TLS protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig {
|
||||
deprecated class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig {
|
||||
SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -443,10 +535,25 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A generic TLS protocol value that flows to the first argument of a context constructor.
|
||||
*/
|
||||
private module SslContextCallTlsProtocolConfig implements SslContextCallConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
isExprTlsBoostProtocol(e)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextCallTlsProtocolFlow = SslContextCallMake<SslContextCallTlsProtocolConfig>;
|
||||
|
||||
/**
|
||||
* A context constructor call that flows to a call to `SetOptions()`.
|
||||
*/
|
||||
class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration {
|
||||
deprecated class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration {
|
||||
SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -467,10 +574,34 @@ module BoostorgAsio {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A context constructor call that flows to a call to `SetOptions()`.
|
||||
*/
|
||||
private module SslContextFlowsToSetOptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(SslContextClass c, ConstructorCall cc |
|
||||
cc = source.asExpr() and
|
||||
c.getAContructorCall() = cc
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc, SslSetOptionsFunction f, Variable v, VariableAccess va |
|
||||
va = sink.asExpr()
|
||||
|
|
||||
f.getACallToThisFunction() = fc and
|
||||
v.getAnAccess() = va and
|
||||
va = fc.getQualifier()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslContextFlowsToSetOptionFlow = DataFlow::Make<SslContextFlowsToSetOptionConfig>;
|
||||
|
||||
/**
|
||||
* An option value that flows to the first parameter of a call to `SetOptions()`.
|
||||
*/
|
||||
class SslOptionConfig extends DataFlow::Configuration {
|
||||
deprecated class SslOptionConfig extends DataFlow::Configuration {
|
||||
SslOptionConfig() { this = "SslOptionConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
@@ -488,4 +619,26 @@ module BoostorgAsio {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An option value that flows to the first parameter of a call to `SetOptions()`.
|
||||
*/
|
||||
private module SslOptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e | e = source.asExpr() |
|
||||
e.fromSource() and
|
||||
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(SslSetOptionsFunction f, FunctionCall call |
|
||||
sink.asExpr() = call.getArgument(0) and
|
||||
f.getACallToThisFunction() = call and
|
||||
not sink.getLocation().getFile().toString().matches("%/boost/asio/%")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SslOptionFlow = DataFlow::Make<SslOptionConfig>;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 0.5.5
|
||||
|
||||
### Deprecated Queries
|
||||
|
||||
* The `NetworkToBufferSizeConfiguration` and `UntrustedDataToExternalApiConfig` dataflow configurations have been deprecated. Please use `NetworkToBufferSizeFlow` and `UntrustedDataToExternalApiFlow`.
|
||||
* The `LeapYearCheckConfiguration`, `FiletimeYearArithmeticOperationCheckConfiguration`, and `PossibleYearArithmeticOperationCheckConfiguration` dataflow configurations have been deprecated. Please use `LeapYearCheckFlow`, `FiletimeYearArithmeticOperationCheckFlow` and `PossibleYearArithmeticOperationCheckFlow`.
|
||||
|
||||
## 0.5.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -22,7 +22,8 @@ import LoopBounds
|
||||
private predicate staticBufferBase(VariableAccess access, Variable v) {
|
||||
v.getType().(ArrayType).getBaseType() instanceof CharType and
|
||||
access = v.getAnAccess() and
|
||||
not memberMayBeVarSize(_, v)
|
||||
not memberMayBeVarSize(_, v) and
|
||||
not access.isUnevaluated()
|
||||
}
|
||||
|
||||
predicate staticBuffer(VariableAccess access, Variable v, int size) {
|
||||
|
||||
@@ -132,7 +132,7 @@ predicate isSinkImpl(DataFlow::Node sink, Expr formatString) {
|
||||
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
|
||||
}
|
||||
|
||||
module NonConstFlowConfiguration implements DataFlow::ConfigSig {
|
||||
module NonConstFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(boolean isIndirect, Type t |
|
||||
isNonConst(source, isIndirect) and
|
||||
@@ -146,7 +146,7 @@ module NonConstFlowConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) }
|
||||
}
|
||||
|
||||
module NonConstFlow = TaintTracking::Make<NonConstFlowConfiguration>;
|
||||
module NonConstFlow = TaintTracking::Make<NonConstFlowConfig>;
|
||||
|
||||
from FormattingFunctionCall call, Expr formatString
|
||||
where
|
||||
|
||||
@@ -223,7 +223,7 @@ deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration {
|
||||
* Data flow configuration for finding a variable access that would flow into
|
||||
* a function call that includes an operation to check for leap year.
|
||||
*/
|
||||
private module LeapYearCheckConfiguration implements DataFlow::ConfigSig {
|
||||
private module LeapYearCheckConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
@@ -231,7 +231,7 @@ private module LeapYearCheckConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module LeapYearCheckFlow = DataFlow::Make<LeapYearCheckConfiguration>;
|
||||
module LeapYearCheckFlow = DataFlow::Make<LeapYearCheckConfig>;
|
||||
|
||||
/**
|
||||
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
|
||||
@@ -264,7 +264,7 @@ deprecated class FiletimeYearArithmeticOperationCheckConfiguration extends DataF
|
||||
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
|
||||
* a `FILEINFO` field.
|
||||
*/
|
||||
private module FiletimeYearArithmeticOperationCheckConfiguration implements DataFlow::ConfigSig {
|
||||
private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Expr e, Operation op | e = source.asExpr() |
|
||||
op.getAChild*().getValue().toInt() = 365 and
|
||||
@@ -284,7 +284,7 @@ private module FiletimeYearArithmeticOperationCheckConfiguration implements Data
|
||||
}
|
||||
|
||||
module FiletimeYearArithmeticOperationCheckFlow =
|
||||
DataFlow::Make<FiletimeYearArithmeticOperationCheckConfiguration>;
|
||||
DataFlow::Make<FiletimeYearArithmeticOperationCheckConfig>;
|
||||
|
||||
/**
|
||||
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
|
||||
@@ -334,7 +334,7 @@ deprecated class PossibleYearArithmeticOperationCheckConfiguration extends Taint
|
||||
/**
|
||||
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
|
||||
*/
|
||||
private module PossibleYearArithmeticOperationCheckConfiguration implements DataFlow::ConfigSig {
|
||||
private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Operation op | op = source.asConvertedExpr() |
|
||||
op.getAChild*().getValue().toInt() = 365 and
|
||||
@@ -372,4 +372,4 @@ private module PossibleYearArithmeticOperationCheckConfiguration implements Data
|
||||
}
|
||||
|
||||
module PossibleYearArithmeticOperationCheckFlow =
|
||||
TaintTracking::Make<PossibleYearArithmeticOperationCheckConfiguration>;
|
||||
TaintTracking::Make<PossibleYearArithmeticOperationCheckConfig>;
|
||||
|
||||
@@ -147,7 +147,7 @@ deprecated class NetworkToBufferSizeConfiguration extends DataFlow::Configuratio
|
||||
}
|
||||
}
|
||||
|
||||
private module NetworkToBufferSizeConfiguration implements DataFlow::ConfigSig {
|
||||
private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node.asExpr() = any(BufferAccess ba).getAccessedLength() }
|
||||
@@ -161,4 +161,4 @@ private module NetworkToBufferSizeConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module NetworkToBufferSizeFlow = DataFlow::Make<NetworkToBufferSizeConfiguration>;
|
||||
module NetworkToBufferSizeFlow = DataFlow::Make<NetworkToBufferSizeConfig>;
|
||||
|
||||
@@ -33,13 +33,10 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
|
||||
ExistsAnyFlow::hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
|
||||
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
|
||||
contextSetOptions = fcSetOptions.getQualifier() and
|
||||
forall(
|
||||
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
|
||||
Expr optionArgumentSource
|
||||
|
|
||||
forall(Expr optionArgument, Expr optionArgumentSource |
|
||||
optionArgument = fcSetOptions.getArgument(0) and
|
||||
optionArgConfig
|
||||
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
||||
BoostorgAsio::SslOptionFlow::hasFlow(DataFlow::exprNode(optionArgumentSource),
|
||||
DataFlow::exprNode(optionArgument))
|
||||
|
|
||||
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
|
||||
)
|
||||
@@ -50,11 +47,10 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
|
||||
bindingset[flag]
|
||||
predicate isOptionNotSet(ConstructorCall cc, int flag) { not isOptionSet(cc, flag, _) }
|
||||
|
||||
from
|
||||
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource,
|
||||
Expr protocolSink, ConstructorCall cc, Expr e, string msg
|
||||
from Expr protocolSource, Expr protocolSink, ConstructorCall cc, Expr e, string msg
|
||||
where
|
||||
configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
|
||||
BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||
DataFlow::exprNode(protocolSink)) and
|
||||
cc.getArgument(0) = protocolSink and
|
||||
(
|
||||
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
|
||||
|
||||
@@ -12,18 +12,15 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.boostorg.asio.protocols
|
||||
|
||||
from
|
||||
BoostorgAsio::SslContextCallConfig config, Expr protocolSource, Expr protocolSink,
|
||||
ConstructorCall cc
|
||||
from Expr protocolSource, Expr protocolSink, ConstructorCall cc
|
||||
where
|
||||
config.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
|
||||
not exists(BoostorgAsio::SslContextCallTlsProtocolConfig tlsConfig |
|
||||
tlsConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink))
|
||||
) and
|
||||
BoostorgAsio::SslContextCallFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||
DataFlow::exprNode(protocolSink)) and
|
||||
not BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||
DataFlow::exprNode(protocolSink)) and
|
||||
cc.getArgument(0) = protocolSink and
|
||||
exists(BoostorgAsio::SslContextCallBannedProtocolConfig bannedConfig |
|
||||
bannedConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink))
|
||||
)
|
||||
BoostorgAsio::SslContextCallBannedProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||
DataFlow::exprNode(protocolSink))
|
||||
select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.",
|
||||
cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(),
|
||||
cc.getEnclosingFunction(), cc.getEnclosingFunction().toString()
|
||||
|
||||
@@ -70,7 +70,7 @@ predicate hasUpperBoundsCheck(Variable var) {
|
||||
)
|
||||
}
|
||||
|
||||
module TaintedPathConfiguration implements DataFlow::ConfigSig {
|
||||
module TaintedPathConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
@@ -90,7 +90,7 @@ module TaintedPathConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module TaintedPath = TaintTracking::Make<TaintedPathConfiguration>;
|
||||
module TaintedPath = TaintTracking::Make<TaintedPathConfig>;
|
||||
|
||||
from
|
||||
FileFunction fileFunction, Expr taintedArg, FlowSource taintSource,
|
||||
|
||||
@@ -97,7 +97,7 @@ predicate isBarrierImpl(DataFlow::Node node) {
|
||||
* given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
|
||||
* `ExecTaintConfiguration::isSink`.
|
||||
*/
|
||||
module ExecStateConfiguration implements DataFlow::ConfigSig {
|
||||
module ExecStateConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { any(ExecState state).getOutgoingNode() = source }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
||||
@@ -109,9 +109,9 @@ module ExecStateConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ExecState = TaintTracking::Make<ExecStateConfiguration>;
|
||||
module ExecState = TaintTracking::Make<ExecStateConfig>;
|
||||
|
||||
module ExecTaintConfiguration implements DataFlow::StateConfigSig {
|
||||
module ExecTaintConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = TState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
@@ -120,7 +120,7 @@ module ExecTaintConfiguration implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
ExecStateConfiguration::isSink(sink) and
|
||||
ExecStateConfig::isSink(sink) and
|
||||
state.(ExecState).isFeasibleForSink(sink)
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ module ExecTaintConfiguration implements DataFlow::StateConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ExecTaint = TaintTracking::MakeWithState<ExecTaintConfiguration>;
|
||||
module ExecTaint = TaintTracking::MakeWithState<ExecTaintConfig>;
|
||||
|
||||
from
|
||||
ExecTaint::PathNode sourceNode, ExecTaint::PathNode sinkNode, string taintCause, string callChain,
|
||||
|
||||
@@ -90,7 +90,7 @@ predicate missingGuard(VariableAccess va, string effect) {
|
||||
)
|
||||
}
|
||||
|
||||
module UncontrolledArithConfiguration implements DataFlow::ConfigSig {
|
||||
module UncontrolledArithConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
||||
rand.getFunctionOutput().isReturnValue() and
|
||||
@@ -122,7 +122,7 @@ module UncontrolledArithConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module UncontrolledArith = TaintTracking::Make<UncontrolledArithConfiguration>;
|
||||
module UncontrolledArith = TaintTracking::Make<UncontrolledArithConfig>;
|
||||
|
||||
/** Gets the expression that corresponds to `node`, if any. */
|
||||
Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] }
|
||||
|
||||
@@ -54,7 +54,7 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va
|
||||
|
||||
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
|
||||
|
||||
module TaintedAllocationSizeConfiguration implements DataFlow::ConfigSig {
|
||||
module TaintedAllocationSizeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { allocSink(_, sink) }
|
||||
@@ -95,7 +95,7 @@ module TaintedAllocationSizeConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module TaintedAllocationSize = TaintTracking::Make<TaintedAllocationSizeConfiguration>;
|
||||
module TaintedAllocationSize = TaintTracking::Make<TaintedAllocationSizeConfig>;
|
||||
|
||||
from
|
||||
Expr alloc, TaintedAllocationSize::PathNode source, TaintedAllocationSize::PathNode sink,
|
||||
|
||||
@@ -39,7 +39,7 @@ class SensitiveBufferWrite extends Expr instanceof BufferWrite::BufferWrite {
|
||||
* A taint flow configuration for flow from user input to a buffer write
|
||||
* into a sensitive expression.
|
||||
*/
|
||||
module ToBufferConfiguration implements DataFlow::ConfigSig {
|
||||
module ToBufferConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
@@ -49,7 +49,7 @@ module ToBufferConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||
}
|
||||
|
||||
module ToBufferFlow = TaintTracking::Make<ToBufferConfiguration>;
|
||||
module ToBufferFlow = TaintTracking::Make<ToBufferConfig>;
|
||||
|
||||
predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) {
|
||||
w.getASource() = sink.asIndirectExpr()
|
||||
|
||||
@@ -23,7 +23,7 @@ import FromSensitiveFlow::PathGraph
|
||||
/**
|
||||
* A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink.
|
||||
*/
|
||||
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
||||
@@ -33,7 +33,7 @@ module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfig>;
|
||||
|
||||
predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) {
|
||||
exists(Expr e |
|
||||
|
||||
@@ -234,7 +234,7 @@ predicate isSourceImpl(DataFlow::Node source) {
|
||||
* A taint flow configuration for flow from a sensitive expression to a network
|
||||
* operation.
|
||||
*/
|
||||
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) }
|
||||
@@ -250,12 +250,12 @@ module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfig>;
|
||||
|
||||
/**
|
||||
* A taint flow configuration for flow from a sensitive expression to an encryption operation.
|
||||
*/
|
||||
module ToEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||
module ToEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { FromSensitiveFlow::hasFlow(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
|
||||
@@ -271,12 +271,12 @@ module ToEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ToEncryptionFlow = TaintTracking::Make<ToEncryptionConfiguration>;
|
||||
module ToEncryptionFlow = TaintTracking::Make<ToEncryptionConfig>;
|
||||
|
||||
/**
|
||||
* A taint flow configuration for flow from an encryption operation to a network operation.
|
||||
*/
|
||||
module FromEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||
module FromEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSinkEncrypt(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::hasFlowTo(sink) }
|
||||
@@ -286,7 +286,7 @@ module FromEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module FromEncryptionFlow = TaintTracking::Make<FromEncryptionConfiguration>;
|
||||
module FromEncryptionFlow = TaintTracking::Make<FromEncryptionConfig>;
|
||||
|
||||
from
|
||||
FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
||||
|
||||
@@ -100,7 +100,7 @@ predicate isSinkImpl(DataFlow::Node sink, SqliteFunctionCall c, Type t) {
|
||||
/**
|
||||
* A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
|
||||
*/
|
||||
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
isSourceImpl(source, _) and not sqlite_encryption_used()
|
||||
}
|
||||
@@ -125,7 +125,7 @@ module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfig>;
|
||||
|
||||
from
|
||||
SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
||||
|
||||
@@ -28,7 +28,7 @@ int getMinimumKeyStrength(string func, int paramIndex) {
|
||||
result = 2048
|
||||
}
|
||||
|
||||
module KeyStrengthFlowConfiguration implements DataFlow::ConfigSig {
|
||||
module KeyStrengthFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
exists(int bits |
|
||||
node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and
|
||||
@@ -46,7 +46,7 @@ module KeyStrengthFlowConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module KeyStrengthFlow = DataFlow::Make<KeyStrengthFlowConfiguration>;
|
||||
module KeyStrengthFlow = DataFlow::Make<KeyStrengthFlowConfig>;
|
||||
|
||||
from
|
||||
KeyStrengthFlow::PathNode source, KeyStrengthFlow::PathNode sink, FunctionCall fc, int param,
|
||||
|
||||
@@ -54,7 +54,7 @@ class CreateProcessFunctionCall extends FunctionCall {
|
||||
/**
|
||||
* Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument
|
||||
*/
|
||||
module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
|
||||
module NullAppNameCreateProcessFunctionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
@@ -64,13 +64,12 @@ module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::Config
|
||||
}
|
||||
}
|
||||
|
||||
module NullAppNameCreateProcessFunction =
|
||||
DataFlow::Make<NullAppNameCreateProcessFunctionConfiguration>;
|
||||
module NullAppNameCreateProcessFunction = DataFlow::Make<NullAppNameCreateProcessFunctionConfig>;
|
||||
|
||||
/**
|
||||
* Dataflow that detects a call to CreateProcess with an unquoted commandLine argument
|
||||
*/
|
||||
module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
|
||||
module QuotedCommandInCreateProcessFunctionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(string s |
|
||||
s = source.asExpr().getValue().toString() and
|
||||
@@ -86,7 +85,7 @@ module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::Co
|
||||
}
|
||||
|
||||
module QuotedCommandInCreateProcessFunction =
|
||||
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfiguration>;
|
||||
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfig>;
|
||||
|
||||
bindingset[s]
|
||||
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import ExposedSystemData::PathGraph
|
||||
import SystemData
|
||||
|
||||
module ExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
||||
module ExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
@@ -30,7 +30,7 @@ module ExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ExposedSystemData = TaintTracking::Make<ExposedSystemDataConfiguration>;
|
||||
module ExposedSystemData = TaintTracking::Make<ExposedSystemDataConfig>;
|
||||
|
||||
from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink
|
||||
where
|
||||
|
||||
@@ -31,7 +31,7 @@ import semmle.code.cpp.security.OutputWrite
|
||||
import PotentiallyExposedSystemData::PathGraph
|
||||
import SystemData
|
||||
|
||||
module PotentiallyExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
||||
module PotentiallyExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
||||
}
|
||||
@@ -51,8 +51,7 @@ module PotentiallyExposedSystemDataConfiguration implements DataFlow::ConfigSig
|
||||
}
|
||||
}
|
||||
|
||||
module PotentiallyExposedSystemData =
|
||||
TaintTracking::Make<PotentiallyExposedSystemDataConfiguration>;
|
||||
module PotentiallyExposedSystemData = TaintTracking::Make<PotentiallyExposedSystemDataConfig>;
|
||||
|
||||
from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink
|
||||
where PotentiallyExposedSystemData::hasFlowPath(source, sink)
|
||||
|
||||
@@ -19,7 +19,7 @@ import XxeFlow::PathGraph
|
||||
/**
|
||||
* A configuration for tracking XML objects and their states.
|
||||
*/
|
||||
module XxeConfiguration implements DataFlow::StateConfigSig {
|
||||
module XxeConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = TXxeFlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node node, FlowState flowstate) {
|
||||
@@ -45,7 +45,7 @@ module XxeConfiguration implements DataFlow::StateConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module XxeFlow = DataFlow::MakeWithState<XxeConfiguration>;
|
||||
module XxeFlow = DataFlow::MakeWithState<XxeConfig>;
|
||||
|
||||
from XxeFlow::PathNode source, XxeFlow::PathNode sink
|
||||
where XxeFlow::hasFlowPath(source, sink)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `NetworkToBufferSizeConfiguration` and `UntrustedDataToExternalApiConfig` dataflow configurations have been deprecated. Please use `NetworkToBufferSizeFlow` and `UntrustedDataToExternalApiFlow`.
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
## 0.5.5
|
||||
|
||||
### Deprecated Queries
|
||||
|
||||
* The `NetworkToBufferSizeConfiguration` and `UntrustedDataToExternalApiConfig` dataflow configurations have been deprecated. Please use `NetworkToBufferSizeFlow` and `UntrustedDataToExternalApiFlow`.
|
||||
* The `LeapYearCheckConfiguration`, `FiletimeYearArithmeticOperationCheckConfiguration`, and `PossibleYearArithmeticOperationCheckConfiguration` dataflow configurations have been deprecated. Please use `LeapYearCheckFlow`, `FiletimeYearArithmeticOperationCheckFlow` and `PossibleYearArithmeticOperationCheckFlow`.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.5.4
|
||||
lastReleaseVersion: 0.5.5
|
||||
|
||||
@@ -35,7 +35,7 @@ private predicate isCommandSubstitutionDisabled(FunctionCall fc) {
|
||||
/**
|
||||
* A configuration to track user-supplied data to the `wordexp` function.
|
||||
*/
|
||||
module WordexpTaintConfiguration implements DataFlow::ConfigSig {
|
||||
module WordexpTaintConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
@@ -50,7 +50,7 @@ module WordexpTaintConfiguration implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module WordexpTaint = TaintTracking::Make<WordexpTaintConfiguration>;
|
||||
module WordexpTaint = TaintTracking::Make<WordexpTaintConfig>;
|
||||
|
||||
from WordexpTaint::PathNode sourceNode, WordexpTaint::PathNode sinkNode
|
||||
where WordexpTaint::hasFlowPath(sourceNode, sinkNode)
|
||||
|
||||
@@ -15,8 +15,7 @@ import experimental.semmle.code.cpp.semantic.SemanticBound
|
||||
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow2
|
||||
import DataFlow2::PathGraph
|
||||
import PointerArithmeticToDerefFlow::PathGraph
|
||||
|
||||
pragma[nomagic]
|
||||
Instruction getABoundIn(SemBound b, IRFunction func) {
|
||||
@@ -36,16 +35,16 @@ predicate bounded(Instruction i, Instruction b, int delta) {
|
||||
)
|
||||
}
|
||||
|
||||
class FieldAddressToPointerArithmeticConf extends DataFlow::Configuration {
|
||||
FieldAddressToPointerArithmeticConf() { this = "FieldAddressToPointerArithmeticConf" }
|
||||
module FieldAddressToPointerArithmeticConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(PointerAddInstruction pai | pai.getLeft() = sink.asInstruction())
|
||||
}
|
||||
}
|
||||
|
||||
module FieldAddressToPointerArithmeticFlow = DataFlow::Make<FieldAddressToPointerArithmeticConfig>;
|
||||
|
||||
predicate isFieldAddressSource(Field f, DataFlow::Node source) {
|
||||
source.asInstruction().(FieldAddressInstruction).getField() = f
|
||||
}
|
||||
@@ -70,11 +69,8 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
|
||||
}
|
||||
|
||||
predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int delta) {
|
||||
exists(
|
||||
int size, int bound, FieldAddressToPointerArithmeticConf conf, DataFlow::Node source,
|
||||
DataFlow::InstructionNode sink
|
||||
|
|
||||
conf.hasFlow(source, sink) and
|
||||
exists(int size, int bound, DataFlow::Node source, DataFlow::InstructionNode sink |
|
||||
FieldAddressToPointerArithmeticFlow::hasFlow(source, sink) and
|
||||
isFieldAddressSource(f, source) and
|
||||
pai.getLeft() = sink.asInstruction() and
|
||||
f.getUnspecifiedType().(ArrayType).getArraySize() = size and
|
||||
@@ -86,21 +82,21 @@ predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int d
|
||||
)
|
||||
}
|
||||
|
||||
class PointerArithmeticToDerefConf extends DataFlow2::Configuration {
|
||||
PointerArithmeticToDerefConf() { this = "PointerArithmeticToDerefConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
isConstantSizeOverflowSource(_, source.asInstruction(), _)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||
}
|
||||
|
||||
module PointerArithmeticToDerefFlow = DataFlow::Make<PointerArithmeticToDerefConfig>;
|
||||
|
||||
from
|
||||
Field f, DataFlow2::PathNode source, DataFlow2::PathNode sink, Instruction deref,
|
||||
PointerArithmeticToDerefConf conf, string operation, int delta
|
||||
Field f, PointerArithmeticToDerefFlow::PathNode source,
|
||||
PointerArithmeticToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
PointerArithmeticToDerefFlow::hasFlowPath(source, sink) and
|
||||
isInvalidPointerDerefSink(sink.getNode(), deref, operation) and
|
||||
isConstantSizeOverflowSource(f, source.getNode().asInstruction(), delta)
|
||||
select source, source, sink,
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
import cpp
|
||||
import experimental.semmle.code.cpp.dataflow.ProductFlow
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow3
|
||||
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis
|
||||
import experimental.semmle.code.cpp.semantic.SemanticBound
|
||||
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
|
||||
@@ -204,14 +203,14 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
|
||||
* A configuration to track flow from a pointer-arithmetic operation found
|
||||
* by `AllocToInvalidPointerConf` to a dereference of the pointer.
|
||||
*/
|
||||
class InvalidPointerToDerefConf extends DataFlow3::Configuration {
|
||||
InvalidPointerToDerefConf() { this = "InvalidPointerToDerefConf" }
|
||||
module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||
}
|
||||
|
||||
module InvalidPointerToDerefFlow = DataFlow::Make<InvalidPointerToDerefConfig>;
|
||||
|
||||
/**
|
||||
* Holds if `pai` is a pointer-arithmetic operation and `source` is a dataflow node with a
|
||||
* pointer-value that is non-strictly upper bounded by `pai + delta`.
|
||||
@@ -236,13 +235,13 @@ newtype TMergedPathNode =
|
||||
// The path nodes computed by the first projection of `AllocToInvalidPointerConf`
|
||||
TPathNode1(DataFlow::PathNode p) or
|
||||
// The path nodes computed by `InvalidPointerToDerefConf`
|
||||
TPathNode3(DataFlow3::PathNode p) or
|
||||
TPathNode3(InvalidPointerToDerefFlow::PathNode p) or
|
||||
// The read/write that uses the invalid pointer identified by `InvalidPointerToDerefConf`.
|
||||
// This one is needed because the sink identified by `InvalidPointerToDerefConf` is the
|
||||
// pointer, but we want to raise an alert at the dereference.
|
||||
TPathNodeSink(Instruction i) {
|
||||
exists(DataFlow::Node n |
|
||||
any(InvalidPointerToDerefConf conf).hasFlow(_, n) and
|
||||
InvalidPointerToDerefFlow::hasFlow(_, n) and
|
||||
isInvalidPointerDerefSink(n, i, _)
|
||||
)
|
||||
}
|
||||
@@ -252,7 +251,7 @@ class MergedPathNode extends TMergedPathNode {
|
||||
|
||||
final DataFlow::PathNode asPathNode1() { this = TPathNode1(result) }
|
||||
|
||||
final DataFlow3::PathNode asPathNode3() { this = TPathNode3(result) }
|
||||
final InvalidPointerToDerefFlow::PathNode asPathNode3() { this = TPathNode3(result) }
|
||||
|
||||
final Instruction asSinkNode() { this = TPathNodeSink(result) }
|
||||
|
||||
@@ -280,7 +279,7 @@ class PathNode1 extends MergedPathNode, TPathNode1 {
|
||||
|
||||
class PathNode3 extends MergedPathNode, TPathNode3 {
|
||||
override string toString() {
|
||||
exists(DataFlow3::PathNode p |
|
||||
exists(InvalidPointerToDerefFlow::PathNode p |
|
||||
this = TPathNode3(p) and
|
||||
result = p.toString()
|
||||
)
|
||||
@@ -324,7 +323,9 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) {
|
||||
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
|
||||
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.
|
||||
*/
|
||||
predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataFlow3::PathNode p2) {
|
||||
predicate joinOn1(
|
||||
PointerArithmeticInstruction pai, DataFlow::PathNode p1, InvalidPointerToDerefFlow::PathNode p2
|
||||
) {
|
||||
isSinkImpl(pai, p1.getNode(), _, _) and
|
||||
invalidPointerToDerefSource(pai, p2.getNode(), _)
|
||||
}
|
||||
@@ -334,28 +335,29 @@ predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataF
|
||||
* that dereferences `p1`. The string `operation` describes whether the `i` is
|
||||
* a `StoreInstruction` or `LoadInstruction`.
|
||||
*/
|
||||
predicate joinOn2(DataFlow3::PathNode p1, Instruction i, string operation) {
|
||||
predicate joinOn2(InvalidPointerToDerefFlow::PathNode p1, Instruction i, string operation) {
|
||||
isInvalidPointerDerefSink(p1.getNode(), i, operation)
|
||||
}
|
||||
|
||||
predicate hasFlowPath(
|
||||
MergedPathNode source1, MergedPathNode sink, DataFlow3::PathNode source3,
|
||||
MergedPathNode source1, MergedPathNode sink, InvalidPointerToDerefFlow::PathNode source3,
|
||||
PointerArithmeticInstruction pai, string operation
|
||||
) {
|
||||
exists(
|
||||
AllocToInvalidPointerConf conf1, InvalidPointerToDerefConf conf2, DataFlow3::PathNode sink3,
|
||||
AllocToInvalidPointerConf conf1, InvalidPointerToDerefFlow::PathNode sink3,
|
||||
DataFlow::PathNode sink1
|
||||
|
|
||||
conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and
|
||||
joinOn1(pai, sink1, source3) and
|
||||
conf2.hasFlowPath(source3, sink3) and
|
||||
InvalidPointerToDerefFlow::hasFlowPath(source3, sink3) and
|
||||
joinOn2(sink3, sink.asSinkNode(), operation)
|
||||
)
|
||||
}
|
||||
|
||||
from
|
||||
MergedPathNode source, MergedPathNode sink, int k, string kstr, DataFlow3::PathNode source3,
|
||||
PointerArithmeticInstruction pai, string operation, Expr offset, DataFlow::Node n
|
||||
MergedPathNode source, MergedPathNode sink, int k, string kstr,
|
||||
InvalidPointerToDerefFlow::PathNode source3, PointerArithmeticInstruction pai, string operation,
|
||||
Expr offset, DataFlow::Node n
|
||||
where
|
||||
hasFlowPath(source, sink, source3, pai, operation) and
|
||||
invalidPointerToDerefSource(pai, source3.getNode(), k) and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.5.5-dev
|
||||
version: 0.5.6-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
|
||||
LiteralToGethostbynameConfiguration() { this = "LiteralToGethostbynameConfiguration" }
|
||||
module LiteralToGethostbynameConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asIndirectExpr(1) instanceof StringLiteral }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asIndirectExpr(1) instanceof StringLiteral
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc |
|
||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||
fc.getTarget().hasName("gethostbyname")
|
||||
@@ -16,11 +12,11 @@ class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg, DataFlow::Node source,
|
||||
DataFlow::Node sink
|
||||
module LiteralToGethostbynameFlow = DataFlow::Make<LiteralToGethostbynameConfig>;
|
||||
|
||||
from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
||||
where
|
||||
source.asIndirectExpr(1) = sl and
|
||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||
cfg.hasFlow(source, sink)
|
||||
LiteralToGethostbynameFlow::hasFlow(source, sink)
|
||||
select sl, fc
|
||||
|
||||
@@ -5,12 +5,10 @@ class GetenvSource extends DataFlow::Node {
|
||||
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
|
||||
}
|
||||
|
||||
class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
|
||||
GetenvToGethostbynameConfiguration() { this = "GetenvToGethostbynameConfiguration" }
|
||||
module GetenvToGethostbynameConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc |
|
||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||
fc.getTarget().hasName("gethostbyname")
|
||||
@@ -18,11 +16,11 @@ class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
Expr getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg, DataFlow::Node source,
|
||||
DataFlow::Node sink
|
||||
module GetenvToGethostbynameFlow = DataFlow::Make<GetenvToGethostbynameConfig>;
|
||||
|
||||
from Expr getenv, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
||||
where
|
||||
source.asIndirectExpr(1) = getenv and
|
||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||
cfg.hasFlow(source, sink)
|
||||
GetenvToGethostbynameFlow::hasFlow(source, sink)
|
||||
select getenv, fc
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
|
||||
EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module EnvironmentToFileConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Function getenv |
|
||||
source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and
|
||||
getenv.hasGlobalName("getenv")
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc |
|
||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||
fc.getTarget().hasGlobalName("fopen")
|
||||
@@ -19,11 +17,11 @@ class EnvironmentToFileConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
Expr getenv, Expr fopen, EnvironmentToFileConfiguration config, DataFlow::Node source,
|
||||
DataFlow::Node sink
|
||||
module EnvironmentToFileFlow = DataFlow::Make<EnvironmentToFileConfig>;
|
||||
|
||||
from Expr getenv, Expr fopen, DataFlow::Node source, DataFlow::Node sink
|
||||
where
|
||||
source.asIndirectExpr(1) = getenv and
|
||||
sink.asIndirectExpr(1) = fopen and
|
||||
config.hasFlow(source, sink)
|
||||
EnvironmentToFileFlow::hasFlow(source, sink)
|
||||
select fopen, "This 'fopen' uses data from $@.", getenv, "call to 'getenv'"
|
||||
|
||||
@@ -2,18 +2,16 @@ import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
|
||||
class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
|
||||
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset())
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(Loop loop, LoopCounter lc |
|
||||
loop = lc.getALoop() and
|
||||
loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr()
|
||||
@@ -22,7 +20,7 @@ class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(GuardCondition gc, Variable v |
|
||||
gc.getAChild*() = v.getAnAccess() and
|
||||
node.asExpr() = v.getAnAccess() and
|
||||
@@ -32,7 +30,9 @@ class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::Node ntohl, DataFlow::Node offset, NetworkToBufferSizeConfiguration conf
|
||||
where conf.hasFlow(ntohl, offset)
|
||||
module NetworkToBufferSizeFlow = TaintTracking::Make<NetworkToBufferSizeConfig>;
|
||||
|
||||
from DataFlow::Node ntohl, DataFlow::Node offset
|
||||
where NetworkToBufferSizeFlow::hasFlow(ntohl, offset)
|
||||
select offset, "This array offset may be influenced by $@.", ntohl,
|
||||
"converted data from the network"
|
||||
|
||||
@@ -4,12 +4,12 @@ import experimental.semmle.code.cpp.semantic.Semantic
|
||||
import experimental.semmle.code.cpp.semantic.analysis.RangeUtils
|
||||
import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
|
||||
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific
|
||||
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis
|
||||
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisImpl
|
||||
import semmle.code.cpp.ir.IR as IR
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
module ModulusAnalysisInstantiated =
|
||||
ModulusAnalysis<FloatDelta, Bounds, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
ModulusAnalysis<FloatDelta, ConstantBounds, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
|
||||
class ModulusAnalysisTest extends InlineExpectationsTest {
|
||||
ModulusAnalysisTest() { this = "ModulusAnalysisTest" }
|
||||
|
||||
@@ -56,3 +56,8 @@ void f3() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int unevaluated_test() {
|
||||
char buffer[100];
|
||||
return sizeof(buffer) / sizeof(buffer[101]); // GOOD
|
||||
}
|
||||
@@ -603,6 +603,11 @@ void test22(bool b, const char* source) {
|
||||
memcpy(dest, source, n); // GOOD
|
||||
}
|
||||
|
||||
int test23() {
|
||||
char buffer[100];
|
||||
return sizeof(buffer) / sizeof(buffer[101]); // GOOD
|
||||
}
|
||||
|
||||
int tests_main(int argc, char *argv[])
|
||||
{
|
||||
long long arr17[19];
|
||||
@@ -627,6 +632,7 @@ int tests_main(int argc, char *argv[])
|
||||
test20();
|
||||
test21(argc == 0);
|
||||
test22(argc == 0, argv[0]);
|
||||
test23();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.4.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.4.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.4.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.4.4
|
||||
lastReleaseVersion: 1.4.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.4.5-dev
|
||||
version: 1.4.6-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.4.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.4.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.4.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.4.4
|
||||
lastReleaseVersion: 1.4.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.4.5-dev
|
||||
version: 1.4.6-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
## 0.5.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getAssertionIndex`, and `getAssertedParameter` predicates from the `AssertMethod` class.
|
||||
* Deleted the deprecated `OverridableMethod` and `OverridableAccessor` classes.
|
||||
* The `unsafe` predicate for `Modifiable` has been extended to cover delegate return types and identify pointer-like types at any nest level. This is relevant for `unsafe` declarations extracted from assemblies.
|
||||
|
||||
## 0.5.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `unsafe` predicate for `Modifiable` has been extended to cover delegate return types and identify pointer like types at any nest level. This is relevant for `unsafe` declarations extracted from assemblies.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getAssertionIndex`, and `getAssertedParameter` predicates from the `AssertMethod` class.
|
||||
* Deleted the deprecated `OverridableMethod` and `OverridableAccessor` classes.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
21
csharp/ql/lib/change-notes/released/0.5.5.md
Normal file
21
csharp/ql/lib/change-notes/released/0.5.5.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## 0.5.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The main data flow and taint tracking APIs have been changed. The old APIs
|
||||
remain in place for now and translate to the new through a
|
||||
backwards-compatible wrapper. If multiple configurations are in scope
|
||||
simultaneously, then this may affect results slightly. The new API is quite
|
||||
similar to the old, but makes use of a configuration module instead of a
|
||||
configuration class.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
|
||||
* Deleted the deprecated `getAssertionIndex`, and `getAssertedParameter` predicates from the `AssertMethod` class.
|
||||
* Deleted the deprecated `OverridableMethod` and `OverridableAccessor` classes.
|
||||
* The `unsafe` predicate for `Modifiable` has been extended to cover delegate return types and identify pointer-like types at any nest level. This is relevant for `unsafe` declarations extracted from assemblies.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user