mirror of
https://github.com/github/codeql.git
synced 2026-07-05 11:35:30 +02:00
Compare commits
270 Commits
codeql-cli
...
igfoo/expa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c354b544e4 | ||
|
|
288e9206c7 | ||
|
|
834511bd78 | ||
|
|
b102ddac30 | ||
|
|
92a31608a2 | ||
|
|
574b2201cb | ||
|
|
5260d9815a | ||
|
|
caa25f78d9 | ||
|
|
98dc73c6dd | ||
|
|
6d665da4dc | ||
|
|
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 | ||
|
|
17c9ba9872 | ||
|
|
ed15cce31f | ||
|
|
8c738b77a3 | ||
|
|
b042c60ca3 | ||
|
|
39726a54ec | ||
|
|
72e97918e9 | ||
|
|
bbe95367d6 | ||
|
|
a19579d21b | ||
|
|
2968c12e12 | ||
|
|
9997326804 | ||
|
|
5f438e433d | ||
|
|
1d2f1b6ae6 | ||
|
|
83b0d073f0 | ||
|
|
1c661fd3ac | ||
|
|
e0e3a1d621 | ||
|
|
9b7a20f4ad | ||
|
|
84fd5f7ee0 | ||
|
|
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 | ||
|
|
208ae192e4 | ||
|
|
86b61d712c | ||
|
|
d537f86324 | ||
|
|
9d05d94f49 | ||
|
|
e84b08409c | ||
|
|
ac85b6e74f | ||
|
|
0cadf4d94a | ||
|
|
c12a85b07b | ||
|
|
b8fb4b9b0f | ||
|
|
76ed56d2b6 | ||
|
|
ee6288173f | ||
|
|
60f313863a | ||
|
|
7c15527300 | ||
|
|
940e492766 | ||
|
|
1aecc64327 | ||
|
|
282b5d4836 | ||
|
|
f2dff092dc | ||
|
|
d2647850d2 | ||
|
|
d146d816a9 | ||
|
|
e69e90db4a | ||
|
|
75746cbacc | ||
|
|
ee01e9ab35 | ||
|
|
2c63dbad67 | ||
|
|
f1094cd3d6 | ||
|
|
f3c7aed1f9 | ||
|
|
e00c41c6e2 | ||
|
|
a63739915d | ||
|
|
2c1c41d8a3 | ||
|
|
d47659b48e | ||
|
|
37e42bb05b | ||
|
|
ebab6ecc30 | ||
|
|
880f948763 | ||
|
|
406d02253d | ||
|
|
3a04e42ae0 | ||
|
|
3e9924fcd2 | ||
|
|
647bd44666 | ||
|
|
f9bb0df6a2 | ||
|
|
13c2ef8c20 | ||
|
|
a229f7a832 | ||
|
|
f35fb13723 | ||
|
|
9d3863eccc | ||
|
|
bce1f29a7e | ||
|
|
86a06bde72 | ||
|
|
e907d685f4 | ||
|
|
ae10e6e08f | ||
|
|
66b03dbd1d | ||
|
|
e7079b35bc | ||
|
|
880632f536 | ||
|
|
3fea9e4d0b | ||
|
|
2e86bbd6cd | ||
|
|
fe4d27e8cc | ||
|
|
a9e5b34ad6 | ||
|
|
f718d78a9a | ||
|
|
d02a50a504 | ||
|
|
b208988675 | ||
|
|
54ec047433 | ||
|
|
1d0b3d4112 | ||
|
|
3ff60e076c | ||
|
|
8bc8342c7c | ||
|
|
be8f04a997 | ||
|
|
48f889b055 | ||
|
|
e999d33332 | ||
|
|
45fdf69461 | ||
|
|
5bc606753e | ||
|
|
3b4980ba2f | ||
|
|
c5a1905302 | ||
|
|
341590f9ad | ||
|
|
e0c852c0b8 | ||
|
|
cc3efcd35e | ||
|
|
2133d1a5ab | ||
|
|
a72436f6f1 | ||
|
|
f811436cff | ||
|
|
623e39031c | ||
|
|
fe1cc405eb | ||
|
|
44f239f4a4 | ||
|
|
cbc0ba6ac6 | ||
|
|
7455c27086 | ||
|
|
6aa9726223 | ||
|
|
db9e305a56 | ||
|
|
267c341965 | ||
|
|
31667b4478 | ||
|
|
720cf0ab7a | ||
|
|
3db95f3ac9 | ||
|
|
d54abddab1 | ||
|
|
2e7ad99059 | ||
|
|
452b9d11db | ||
|
|
cad5cd4037 | ||
|
|
db83fe6f42 | ||
|
|
8cc2686a2f | ||
|
|
1b85e8b706 | ||
|
|
ccf7d9beec | ||
|
|
984a589954 | ||
|
|
4307889b1f | ||
|
|
b4b7507fe4 | ||
|
|
8b99e8af88 | ||
|
|
25a6d496d9 | ||
|
|
41b2273dee | ||
|
|
e2479940d2 | ||
|
|
df45ba0476 | ||
|
|
8398ee43b3 | ||
|
|
a964f536e8 | ||
|
|
278f90e5fa | ||
|
|
cfe2a76431 | ||
|
|
3734a544bc | ||
|
|
e80ff4efba | ||
|
|
071517c74b | ||
|
|
bfe42a656c | ||
|
|
384e7c7a80 | ||
|
|
e65d7224db | ||
|
|
eada3b91df | ||
|
|
c82b4638c6 | ||
|
|
a1fab31bfc | ||
|
|
d4e3f7f738 | ||
|
|
bbb43a53e5 | ||
|
|
b941d54f1f | ||
|
|
50fac3060c | ||
|
|
5a9a90d00b | ||
|
|
d9d63bbdc6 | ||
|
|
3e1808d92e | ||
|
|
cd49175fae | ||
|
|
cbb031ee14 | ||
|
|
6cd4cd332d | ||
|
|
31336b09c4 | ||
|
|
36b33765a5 | ||
|
|
b0797a2559 | ||
|
|
44997d6b5f | ||
|
|
61fe3704c0 | ||
|
|
dd1f7cc1d2 | ||
|
|
ff50513441 | ||
|
|
17f7ba2a8f | ||
|
|
d2bd70dc33 | ||
|
|
c2e8206090 | ||
|
|
962465f77a | ||
|
|
a4c42aa14b |
4
.github/workflows/go-tests-other-os.yml
vendored
4
.github/workflows/go-tests-other-os.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.20
|
- name: Set up Go 1.20
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.20.0
|
go-version: 1.20.0
|
||||||
id: go
|
id: go
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
runs-on: windows-latest-xl
|
runs-on: windows-latest-xl
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.20
|
- name: Set up Go 1.20
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.20.0
|
go-version: 1.20.0
|
||||||
id: go
|
id: go
|
||||||
|
|||||||
2
.github/workflows/go-tests.yml
vendored
2
.github/workflows/go-tests.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest-xl
|
runs-on: ubuntu-latest-xl
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.20
|
- name: Set up Go 1.20
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.20.0
|
go-version: 1.20.0
|
||||||
id: go
|
id: go
|
||||||
|
|||||||
@@ -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/unaliased_ssa/internal/IRBlockImports.qll",
|
||||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_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": [
|
"C++ IR IRFunctionImports": [
|
||||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRFunctionImports.qll",
|
"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",
|
"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
|
## 0.5.4
|
||||||
|
|
||||||
No user-facing changes.
|
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 SemanticExpr
|
||||||
private import SemanticExprSpecific::SemanticExprConfig as Specific
|
private import SemanticExprSpecific::SemanticExprConfig as Specific
|
||||||
private import SemanticSSA
|
private import SemanticSSA
|
||||||
|
private import SemanticLocation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A valid base for an expression bound.
|
* A valid base for an expression bound.
|
||||||
@@ -14,6 +15,8 @@ private import SemanticSSA
|
|||||||
class SemBound instanceof Specific::Bound {
|
class SemBound instanceof Specific::Bound {
|
||||||
final string toString() { result = super.toString() }
|
final string toString() { result = super.toString() }
|
||||||
|
|
||||||
|
final SemLocation getLocation() { result = super.getLocation() }
|
||||||
|
|
||||||
final SemExpr getExpr(int delta) { result = Specific::getBoundExpr(this, delta) }
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
import RangeAnalysisImpl
|
||||||
private import RangeAnalysisSpecific
|
import experimental.semmle.code.cpp.semantic.SemanticBound
|
||||||
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
|
|
||||||
|
|||||||
@@ -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.SemanticType
|
||||||
import experimental.semmle.code.cpp.semantic.SemanticOpcode
|
import experimental.semmle.code.cpp.semantic.SemanticOpcode
|
||||||
private import ConstantAnalysis
|
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.
|
* 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> {
|
signature module BoundSig<DeltaSig D> {
|
||||||
class SemBound {
|
class SemBound {
|
||||||
|
string toString();
|
||||||
|
|
||||||
|
SemLocation getLocation();
|
||||||
|
|
||||||
SemExpr getExpr(D::Delta delta);
|
SemExpr getExpr(D::Delta delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 0.5.5-dev
|
version: 0.6.1-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -418,6 +418,10 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate sourceCallCtx(CallContext cc) {
|
||||||
|
if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny
|
||||||
|
}
|
||||||
|
|
||||||
private predicate hasSinkCallCtx() {
|
private predicate hasSinkCallCtx() {
|
||||||
exists(FlowFeature feature | feature = Config::getAFeature() |
|
exists(FlowFeature feature | feature = Config::getAFeature() |
|
||||||
feature instanceof FeatureHasSinkCallContext or
|
feature instanceof FeatureHasSinkCallContext or
|
||||||
@@ -1141,19 +1145,13 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
import Param
|
import Param
|
||||||
|
|
||||||
/* Begin: Stage logic. */
|
/* 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]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallApa(
|
private predicate flowIntoCallApa(
|
||||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
||||||
) {
|
) {
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
||||||
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) 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]
|
pragma[nomagic]
|
||||||
@@ -1163,7 +1161,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
||||||
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) 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]
|
pragma[nomagic]
|
||||||
@@ -1691,16 +1689,6 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) }
|
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 fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) }
|
||||||
|
|
||||||
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
||||||
@@ -1974,7 +1962,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
Stage2::revFlow(node2) and
|
Stage2::revFlow(node2) and
|
||||||
Stage2::revFlowAlias(node1)
|
Stage2::revFlow(node1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -1983,7 +1971,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
||||||
Stage2::revFlow(node2) and
|
Stage2::revFlow(node2) and
|
||||||
Stage2::revFlowAlias(node1)
|
Stage2::revFlow(node1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private module LocalFlowBigStep {
|
private module LocalFlowBigStep {
|
||||||
@@ -2065,11 +2053,11 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
additionalLocalFlowStepNodeCand1(node1, node2) and
|
additionalLocalFlowStepNodeCand1(node1, node2) and
|
||||||
state1 = state2 and
|
state1 = state2 and
|
||||||
Stage2::revFlow(node1, pragma[only_bind_into](state1), false) 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
|
or
|
||||||
additionalLocalStateStep(node1, state1, node2, state2) and
|
additionalLocalStateStep(node1, state1, node2, state2) and
|
||||||
Stage2::revFlow(node1, state1, false) and
|
Stage2::revFlow(node1, state1, false) and
|
||||||
Stage2::revFlowAlias(node2, state2, false)
|
Stage2::revFlow(node2, state2, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2262,7 +2250,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
||||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) 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)
|
exists(lcc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2273,7 +2261,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2284,7 +2272,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2586,7 +2574,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
||||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) 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]
|
pragma[nomagic]
|
||||||
@@ -2596,7 +2584,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2607,7 +2595,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2804,11 +2792,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
// A PathNode is introduced by a source ...
|
// A PathNode is introduced by a source ...
|
||||||
Stage5::revFlow(node, state) and
|
Stage5::revFlow(node, state) and
|
||||||
sourceNode(node, state) and
|
sourceNode(node, state) and
|
||||||
(
|
sourceCallCtx(cc) and
|
||||||
if hasSourceCallCtx()
|
|
||||||
then cc instanceof CallContextSomeCall
|
|
||||||
else cc instanceof CallContextAny
|
|
||||||
) and
|
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(node.getDataFlowType())
|
ap = TAccessPathNil(node.getDataFlowType())
|
||||||
or
|
or
|
||||||
@@ -3214,11 +3198,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
|
|
||||||
override predicate isSource() {
|
override predicate isSource() {
|
||||||
sourceNode(node, state) and
|
sourceNode(node, state) and
|
||||||
(
|
sourceCallCtx(cc) and
|
||||||
if hasSourceCallCtx()
|
|
||||||
then cc instanceof CallContextSomeCall
|
|
||||||
else cc instanceof CallContextAny
|
|
||||||
) and
|
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(node.getDataFlowType())
|
ap = TAccessPathNil(node.getDataFlowType())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,6 +418,10 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate sourceCallCtx(CallContext cc) {
|
||||||
|
if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny
|
||||||
|
}
|
||||||
|
|
||||||
private predicate hasSinkCallCtx() {
|
private predicate hasSinkCallCtx() {
|
||||||
exists(FlowFeature feature | feature = Config::getAFeature() |
|
exists(FlowFeature feature | feature = Config::getAFeature() |
|
||||||
feature instanceof FeatureHasSinkCallContext or
|
feature instanceof FeatureHasSinkCallContext or
|
||||||
@@ -1141,19 +1145,13 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
import Param
|
import Param
|
||||||
|
|
||||||
/* Begin: Stage logic. */
|
/* 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]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallApa(
|
private predicate flowIntoCallApa(
|
||||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
||||||
) {
|
) {
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
||||||
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) 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]
|
pragma[nomagic]
|
||||||
@@ -1163,7 +1161,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
||||||
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) 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]
|
pragma[nomagic]
|
||||||
@@ -1691,16 +1689,6 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) }
|
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 fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) }
|
||||||
|
|
||||||
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) }
|
||||||
@@ -1974,7 +1962,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
Stage2::revFlow(node2) and
|
Stage2::revFlow(node2) and
|
||||||
Stage2::revFlowAlias(node1)
|
Stage2::revFlow(node1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -1983,7 +1971,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and
|
||||||
Stage2::revFlow(node2) and
|
Stage2::revFlow(node2) and
|
||||||
Stage2::revFlowAlias(node1)
|
Stage2::revFlow(node1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private module LocalFlowBigStep {
|
private module LocalFlowBigStep {
|
||||||
@@ -2065,11 +2053,11 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
additionalLocalFlowStepNodeCand1(node1, node2) and
|
additionalLocalFlowStepNodeCand1(node1, node2) and
|
||||||
state1 = state2 and
|
state1 = state2 and
|
||||||
Stage2::revFlow(node1, pragma[only_bind_into](state1), false) 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
|
or
|
||||||
additionalLocalStateStep(node1, state1, node2, state2) and
|
additionalLocalStateStep(node1, state1, node2, state2) and
|
||||||
Stage2::revFlow(node1, state1, false) and
|
Stage2::revFlow(node1, state1, false) and
|
||||||
Stage2::revFlowAlias(node2, state2, false)
|
Stage2::revFlow(node2, state2, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2262,7 +2250,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and
|
||||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) 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)
|
exists(lcc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2273,7 +2261,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2284,7 +2272,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2586,7 +2574,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
) {
|
) {
|
||||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and
|
||||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) 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]
|
pragma[nomagic]
|
||||||
@@ -2596,7 +2584,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2607,7 +2595,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
exists(FlowState state |
|
exists(FlowState state |
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and
|
||||||
PrevStage::revFlow(node2, pragma[only_bind_into](state), _) 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), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2804,11 +2792,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
// A PathNode is introduced by a source ...
|
// A PathNode is introduced by a source ...
|
||||||
Stage5::revFlow(node, state) and
|
Stage5::revFlow(node, state) and
|
||||||
sourceNode(node, state) and
|
sourceNode(node, state) and
|
||||||
(
|
sourceCallCtx(cc) and
|
||||||
if hasSourceCallCtx()
|
|
||||||
then cc instanceof CallContextSomeCall
|
|
||||||
else cc instanceof CallContextAny
|
|
||||||
) and
|
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(node.getDataFlowType())
|
ap = TAccessPathNil(node.getDataFlowType())
|
||||||
or
|
or
|
||||||
@@ -3214,11 +3198,7 @@ module Impl<FullStateConfigSig Config> {
|
|||||||
|
|
||||||
override predicate isSource() {
|
override predicate isSource() {
|
||||||
sourceNode(node, state) and
|
sourceNode(node, state) and
|
||||||
(
|
sourceCallCtx(cc) and
|
||||||
if hasSourceCallCtx()
|
|
||||||
then cc instanceof CallContextSomeCall
|
|
||||||
else cc instanceof CallContextAny
|
|
||||||
) and
|
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(node.getDataFlowType())
|
ap = TAccessPathNil(node.getDataFlowType())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import cpp
|
|||||||
import semmle.code.cpp.security.Security
|
import semmle.code.cpp.security.Security
|
||||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
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.IR
|
||||||
private import semmle.code.cpp.ir.dataflow.ResolveCall
|
private import semmle.code.cpp.ir.dataflow.ResolveCall
|
||||||
private import semmle.code.cpp.controlflow.IRGuards
|
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 {
|
private module DefaultTaintTrackingConfig implements DataFlow::ConfigSig {
|
||||||
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
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) }
|
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
|
||||||
conflatePointerAndPointee(nodeFrom, nodeTo)
|
conflatePointerAndPointee(nodeFrom, nodeTo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ToGlobalVarTaintTrackingCfg extends TaintTracking::Configuration {
|
private module DefaultTaintTrackingFlow = TaintTracking::Make<DefaultTaintTrackingConfig>;
|
||||||
ToGlobalVarTaintTrackingCfg() { this = "GlobalVarTaintTrackingCfg" }
|
|
||||||
|
|
||||||
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) {
|
predicate isSink(DataFlow::Node sink) { sink.asVariable() instanceof GlobalOrNamespaceVariable }
|
||||||
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))
|
writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable))
|
||||||
or
|
or
|
||||||
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
|
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 {
|
private module ToGlobalVarTaintTrackingFlow = TaintTracking::Make<ToGlobalVarTaintTrackingConfig>;
|
||||||
FromGlobalVarTaintTrackingCfg() { this = "FromGlobalVarTaintTrackingCfg" }
|
|
||||||
|
|
||||||
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
|
// This set of sources should be reasonably small, which is good for
|
||||||
// performance since the set of sinks is very large.
|
// 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_
|
// Additional step for flow out of variables. There is no flow _into_
|
||||||
// variables in this configuration, so this step only serves to take flow
|
// variables in this configuration, so this step only serves to take flow
|
||||||
// out of a variable that's a source.
|
// out of a variable that's a source.
|
||||||
readsVariable(n2.asInstruction(), n1.asVariable())
|
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) {
|
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||||
}
|
}
|
||||||
@@ -332,8 +330,8 @@ private import Cached
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate tainted(Expr source, Element tainted) {
|
predicate tainted(Expr source, Element tainted) {
|
||||||
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
|
exists(DataFlow::Node sink |
|
||||||
cfg.hasFlow(getNodeForSource(source), sink) and
|
DefaultTaintTrackingFlow::hasFlow(getNodeForSource(source), sink) and
|
||||||
tainted = adjustedSink(sink)
|
tainted = adjustedSink(sink)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -359,12 +357,11 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
|
|||||||
globalVar = ""
|
globalVar = ""
|
||||||
or
|
or
|
||||||
exists(
|
exists(
|
||||||
ToGlobalVarTaintTrackingCfg toCfg, FromGlobalVarTaintTrackingCfg fromCfg,
|
|
||||||
DataFlow::VariableNode variableNode, GlobalOrNamespaceVariable global, DataFlow::Node sink
|
DataFlow::VariableNode variableNode, GlobalOrNamespaceVariable global, DataFlow::Node sink
|
||||||
|
|
|
|
||||||
global = variableNode.getVariable() and
|
global = variableNode.getVariable() and
|
||||||
toCfg.hasFlow(getNodeForSource(source), variableNode) and
|
ToGlobalVarTaintTrackingFlow::hasFlow(getNodeForSource(source), variableNode) and
|
||||||
fromCfg.hasFlow(variableNode, sink) and
|
FromGlobalVarTaintTrackingFlow::hasFlow(variableNode, sink) and
|
||||||
tainted = adjustedSink(sink) and
|
tainted = adjustedSink(sink) and
|
||||||
global = globalVarFromId(globalVar)
|
global = globalVarFromId(globalVar)
|
||||||
)
|
)
|
||||||
@@ -422,20 +419,18 @@ module TaintedWithPath {
|
|||||||
string toString() { result = "TaintTrackingConfiguration" }
|
string toString() { result = "TaintTrackingConfiguration" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AdjustedConfiguration extends TaintTracking3::Configuration {
|
private module AdjustedConfig implements DataFlow::ConfigSig {
|
||||||
AdjustedConfiguration() { this = "AdjustedConfiguration" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(TaintTrackingConfiguration cfg, Expr e |
|
exists(TaintTrackingConfiguration cfg, Expr e |
|
||||||
cfg.isSource(e) and source = getNodeForExpr(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)))
|
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)
|
conflatePointerAndPointee(n1, n2)
|
||||||
or
|
or
|
||||||
// Steps into and out of global variables
|
// Steps into and out of global variables
|
||||||
@@ -448,13 +443,15 @@ module TaintedWithPath {
|
|||||||
additionalTaintStep(n1, n2)
|
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))
|
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
|
* A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the
|
||||||
* inverse of) `adjustedSink`. For example, an `Expr` maps to all its
|
* inverse of) `adjustedSink`. For example, an `Expr` maps to all its
|
||||||
@@ -470,12 +467,12 @@ module TaintedWithPath {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private newtype TPathNode =
|
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
|
// There's a single newtype constructor for both sources and sinks since
|
||||||
// that makes it easiest to deal with the case where source = sink.
|
// that makes it easiest to deal with the case where source = sink.
|
||||||
TEndpointPathNode(Element e) {
|
TEndpointPathNode(Element e) {
|
||||||
exists(AdjustedConfiguration cfg, DataFlow3::Node sourceNode, DataFlow3::Node sinkNode |
|
exists(DataFlow::Node sourceNode, DataFlow::Node sinkNode |
|
||||||
cfg.hasFlow(sourceNode, sinkNode)
|
AdjustedFlow::hasFlow(sourceNode, sinkNode)
|
||||||
|
|
|
|
||||||
sourceNode = getNodeForExpr(e) and
|
sourceNode = getNodeForExpr(e) and
|
||||||
exists(TaintTrackingConfiguration ttCfg | ttCfg.isSource(e))
|
exists(TaintTrackingConfiguration ttCfg | ttCfg.isSource(e))
|
||||||
@@ -524,7 +521,7 @@ module TaintedWithPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class WrapPathNode extends PathNode, TWrapPathNode {
|
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() }
|
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. */
|
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||||
query predicate edges(PathNode a, PathNode b) {
|
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
|
or
|
||||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||||
// of adding an edge out of it.
|
// of adding an edge out of it.
|
||||||
exists(WrapPathNode sinkNode |
|
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())
|
b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Same for the first node
|
// Same for the first node
|
||||||
exists(WrapPathNode sourceNode |
|
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())
|
sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Finally, handle the case where the path goes directly from a source to a
|
// Finally, handle the case where the path goes directly from a source to a
|
||||||
// sink, meaning that they both need to be translated.
|
// sink, meaning that they both need to be translated.
|
||||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
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
|
sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner()) and
|
||||||
b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
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.
|
* 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) {
|
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())
|
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner())
|
||||||
or
|
or
|
||||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||||
// of adding an edge out of it.
|
// of adding an edge out of it.
|
||||||
exists(WrapPathNode sinkNode |
|
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
|
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Same for the first node
|
// Same for the first node
|
||||||
exists(WrapPathNode sourceNode |
|
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
|
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner()) and
|
||||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner())
|
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
|
// Finally, handle the case where the path goes directly from a source to a
|
||||||
// sink, meaning that they both need to be translated.
|
// sink, meaning that they both need to be translated.
|
||||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
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
|
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner()) and
|
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner()) and
|
||||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||||
@@ -634,10 +631,10 @@ module TaintedWithPath {
|
|||||||
* the computation.
|
* the computation.
|
||||||
*/
|
*/
|
||||||
predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) {
|
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
|
source = sourceNode.(InitialPathNode).inner() and
|
||||||
flowSource = getNodeForExpr(source) and
|
flowSource = getNodeForExpr(source) and
|
||||||
cfg.hasFlow(flowSource, flowSink) and
|
AdjustedFlow::hasFlow(flowSource, flowSink) and
|
||||||
tainted = adjustedSink(flowSink) and
|
tainted = adjustedSink(flowSink) and
|
||||||
tainted = sinkNode.(FinalPathNode).inner()
|
tainted = sinkNode.(FinalPathNode).inner()
|
||||||
)
|
)
|
||||||
@@ -660,8 +657,8 @@ module TaintedWithPath {
|
|||||||
* through a global variable.
|
* through a global variable.
|
||||||
*/
|
*/
|
||||||
predicate taintedWithoutGlobals(Element tainted) {
|
predicate taintedWithoutGlobals(Element tainted) {
|
||||||
exists(AdjustedConfiguration cfg, PathNode sourceNode, FinalPathNode sinkNode |
|
exists(PathNode sourceNode, FinalPathNode sinkNode |
|
||||||
cfg.isSource(sourceNode.(WrapPathNode).inner().getNode()) and
|
AdjustedConfig::isSource(sourceNode.(WrapPathNode).inner().getNode()) and
|
||||||
edgesWithoutGlobals+(sourceNode, sinkNode) and
|
edgesWithoutGlobals+(sourceNode, sinkNode) and
|
||||||
tainted = sinkNode.inner()
|
tainted = sinkNode.inner()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
private import IR
|
private import IR
|
||||||
import InstructionConsistency // module is below
|
import InstructionConsistency // module is below
|
||||||
import IRTypeConsistency // module is in IRType.qll
|
import IRTypeConsistency // module is in IRType.qll
|
||||||
|
import internal.IRConsistencyImports
|
||||||
|
|
||||||
module InstructionConsistency {
|
module InstructionConsistency {
|
||||||
private import internal.InstructionImports as Imports
|
private import internal.InstructionImports as Imports
|
||||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
|||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
override Language::Location getLocation() {
|
override Language::Location getLocation() {
|
||||||
|
|||||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
|||||||
|
|
||||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
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() {
|
override int getOrder() {
|
||||||
this =
|
this =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import AliasAnalysis
|
import AliasAnalysis
|
||||||
|
import semmle.code.cpp.Location
|
||||||
import semmle.code.cpp.ir.internal.Overlap
|
import semmle.code.cpp.ir.internal.Overlap
|
||||||
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
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.IR
|
||||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa
|
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa
|
||||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
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.IRConfiguration as IRConfiguration
|
||||||
|
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||||
|
|||||||
@@ -1,2 +1,55 @@
|
|||||||
private import SSAConstruction as Ssa
|
import SsaConsistency
|
||||||
import Ssa::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
|
* 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 {
|
module DebugSsa {
|
||||||
import PhiInsertion
|
import PhiInsertion
|
||||||
@@ -1063,62 +1063,6 @@ private module CachedForDebugging {
|
|||||||
int maxValue() { result = 2147483647 }
|
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
|
* 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.
|
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
private import IR
|
private import IR
|
||||||
import InstructionConsistency // module is below
|
import InstructionConsistency // module is below
|
||||||
import IRTypeConsistency // module is in IRType.qll
|
import IRTypeConsistency // module is in IRType.qll
|
||||||
|
import internal.IRConsistencyImports
|
||||||
|
|
||||||
module InstructionConsistency {
|
module InstructionConsistency {
|
||||||
private import internal.InstructionImports as Imports
|
private import internal.InstructionImports as Imports
|
||||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
|||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
override Language::Location getLocation() {
|
override Language::Location getLocation() {
|
||||||
|
|||||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
|||||||
|
|
||||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
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() {
|
override int getOrder() {
|
||||||
this =
|
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.IRConfiguration as IRConfiguration
|
||||||
|
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
private import IR
|
private import IR
|
||||||
import InstructionConsistency // module is below
|
import InstructionConsistency // module is below
|
||||||
import IRTypeConsistency // module is in IRType.qll
|
import IRTypeConsistency // module is in IRType.qll
|
||||||
|
import internal.IRConsistencyImports
|
||||||
|
|
||||||
module InstructionConsistency {
|
module InstructionConsistency {
|
||||||
private import internal.InstructionImports as Imports
|
private import internal.InstructionImports as Imports
|
||||||
@@ -28,7 +29,7 @@ module InstructionConsistency {
|
|||||||
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
PresentIRFunction() { this = TPresentIRFunction(irFunc) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
result = concat(Language::getIdentityString(irFunc.getFunction()), "; ")
|
result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
override Language::Location getLocation() {
|
override Language::Location getLocation() {
|
||||||
|
|||||||
@@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction
|
|||||||
|
|
||||||
override Language::Location getLocation() { result = irFunc.getLocation() }
|
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() {
|
override int getOrder() {
|
||||||
this =
|
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.IRConfiguration as IRConfiguration
|
||||||
|
import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug
|
||||||
|
|||||||
@@ -1,2 +1,55 @@
|
|||||||
private import SSAConstruction as Ssa
|
import SsaConsistency
|
||||||
import Ssa::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
|
* 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 {
|
module DebugSsa {
|
||||||
import PhiInsertion
|
import PhiInsertion
|
||||||
@@ -1063,62 +1063,6 @@ private module CachedForDebugging {
|
|||||||
int maxValue() { result = 2147483647 }
|
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
|
* 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.
|
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
private import cpp
|
private import cpp
|
||||||
private import semmle.code.cpp.Print
|
|
||||||
private import semmle.code.cpp.ir.implementation.IRType
|
private import semmle.code.cpp.ir.implementation.IRType
|
||||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction::Raw as Raw
|
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
|
* Gets a string that uniquely identifies an `IROpaqueType` tag. Using `toString` here might
|
||||||
* `toString()` of the tag in order to ensure uniqueness.
|
* 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) {
|
string getOpaqueTagIdentityString(Type tag) {
|
||||||
hasOpaqueType(tag, _) and
|
hasOpaqueType(tag, _) and
|
||||||
result = getTypeIdentityString(tag)
|
result = tag.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
module LanguageTypeConsistency {
|
module LanguageTypeConsistency {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
private import cpp as Cpp
|
private import cpp as Cpp
|
||||||
private import semmle.code.cpp.Print as Print
|
|
||||||
private import IRUtilities
|
private import IRUtilities
|
||||||
private import semmle.code.cpp.ir.implementation.IRType
|
private import semmle.code.cpp.ir.implementation.IRType
|
||||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
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
|
class Class = Cpp::Class; // Used for inheritance conversions
|
||||||
|
|
||||||
predicate getIdentityString = Print::getIdentityString/1;
|
|
||||||
|
|
||||||
predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) }
|
predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) }
|
||||||
|
|
||||||
predicate hasPositionalArgIndex(int argIndex) {
|
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.
|
* BufferWrite differ.
|
||||||
*/
|
*/
|
||||||
abstract class BufferAccess extends Expr {
|
abstract class BufferAccess extends Expr {
|
||||||
|
BufferAccess() { not this.isUnevaluated() }
|
||||||
|
|
||||||
abstract string getName();
|
abstract string getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ module BoostorgAsio {
|
|||||||
* Abstract class for flows of protocol values to the first argument of a context
|
* Abstract class for flows of protocol values to the first argument of a context
|
||||||
* constructor.
|
* constructor.
|
||||||
*/
|
*/
|
||||||
abstract class SslContextCallAbstractConfig extends DataFlow::Configuration {
|
abstract deprecated class SslContextCallAbstractConfig extends DataFlow::Configuration {
|
||||||
bindingset[this]
|
bindingset[this]
|
||||||
SslContextCallAbstractConfig() { any() }
|
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.
|
* 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" }
|
SslContextCallConfig() { this = "SslContextCallConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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.
|
* 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" }
|
SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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.
|
* 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" }
|
SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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.
|
* 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" }
|
SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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.
|
* 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" }
|
SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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()`.
|
* 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" }
|
SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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()`.
|
* 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" }
|
SslOptionConfig() { this = "SslOptionConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
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
|
## 0.5.4
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ import LoopBounds
|
|||||||
private predicate staticBufferBase(VariableAccess access, Variable v) {
|
private predicate staticBufferBase(VariableAccess access, Variable v) {
|
||||||
v.getType().(ArrayType).getBaseType() instanceof CharType and
|
v.getType().(ArrayType).getBaseType() instanceof CharType and
|
||||||
access = v.getAnAccess() and
|
access = v.getAnAccess() and
|
||||||
not memberMayBeVarSize(_, v)
|
not memberMayBeVarSize(_, v) and
|
||||||
|
not access.isUnevaluated()
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate staticBuffer(VariableAccess access, Variable v, int size) {
|
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()))
|
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
|
||||||
}
|
}
|
||||||
|
|
||||||
module NonConstFlowConfiguration implements DataFlow::ConfigSig {
|
module NonConstFlowConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
exists(boolean isIndirect, Type t |
|
exists(boolean isIndirect, Type t |
|
||||||
isNonConst(source, isIndirect) and
|
isNonConst(source, isIndirect) and
|
||||||
@@ -146,7 +146,7 @@ module NonConstFlowConfiguration implements DataFlow::ConfigSig {
|
|||||||
predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) }
|
predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) }
|
||||||
}
|
}
|
||||||
|
|
||||||
module NonConstFlow = TaintTracking::Make<NonConstFlowConfiguration>;
|
module NonConstFlow = TaintTracking::Make<NonConstFlowConfig>;
|
||||||
|
|
||||||
from FormattingFunctionCall call, Expr formatString
|
from FormattingFunctionCall call, Expr formatString
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration {
|
|||||||
* Data flow configuration for finding a variable access that would flow into
|
* Data flow configuration for finding a variable access that would flow into
|
||||||
* a function call that includes an operation to check for leap year.
|
* 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 isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
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
|
* 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
|
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
|
||||||
* a `FILEINFO` field.
|
* a `FILEINFO` field.
|
||||||
*/
|
*/
|
||||||
private module FiletimeYearArithmeticOperationCheckConfiguration implements DataFlow::ConfigSig {
|
private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
exists(Expr e, Operation op | e = source.asExpr() |
|
exists(Expr e, Operation op | e = source.asExpr() |
|
||||||
op.getAChild*().getValue().toInt() = 365 and
|
op.getAChild*().getValue().toInt() = 365 and
|
||||||
@@ -284,7 +284,7 @@ private module FiletimeYearArithmeticOperationCheckConfiguration implements Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
module FiletimeYearArithmeticOperationCheckFlow =
|
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.
|
* 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.
|
* 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) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
exists(Operation op | op = source.asConvertedExpr() |
|
exists(Operation op | op = source.asConvertedExpr() |
|
||||||
op.getAChild*().getValue().toInt() = 365 and
|
op.getAChild*().getValue().toInt() = 365 and
|
||||||
@@ -372,4 +372,4 @@ private module PossibleYearArithmeticOperationCheckConfiguration implements Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
module PossibleYearArithmeticOperationCheckFlow =
|
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 isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node node) { node.asExpr() = any(BufferAccess ba).getAccessedLength() }
|
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
|
ExistsAnyFlow::hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
|
||||||
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
|
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
|
||||||
contextSetOptions = fcSetOptions.getQualifier() and
|
contextSetOptions = fcSetOptions.getQualifier() and
|
||||||
forall(
|
forall(Expr optionArgument, Expr optionArgumentSource |
|
||||||
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
|
|
||||||
Expr optionArgumentSource
|
|
||||||
|
|
|
||||||
optionArgument = fcSetOptions.getArgument(0) and
|
optionArgument = fcSetOptions.getArgument(0) and
|
||||||
optionArgConfig
|
BoostorgAsio::SslOptionFlow::hasFlow(DataFlow::exprNode(optionArgumentSource),
|
||||||
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
DataFlow::exprNode(optionArgument))
|
||||||
|
|
|
|
||||||
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
|
||||||
)
|
)
|
||||||
@@ -50,11 +47,10 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
|
|||||||
bindingset[flag]
|
bindingset[flag]
|
||||||
predicate isOptionNotSet(ConstructorCall cc, int flag) { not isOptionSet(cc, flag, _) }
|
predicate isOptionNotSet(ConstructorCall cc, int flag) { not isOptionSet(cc, flag, _) }
|
||||||
|
|
||||||
from
|
from Expr protocolSource, Expr protocolSink, ConstructorCall cc, Expr e, string msg
|
||||||
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource,
|
|
||||||
Expr protocolSink, ConstructorCall cc, Expr e, string msg
|
|
||||||
where
|
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
|
cc.getArgument(0) = protocolSink and
|
||||||
(
|
(
|
||||||
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
|
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
|
||||||
|
|||||||
@@ -12,18 +12,15 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.security.boostorg.asio.protocols
|
import semmle.code.cpp.security.boostorg.asio.protocols
|
||||||
|
|
||||||
from
|
from Expr protocolSource, Expr protocolSink, ConstructorCall cc
|
||||||
BoostorgAsio::SslContextCallConfig config, Expr protocolSource, Expr protocolSink,
|
|
||||||
ConstructorCall cc
|
|
||||||
where
|
where
|
||||||
config.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
|
BoostorgAsio::SslContextCallFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||||
not exists(BoostorgAsio::SslContextCallTlsProtocolConfig tlsConfig |
|
DataFlow::exprNode(protocolSink)) and
|
||||||
tlsConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink))
|
not BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||||
) and
|
DataFlow::exprNode(protocolSink)) and
|
||||||
cc.getArgument(0) = protocolSink and
|
cc.getArgument(0) = protocolSink and
|
||||||
exists(BoostorgAsio::SslContextCallBannedProtocolConfig bannedConfig |
|
BoostorgAsio::SslContextCallBannedProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource),
|
||||||
bannedConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink))
|
DataFlow::exprNode(protocolSink))
|
||||||
)
|
|
||||||
select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.",
|
select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.",
|
||||||
cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(),
|
cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(),
|
||||||
cc.getEnclosingFunction(), cc.getEnclosingFunction().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 isSource(DataFlow::Node node) { node instanceof FlowSource }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node node) {
|
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
|
from
|
||||||
FileFunction fileFunction, Expr taintedArg, FlowSource taintSource,
|
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
|
* given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
|
||||||
* `ExecTaintConfiguration::isSink`.
|
* `ExecTaintConfiguration::isSink`.
|
||||||
*/
|
*/
|
||||||
module ExecStateConfiguration implements DataFlow::ConfigSig {
|
module ExecStateConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) { any(ExecState state).getOutgoingNode() = source }
|
predicate isSource(DataFlow::Node source) { any(ExecState state).getOutgoingNode() = source }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
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;
|
class FlowState = TState;
|
||||||
|
|
||||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||||
@@ -120,7 +120,7 @@ module ExecTaintConfiguration implements DataFlow::StateConfigSig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||||
ExecStateConfiguration::isSink(sink) and
|
ExecStateConfig::isSink(sink) and
|
||||||
state.(ExecState).isFeasibleForSink(sink)
|
state.(ExecState).isFeasibleForSink(sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ module ExecTaintConfiguration implements DataFlow::StateConfigSig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module ExecTaint = TaintTracking::MakeWithState<ExecTaintConfiguration>;
|
module ExecTaint = TaintTracking::MakeWithState<ExecTaintConfig>;
|
||||||
|
|
||||||
from
|
from
|
||||||
ExecTaint::PathNode sourceNode, ExecTaint::PathNode sinkNode, string taintCause, string callChain,
|
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) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
||||||
rand.getFunctionOutput().isReturnValue() and
|
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. */
|
/** Gets the expression that corresponds to `node`, if any. */
|
||||||
Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] }
|
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() }
|
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 isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { allocSink(_, sink) }
|
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
|
from
|
||||||
Expr alloc, TaintedAllocationSize::PathNode source, TaintedAllocationSize::PathNode sink,
|
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
|
* A taint flow configuration for flow from user input to a buffer write
|
||||||
* into a sensitive expression.
|
* into a sensitive expression.
|
||||||
*/
|
*/
|
||||||
module ToBufferConfiguration implements DataFlow::ConfigSig {
|
module ToBufferConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
predicate isBarrier(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
@@ -49,7 +49,7 @@ module ToBufferConfiguration implements DataFlow::ConfigSig {
|
|||||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
module ToBufferFlow = TaintTracking::Make<ToBufferConfiguration>;
|
module ToBufferFlow = TaintTracking::Make<ToBufferConfig>;
|
||||||
|
|
||||||
predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) {
|
predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) {
|
||||||
w.getASource() = sink.asIndirectExpr()
|
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.
|
* 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 isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
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) {
|
predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) {
|
||||||
exists(Expr e |
|
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
|
* A taint flow configuration for flow from a sensitive expression to a network
|
||||||
* operation.
|
* operation.
|
||||||
*/
|
*/
|
||||||
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
|
predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) }
|
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.
|
* 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 isSource(DataFlow::Node source) { FromSensitiveFlow::hasFlow(source, _) }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
|
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.
|
* 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 isSource(DataFlow::Node source) { isSinkEncrypt(source, _) }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::hasFlowTo(sink) }
|
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
|
from
|
||||||
FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
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.
|
* 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) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
isSourceImpl(source, _) and not sqlite_encryption_used()
|
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
|
from
|
||||||
SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ int getMinimumKeyStrength(string func, int paramIndex) {
|
|||||||
result = 2048
|
result = 2048
|
||||||
}
|
}
|
||||||
|
|
||||||
module KeyStrengthFlowConfiguration implements DataFlow::ConfigSig {
|
module KeyStrengthFlowConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node node) {
|
predicate isSource(DataFlow::Node node) {
|
||||||
exists(int bits |
|
exists(int bits |
|
||||||
node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and
|
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
|
from
|
||||||
KeyStrengthFlow::PathNode source, KeyStrengthFlow::PathNode sink, FunctionCall fc, int param,
|
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
|
* 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 isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
@@ -64,13 +64,12 @@ module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::Config
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module NullAppNameCreateProcessFunction =
|
module NullAppNameCreateProcessFunction = DataFlow::Make<NullAppNameCreateProcessFunctionConfig>;
|
||||||
DataFlow::Make<NullAppNameCreateProcessFunctionConfiguration>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dataflow that detects a call to CreateProcess with an unquoted commandLine argument
|
* 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) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
exists(string s |
|
exists(string s |
|
||||||
s = source.asExpr().getValue().toString() and
|
s = source.asExpr().getValue().toString() and
|
||||||
@@ -86,7 +85,7 @@ module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
module QuotedCommandInCreateProcessFunction =
|
module QuotedCommandInCreateProcessFunction =
|
||||||
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfiguration>;
|
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfig>;
|
||||||
|
|
||||||
bindingset[s]
|
bindingset[s]
|
||||||
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
|
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import semmle.code.cpp.models.interfaces.FlowSource
|
|||||||
import ExposedSystemData::PathGraph
|
import ExposedSystemData::PathGraph
|
||||||
import SystemData
|
import SystemData
|
||||||
|
|
||||||
module ExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
module ExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
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
|
from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import semmle.code.cpp.security.OutputWrite
|
|||||||
import PotentiallyExposedSystemData::PathGraph
|
import PotentiallyExposedSystemData::PathGraph
|
||||||
import SystemData
|
import SystemData
|
||||||
|
|
||||||
module PotentiallyExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
module PotentiallyExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) {
|
predicate isSource(DataFlow::Node source) {
|
||||||
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,7 @@ module PotentiallyExposedSystemDataConfiguration implements DataFlow::ConfigSig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module PotentiallyExposedSystemData =
|
module PotentiallyExposedSystemData = TaintTracking::Make<PotentiallyExposedSystemDataConfig>;
|
||||||
TaintTracking::Make<PotentiallyExposedSystemDataConfiguration>;
|
|
||||||
|
|
||||||
from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink
|
from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink
|
||||||
where PotentiallyExposedSystemData::hasFlowPath(source, sink)
|
where PotentiallyExposedSystemData::hasFlowPath(source, sink)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import XxeFlow::PathGraph
|
|||||||
/**
|
/**
|
||||||
* A configuration for tracking XML objects and their states.
|
* A configuration for tracking XML objects and their states.
|
||||||
*/
|
*/
|
||||||
module XxeConfiguration implements DataFlow::StateConfigSig {
|
module XxeConfig implements DataFlow::StateConfigSig {
|
||||||
class FlowState = TXxeFlowState;
|
class FlowState = TXxeFlowState;
|
||||||
|
|
||||||
predicate isSource(DataFlow::Node node, FlowState flowstate) {
|
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
|
from XxeFlow::PathNode source, XxeFlow::PathNode sink
|
||||||
where XxeFlow::hasFlowPath(source, 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 @@
|
|||||||
---
|
## 0.5.5
|
||||||
category: deprecated
|
|
||||||
---
|
### 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`.
|
* 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.
|
* 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 isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
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
|
from WordexpTaint::PathNode sourceNode, WordexpTaint::PathNode sinkNode
|
||||||
where WordexpTaint::hasFlowPath(sourceNode, 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 experimental.semmle.code.cpp.semantic.SemanticExprSpecific
|
||||||
import semmle.code.cpp.ir.IR
|
import semmle.code.cpp.ir.IR
|
||||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
import semmle.code.cpp.ir.dataflow.DataFlow2
|
import PointerArithmeticToDerefFlow::PathGraph
|
||||||
import DataFlow2::PathGraph
|
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Instruction getABoundIn(SemBound b, IRFunction func) {
|
Instruction getABoundIn(SemBound b, IRFunction func) {
|
||||||
@@ -36,16 +35,16 @@ predicate bounded(Instruction i, Instruction b, int delta) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldAddressToPointerArithmeticConf extends DataFlow::Configuration {
|
module FieldAddressToPointerArithmeticConfig implements DataFlow::ConfigSig {
|
||||||
FieldAddressToPointerArithmeticConf() { this = "FieldAddressToPointerArithmeticConf" }
|
predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(PointerAddInstruction pai | pai.getLeft() = sink.asInstruction())
|
exists(PointerAddInstruction pai | pai.getLeft() = sink.asInstruction())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module FieldAddressToPointerArithmeticFlow = DataFlow::Make<FieldAddressToPointerArithmeticConfig>;
|
||||||
|
|
||||||
predicate isFieldAddressSource(Field f, DataFlow::Node source) {
|
predicate isFieldAddressSource(Field f, DataFlow::Node source) {
|
||||||
source.asInstruction().(FieldAddressInstruction).getField() = f
|
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) {
|
predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int delta) {
|
||||||
exists(
|
exists(int size, int bound, DataFlow::Node source, DataFlow::InstructionNode sink |
|
||||||
int size, int bound, FieldAddressToPointerArithmeticConf conf, DataFlow::Node source,
|
FieldAddressToPointerArithmeticFlow::hasFlow(source, sink) and
|
||||||
DataFlow::InstructionNode sink
|
|
||||||
|
|
|
||||||
conf.hasFlow(source, sink) and
|
|
||||||
isFieldAddressSource(f, source) and
|
isFieldAddressSource(f, source) and
|
||||||
pai.getLeft() = sink.asInstruction() and
|
pai.getLeft() = sink.asInstruction() and
|
||||||
f.getUnspecifiedType().(ArrayType).getArraySize() = size and
|
f.getUnspecifiedType().(ArrayType).getArraySize() = size and
|
||||||
@@ -86,21 +82,21 @@ predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int d
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class PointerArithmeticToDerefConf extends DataFlow2::Configuration {
|
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
|
||||||
PointerArithmeticToDerefConf() { this = "PointerArithmeticToDerefConf" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
isConstantSizeOverflowSource(_, source.asInstruction(), _)
|
isConstantSizeOverflowSource(_, source.asInstruction(), _)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module PointerArithmeticToDerefFlow = DataFlow::Make<PointerArithmeticToDerefConfig>;
|
||||||
|
|
||||||
from
|
from
|
||||||
Field f, DataFlow2::PathNode source, DataFlow2::PathNode sink, Instruction deref,
|
Field f, PointerArithmeticToDerefFlow::PathNode source,
|
||||||
PointerArithmeticToDerefConf conf, string operation, int delta
|
PointerArithmeticToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(source, sink) and
|
PointerArithmeticToDerefFlow::hasFlowPath(source, sink) and
|
||||||
isInvalidPointerDerefSink(sink.getNode(), deref, operation) and
|
isInvalidPointerDerefSink(sink.getNode(), deref, operation) and
|
||||||
isConstantSizeOverflowSource(f, source.getNode().asInstruction(), delta)
|
isConstantSizeOverflowSource(f, source.getNode().asInstruction(), delta)
|
||||||
select source, source, sink,
|
select source, source, sink,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
import experimental.semmle.code.cpp.dataflow.ProductFlow
|
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.analysis.RangeAnalysis
|
||||||
import experimental.semmle.code.cpp.semantic.SemanticBound
|
import experimental.semmle.code.cpp.semantic.SemanticBound
|
||||||
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
|
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
|
* A configuration to track flow from a pointer-arithmetic operation found
|
||||||
* by `AllocToInvalidPointerConf` to a dereference of the pointer.
|
* by `AllocToInvalidPointerConf` to a dereference of the pointer.
|
||||||
*/
|
*/
|
||||||
class InvalidPointerToDerefConf extends DataFlow3::Configuration {
|
module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
|
||||||
InvalidPointerToDerefConf() { this = "InvalidPointerToDerefConf" }
|
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
|
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
|
||||||
|
|
||||||
override 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
|
* 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`.
|
* 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`
|
// The path nodes computed by the first projection of `AllocToInvalidPointerConf`
|
||||||
TPathNode1(DataFlow::PathNode p) or
|
TPathNode1(DataFlow::PathNode p) or
|
||||||
// The path nodes computed by `InvalidPointerToDerefConf`
|
// 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`.
|
// The read/write that uses the invalid pointer identified by `InvalidPointerToDerefConf`.
|
||||||
// This one is needed because the sink identified by `InvalidPointerToDerefConf` is the
|
// This one is needed because the sink identified by `InvalidPointerToDerefConf` is the
|
||||||
// pointer, but we want to raise an alert at the dereference.
|
// pointer, but we want to raise an alert at the dereference.
|
||||||
TPathNodeSink(Instruction i) {
|
TPathNodeSink(Instruction i) {
|
||||||
exists(DataFlow::Node n |
|
exists(DataFlow::Node n |
|
||||||
any(InvalidPointerToDerefConf conf).hasFlow(_, n) and
|
InvalidPointerToDerefFlow::hasFlow(_, n) and
|
||||||
isInvalidPointerDerefSink(n, i, _)
|
isInvalidPointerDerefSink(n, i, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -252,7 +251,7 @@ class MergedPathNode extends TMergedPathNode {
|
|||||||
|
|
||||||
final DataFlow::PathNode asPathNode1() { this = TPathNode1(result) }
|
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) }
|
final Instruction asSinkNode() { this = TPathNodeSink(result) }
|
||||||
|
|
||||||
@@ -280,7 +279,7 @@ class PathNode1 extends MergedPathNode, TPathNode1 {
|
|||||||
|
|
||||||
class PathNode3 extends MergedPathNode, TPathNode3 {
|
class PathNode3 extends MergedPathNode, TPathNode3 {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(DataFlow3::PathNode p |
|
exists(InvalidPointerToDerefFlow::PathNode p |
|
||||||
this = TPathNode3(p) and
|
this = TPathNode3(p) and
|
||||||
result = p.toString()
|
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
|
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
|
||||||
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.
|
* 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
|
isSinkImpl(pai, p1.getNode(), _, _) and
|
||||||
invalidPointerToDerefSource(pai, p2.getNode(), _)
|
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
|
* that dereferences `p1`. The string `operation` describes whether the `i` is
|
||||||
* a `StoreInstruction` or `LoadInstruction`.
|
* 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)
|
isInvalidPointerDerefSink(p1.getNode(), i, operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate hasFlowPath(
|
predicate hasFlowPath(
|
||||||
MergedPathNode source1, MergedPathNode sink, DataFlow3::PathNode source3,
|
MergedPathNode source1, MergedPathNode sink, InvalidPointerToDerefFlow::PathNode source3,
|
||||||
PointerArithmeticInstruction pai, string operation
|
PointerArithmeticInstruction pai, string operation
|
||||||
) {
|
) {
|
||||||
exists(
|
exists(
|
||||||
AllocToInvalidPointerConf conf1, InvalidPointerToDerefConf conf2, DataFlow3::PathNode sink3,
|
AllocToInvalidPointerConf conf1, InvalidPointerToDerefFlow::PathNode sink3,
|
||||||
DataFlow::PathNode sink1
|
DataFlow::PathNode sink1
|
||||||
|
|
|
|
||||||
conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and
|
conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and
|
||||||
joinOn1(pai, sink1, source3) and
|
joinOn1(pai, sink1, source3) and
|
||||||
conf2.hasFlowPath(source3, sink3) and
|
InvalidPointerToDerefFlow::hasFlowPath(source3, sink3) and
|
||||||
joinOn2(sink3, sink.asSinkNode(), operation)
|
joinOn2(sink3, sink.asSinkNode(), operation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
from
|
||||||
MergedPathNode source, MergedPathNode sink, int k, string kstr, DataFlow3::PathNode source3,
|
MergedPathNode source, MergedPathNode sink, int k, string kstr,
|
||||||
PointerArithmeticInstruction pai, string operation, Expr offset, DataFlow::Node n
|
InvalidPointerToDerefFlow::PathNode source3, PointerArithmeticInstruction pai, string operation,
|
||||||
|
Expr offset, DataFlow::Node n
|
||||||
where
|
where
|
||||||
hasFlowPath(source, sink, source3, pai, operation) and
|
hasFlowPath(source, sink, source3, pai, operation) and
|
||||||
invalidPointerToDerefSource(pai, source3.getNode(), k) and
|
invalidPointerToDerefSource(pai, source3.getNode(), k) and
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-queries
|
name: codeql/cpp-queries
|
||||||
version: 0.5.5-dev
|
version: 0.5.6-dev
|
||||||
groups:
|
groups:
|
||||||
- cpp
|
- cpp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.dataflow.new.DataFlow
|
import semmle.code.cpp.dataflow.new.DataFlow
|
||||||
|
|
||||||
class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
|
module LiteralToGethostbynameConfig implements DataFlow::ConfigSig {
|
||||||
LiteralToGethostbynameConfiguration() { this = "LiteralToGethostbynameConfiguration" }
|
predicate isSource(DataFlow::Node source) { source.asIndirectExpr(1) instanceof StringLiteral }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
source.asIndirectExpr(1) instanceof StringLiteral
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(FunctionCall fc |
|
exists(FunctionCall fc |
|
||||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
fc.getTarget().hasName("gethostbyname")
|
fc.getTarget().hasName("gethostbyname")
|
||||||
@@ -16,11 +12,11 @@ class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module LiteralToGethostbynameFlow = DataFlow::Make<LiteralToGethostbynameConfig>;
|
||||||
StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg, DataFlow::Node source,
|
|
||||||
DataFlow::Node sink
|
from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
||||||
where
|
where
|
||||||
source.asIndirectExpr(1) = sl and
|
source.asIndirectExpr(1) = sl and
|
||||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
cfg.hasFlow(source, sink)
|
LiteralToGethostbynameFlow::hasFlow(source, sink)
|
||||||
select sl, fc
|
select sl, fc
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ class GetenvSource extends DataFlow::Node {
|
|||||||
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
|
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
|
module GetenvToGethostbynameConfig implements DataFlow::ConfigSig {
|
||||||
GetenvToGethostbynameConfiguration() { this = "GetenvToGethostbynameConfiguration" }
|
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(FunctionCall fc |
|
exists(FunctionCall fc |
|
||||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
fc.getTarget().hasName("gethostbyname")
|
fc.getTarget().hasName("gethostbyname")
|
||||||
@@ -18,11 +16,11 @@ class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module GetenvToGethostbynameFlow = DataFlow::Make<GetenvToGethostbynameConfig>;
|
||||||
Expr getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg, DataFlow::Node source,
|
|
||||||
DataFlow::Node sink
|
from Expr getenv, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
||||||
where
|
where
|
||||||
source.asIndirectExpr(1) = getenv and
|
source.asIndirectExpr(1) = getenv and
|
||||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
cfg.hasFlow(source, sink)
|
GetenvToGethostbynameFlow::hasFlow(source, sink)
|
||||||
select getenv, fc
|
select getenv, fc
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.dataflow.new.DataFlow
|
import semmle.code.cpp.dataflow.new.DataFlow
|
||||||
|
|
||||||
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
|
module EnvironmentToFileConfig implements DataFlow::ConfigSig {
|
||||||
EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(Function getenv |
|
exists(Function getenv |
|
||||||
source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and
|
source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and
|
||||||
getenv.hasGlobalName("getenv")
|
getenv.hasGlobalName("getenv")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
exists(FunctionCall fc |
|
exists(FunctionCall fc |
|
||||||
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
fc.getTarget().hasGlobalName("fopen")
|
fc.getTarget().hasGlobalName("fopen")
|
||||||
@@ -19,11 +17,11 @@ class EnvironmentToFileConfiguration extends DataFlow::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module EnvironmentToFileFlow = DataFlow::Make<EnvironmentToFileConfig>;
|
||||||
Expr getenv, Expr fopen, EnvironmentToFileConfiguration config, DataFlow::Node source,
|
|
||||||
DataFlow::Node sink
|
from Expr getenv, Expr fopen, DataFlow::Node source, DataFlow::Node sink
|
||||||
where
|
where
|
||||||
source.asIndirectExpr(1) = getenv and
|
source.asIndirectExpr(1) = getenv and
|
||||||
sink.asIndirectExpr(1) = fopen 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'"
|
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.controlflow.Guards
|
||||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||||
|
|
||||||
class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
|
module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
|
||||||
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
|
predicate isSource(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) {
|
|
||||||
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
|
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset())
|
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 |
|
exists(Loop loop, LoopCounter lc |
|
||||||
loop = lc.getALoop() and
|
loop = lc.getALoop() and
|
||||||
loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr()
|
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 |
|
exists(GuardCondition gc, Variable v |
|
||||||
gc.getAChild*() = v.getAnAccess() and
|
gc.getAChild*() = v.getAnAccess() and
|
||||||
node.asExpr() = 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
|
module NetworkToBufferSizeFlow = TaintTracking::Make<NetworkToBufferSizeConfig>;
|
||||||
where conf.hasFlow(ntohl, offset)
|
|
||||||
|
from DataFlow::Node ntohl, DataFlow::Node offset
|
||||||
|
where NetworkToBufferSizeFlow::hasFlow(ntohl, offset)
|
||||||
select offset, "This array offset may be influenced by $@.", ntohl,
|
select offset, "This array offset may be influenced by $@.", ntohl,
|
||||||
"converted data from the network"
|
"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.RangeUtils
|
||||||
import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
|
import experimental.semmle.code.cpp.semantic.analysis.FloatDelta
|
||||||
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific
|
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 semmle.code.cpp.ir.IR as IR
|
||||||
import TestUtilities.InlineExpectationsTest
|
import TestUtilities.InlineExpectationsTest
|
||||||
|
|
||||||
module ModulusAnalysisInstantiated =
|
module ModulusAnalysisInstantiated =
|
||||||
ModulusAnalysis<FloatDelta, Bounds, RangeUtil<FloatDelta, CppLangImpl>>;
|
ModulusAnalysis<FloatDelta, ConstantBounds, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||||
|
|
||||||
class ModulusAnalysisTest extends InlineExpectationsTest {
|
class ModulusAnalysisTest extends InlineExpectationsTest {
|
||||||
ModulusAnalysisTest() { this = "ModulusAnalysisTest" }
|
ModulusAnalysisTest() { this = "ModulusAnalysisTest" }
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ int test9(int x, int y) {
|
|||||||
}
|
}
|
||||||
range(x); // $ range=>=4
|
range(x); // $ range=>=4
|
||||||
}
|
}
|
||||||
|
range(x); // $ MISSING: range=>=4
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
memcpy(dest, source, n); // GOOD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test23() {
|
||||||
|
char buffer[100];
|
||||||
|
return sizeof(buffer) / sizeof(buffer[101]); // GOOD
|
||||||
|
}
|
||||||
|
|
||||||
int tests_main(int argc, char *argv[])
|
int tests_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
long long arr17[19];
|
long long arr17[19];
|
||||||
@@ -627,6 +632,7 @@ int tests_main(int argc, char *argv[])
|
|||||||
test20();
|
test20();
|
||||||
test21(argc == 0);
|
test21(argc == 0);
|
||||||
test22(argc == 0, argv[0]);
|
test22(argc == 0, argv[0]);
|
||||||
|
test23();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.5
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
## 1.4.4
|
## 1.4.4
|
||||||
|
|
||||||
No user-facing changes.
|
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
|
name: codeql/csharp-solorigate-all
|
||||||
version: 1.4.5-dev
|
version: 1.4.6-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- solorigate
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.5
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
## 1.4.4
|
## 1.4.4
|
||||||
|
|
||||||
No user-facing changes.
|
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
|
name: codeql/csharp-solorigate-queries
|
||||||
version: 1.4.5-dev
|
version: 1.4.6-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- 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
|
## 0.5.4
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
### 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.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.5.4
|
lastReleaseVersion: 0.5.5
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-all
|
name: codeql/csharp-all
|
||||||
version: 0.5.5-dev
|
version: 0.5.6-dev
|
||||||
groups: csharp
|
groups: csharp
|
||||||
dbscheme: semmlecode.csharp.dbscheme
|
dbscheme: semmlecode.csharp.dbscheme
|
||||||
extractor: csharp
|
extractor: csharp
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user