mirror of
https://github.com/github/codeql.git
synced 2026-07-05 19:45:29 +02:00
Compare commits
294 Commits
codeql-cli
...
tombolton/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36a7c0ae48 | ||
|
|
f20de8e9b9 | ||
|
|
535658311e | ||
|
|
fafb032a7c | ||
|
|
9df77f80d6 | ||
|
|
2ba76fe61a | ||
|
|
320f4ca1da | ||
|
|
46e9b66b74 | ||
|
|
c0577f21da | ||
|
|
e5f2b830f3 | ||
|
|
f22df765ed | ||
|
|
0b30ecf36a | ||
|
|
d5bcd14733 | ||
|
|
7e6206ed36 | ||
|
|
af1d949d06 | ||
|
|
c98d024c0e | ||
|
|
accdd9499a | ||
|
|
7ac6f5849c | ||
|
|
57c39e9642 | ||
|
|
77aff04429 | ||
|
|
d4c8f42336 | ||
|
|
5efc19c39d | ||
|
|
8faabb837a | ||
|
|
21192b7593 | ||
|
|
5fb84a774b | ||
|
|
79f3da8af1 | ||
|
|
2014599f88 | ||
|
|
b75ac4e827 | ||
|
|
9e71d9bada | ||
|
|
68c07fe1c0 | ||
|
|
8f377f4101 | ||
|
|
cf57eb825c | ||
|
|
d56caa2398 | ||
|
|
9f3fd57534 | ||
|
|
c115c68247 | ||
|
|
b91914bd89 | ||
|
|
e377eebdbc | ||
|
|
11074b6d77 | ||
|
|
6b6ee61d3f | ||
|
|
94f014d948 | ||
|
|
b18b86b2e2 | ||
|
|
f0168d00d1 | ||
|
|
8e2ffc2508 | ||
|
|
5703f63afa | ||
|
|
cf94c93b1a | ||
|
|
99f14af56a | ||
|
|
e12b6df118 | ||
|
|
d51aaf2f91 | ||
|
|
80630972b1 | ||
|
|
98c0d73ffe | ||
|
|
005a020f04 | ||
|
|
15801fcc85 | ||
|
|
eef0da09bb | ||
|
|
1a9aaf4543 | ||
|
|
5f787144c0 | ||
|
|
3c434931ec | ||
|
|
74aea81fe3 | ||
|
|
496aab78a7 | ||
|
|
eff7cf6396 | ||
|
|
2699412160 | ||
|
|
28a430a2f2 | ||
|
|
3b4206cebf | ||
|
|
61c944201f | ||
|
|
b0b795dbbb | ||
|
|
c76a323246 | ||
|
|
1b4fb45089 | ||
|
|
69eb24e748 | ||
|
|
6870a19ace | ||
|
|
0d51804b5e | ||
|
|
ce54eb3c78 | ||
|
|
c923b9bb9b | ||
|
|
ec30a0f975 | ||
|
|
6d84baf276 | ||
|
|
95122b2b6c | ||
|
|
d476f976fe | ||
|
|
af888f7604 | ||
|
|
ac29d5f51b | ||
|
|
8b8f0ca6e5 | ||
|
|
41418e729e | ||
|
|
13be99196f | ||
|
|
9ae1ec69dc | ||
|
|
6804e20e4a | ||
|
|
06a99c3987 | ||
|
|
1e620c99c6 | ||
|
|
dc0c8374d2 | ||
|
|
2b42d84ccd | ||
|
|
6fbc0e6e32 | ||
|
|
8d13662315 | ||
|
|
647d37492d | ||
|
|
a81024a485 | ||
|
|
0eab54d385 | ||
|
|
b204f783fb | ||
|
|
671889372b | ||
|
|
e66932c728 | ||
|
|
4bcd4d75a9 | ||
|
|
f2285709bd | ||
|
|
59d5c54432 | ||
|
|
73071bdc08 | ||
|
|
6bef5a70b3 | ||
|
|
a84ee50af0 | ||
|
|
bbe28bc668 | ||
|
|
7eddc1e7ec | ||
|
|
7fc11be787 | ||
|
|
bd89de3c43 | ||
|
|
6c9d1a3edb | ||
|
|
9564f8bf5c | ||
|
|
20414c0e56 | ||
|
|
3f33cdf688 | ||
|
|
6ed1424679 | ||
|
|
1ac988323a | ||
|
|
586fd5a43b | ||
|
|
bbf60b875e | ||
|
|
5a1dc61d9d | ||
|
|
6a6cd61d83 | ||
|
|
01929d484e | ||
|
|
efc0d95535 | ||
|
|
f9120167b4 | ||
|
|
64a5c5d9aa | ||
|
|
f2728f5284 | ||
|
|
b5c05a580d | ||
|
|
47e062cfb9 | ||
|
|
8ae04e04d4 | ||
|
|
c35b385383 | ||
|
|
c06508570a | ||
|
|
afe4a8435f | ||
|
|
35af797683 | ||
|
|
93346a574f | ||
|
|
c6c3206031 | ||
|
|
5cdf0b5ee2 | ||
|
|
d476493c3e | ||
|
|
dd4e82126c | ||
|
|
2dad2c477b | ||
|
|
5d5904d6c8 | ||
|
|
5cbd86519b | ||
|
|
b95a332ded | ||
|
|
9254b2904e | ||
|
|
6bd9d82610 | ||
|
|
945b52fc46 | ||
|
|
1d45996001 | ||
|
|
68de6a4e3c | ||
|
|
9c2fc1b415 | ||
|
|
311cbb4e13 | ||
|
|
414764ccee | ||
|
|
e50a9421a6 | ||
|
|
099d91ba6f | ||
|
|
99ddfb489f | ||
|
|
ea065b7d8a | ||
|
|
90a6717932 | ||
|
|
36c7e10195 | ||
|
|
87e1641772 | ||
|
|
80fb021e32 | ||
|
|
99b5c580a5 | ||
|
|
c891e62a0e | ||
|
|
3e8bc8b0f2 | ||
|
|
2d9b630fa8 | ||
|
|
b1ae548f4c | ||
|
|
c2d4bc50c9 | ||
|
|
91a7e9405c | ||
|
|
130d93dded | ||
|
|
fac17384c3 | ||
|
|
ff1d96c922 | ||
|
|
b79eb6d10d | ||
|
|
6c18e1d7ac | ||
|
|
aff76b7295 | ||
|
|
2e55fd6be3 | ||
|
|
cf54006c86 | ||
|
|
c8385a1e80 | ||
|
|
758a81cc0f | ||
|
|
79cd7bf8ed | ||
|
|
92f8a90f31 | ||
|
|
8e2277e4f3 | ||
|
|
d31ef371ec | ||
|
|
97fef4b3a5 | ||
|
|
7295a5d313 | ||
|
|
6284362868 | ||
|
|
7f825c12eb | ||
|
|
e05227d3fe | ||
|
|
8b4c42dd07 | ||
|
|
5a6da827d0 | ||
|
|
5dcf0ad759 | ||
|
|
c253bddbe0 | ||
|
|
c73dc8ad0c | ||
|
|
10a411e5cc | ||
|
|
d79a6ddcb2 | ||
|
|
0cfe37dff4 | ||
|
|
4249e30824 | ||
|
|
63199024a2 | ||
|
|
f6215d4c7e | ||
|
|
f8198c3123 | ||
|
|
9412b331db | ||
|
|
693c77f3df | ||
|
|
235aa9c24e | ||
|
|
ff3bedcab9 | ||
|
|
2b9408b0c3 | ||
|
|
36c421346b | ||
|
|
4a68b74aa3 | ||
|
|
115cef2484 | ||
|
|
138eb485c6 | ||
|
|
565f607096 | ||
|
|
95a63a69a5 | ||
|
|
ae1ba11d57 | ||
|
|
85b22647ac | ||
|
|
f1e6271d20 | ||
|
|
461e2f3663 | ||
|
|
8b16c1f585 | ||
|
|
e69ea8f577 | ||
|
|
814947b876 | ||
|
|
a555e04b55 | ||
|
|
226a874a74 | ||
|
|
ec6dab89d8 | ||
|
|
92d748e006 | ||
|
|
2116e6d120 | ||
|
|
46f3f28a11 | ||
|
|
4f2678fc72 | ||
|
|
a9bbe6889b | ||
|
|
71e0da738d | ||
|
|
28315df405 | ||
|
|
ba67ea0445 | ||
|
|
73710e9edb | ||
|
|
7c93eb1eaf | ||
|
|
d1b04b4e07 | ||
|
|
432ac7a824 | ||
|
|
5a4a97569f | ||
|
|
5b5ea140d2 | ||
|
|
bf4dc0034a | ||
|
|
90b4eb9e13 | ||
|
|
74b8e73133 | ||
|
|
94999d4df5 | ||
|
|
8e7c7d8259 | ||
|
|
4a1981edfd | ||
|
|
b4f2fc60ec | ||
|
|
f241eef2ea | ||
|
|
6f5b2e8440 | ||
|
|
9ebdb2ac1d | ||
|
|
cb33ed4fc2 | ||
|
|
f1d6234483 | ||
|
|
4316026720 | ||
|
|
7691807713 | ||
|
|
934e06ca3b | ||
|
|
6848b6095b | ||
|
|
5c6923c099 | ||
|
|
88b7a085b0 | ||
|
|
07b4bf7023 | ||
|
|
6e5729c924 | ||
|
|
9e193f624c | ||
|
|
2a14a4f14e | ||
|
|
66b9356eb9 | ||
|
|
a1ace7122d | ||
|
|
70e4a409fd | ||
|
|
d95b56fca0 | ||
|
|
67aa1449ce | ||
|
|
19718fa280 | ||
|
|
da740cfa05 | ||
|
|
27d5349a74 | ||
|
|
a1c7ec8c6d | ||
|
|
cd58c12bbe | ||
|
|
98c60a706e | ||
|
|
e32f8d98b0 | ||
|
|
1538e89bd9 | ||
|
|
bd30c63aa1 | ||
|
|
714659c706 | ||
|
|
8afd560c64 | ||
|
|
48fba87273 | ||
|
|
6b9dd49499 | ||
|
|
e1191cf63c | ||
|
|
092cfceb18 | ||
|
|
d7ff00e615 | ||
|
|
ed36ff1570 | ||
|
|
fea46b642d | ||
|
|
9b458b54aa | ||
|
|
9cff4cbd1c | ||
|
|
ae057c74cc | ||
|
|
f8a51bb994 | ||
|
|
ef39968a56 | ||
|
|
d3f07cdc10 | ||
|
|
c78fed6594 | ||
|
|
f89fb50eb5 | ||
|
|
5130929358 | ||
|
|
843ed8fca5 | ||
|
|
5e23da813f | ||
|
|
e434f075fa | ||
|
|
3801a158a8 | ||
|
|
c3f4a851f0 | ||
|
|
3be3da2eb6 | ||
|
|
ef5818e243 | ||
|
|
16774ba285 | ||
|
|
095c73f1fe | ||
|
|
66fd43fc3b | ||
|
|
d8eea7ba4c | ||
|
|
a908b219e9 | ||
|
|
038b032a43 | ||
|
|
df9efbe778 | ||
|
|
52ca0d168b | ||
|
|
89786d9ce2 |
16
.github/workflows/ql-for-ql-build.yml
vendored
16
.github/workflows/ql-for-ql-build.yml
vendored
@@ -16,9 +16,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
tools: latest
|
||||
- name: Get CodeQL version
|
||||
id: get-codeql-version
|
||||
run: |
|
||||
@@ -159,7 +160,7 @@ jobs:
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
- name: Hack codeql-action options
|
||||
run: |
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
@@ -171,22 +172,25 @@ jobs:
|
||||
echo "paths:" > ${CONF}
|
||||
echo " - ${FOLDER}" >> ${CONF}
|
||||
echo "paths-ignore:" >> ${CONF}
|
||||
echo " - ql/ql/test" >> ${CONF}
|
||||
echo " - ql/ql/test" >> ${CONF}
|
||||
echo "disable-default-queries: true" >> ${CONF}
|
||||
echo "packs:" >> ${CONF}
|
||||
echo " - codeql/ql" >> ${CONF}
|
||||
echo "Config file: "
|
||||
cat ${CONF}
|
||||
env:
|
||||
CONF: ./ql-for-ql-config.yml
|
||||
FOLDER: ${{ matrix.folder }}
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
config-file: ./ql-for-ql-config.yml
|
||||
tools: latest
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@erik-krogh/ql
|
||||
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
with:
|
||||
category: "ql-for-ql-${{ matrix.folder }}"
|
||||
- name: Copy sarif file to CWD
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
2
.github/workflows/ql-for-ql-tests.yml
vendored
2
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
@@ -36,7 +36,7 @@ If you have an idea for a query that you would like to share with other CodeQL u
|
||||
|
||||
For details, see the [guide on query metadata](docs/query-metadata-style-guide.md).
|
||||
|
||||
Make sure the `select` statement is compatible with the query `@kind`. See [About CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/introduction-to-queries.html#select-clause) on help.semmle.com.
|
||||
Make sure the `select` statement is compatible with the query `@kind`. See [About CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/about-codeql-queries/#select-clause) on codeql.github.com.
|
||||
|
||||
3. **Formatting**
|
||||
|
||||
|
||||
@@ -482,11 +482,12 @@
|
||||
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll"
|
||||
],
|
||||
"ReDoS Exponential Python/JS": [
|
||||
"ReDoS Exponential Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll"
|
||||
"python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/ExponentialBackTracking.qll"
|
||||
],
|
||||
"ReDoS Polynomial Python/JS": [
|
||||
"ReDoS Polynomial Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/SuperlinearBackTracking.qll"
|
||||
@@ -518,12 +519,34 @@
|
||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
|
||||
],
|
||||
"Concepts Python/Ruby/JS": [
|
||||
"python/ql/lib/semmle/python/internal/ConceptsShared.qll",
|
||||
"ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll",
|
||||
"javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll"
|
||||
],
|
||||
"Hostname Regexp queries": [
|
||||
"javascript/ql/src/Security/CWE-020/HostnameRegexpShared.qll",
|
||||
"python/ql/src/Security/CWE-020/HostnameRegexpShared.qll",
|
||||
"ruby/ql/src/queries/security/cwe-020/HostnameRegexpShared.qll"
|
||||
],
|
||||
"ApiGraphModels": [
|
||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
|
||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
|
||||
],
|
||||
"TaintedFormatStringQuery Ruby/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/TaintedFormatStringQuery.qll"
|
||||
],
|
||||
"TaintedFormatStringCustomizations Ruby/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/TaintedFormatStringCustomizations.qll"
|
||||
],
|
||||
"HttpToFileAccessQuery JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessQuery.qll"
|
||||
],
|
||||
"HttpToFileAccessCustomizations JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -73,8 +73,24 @@ class Location extends @location {
|
||||
|
||||
/** Holds if `this` comes on a line strictly before `l`. */
|
||||
pragma[inline]
|
||||
predicate isBefore(Location l) {
|
||||
this.getFile() = l.getFile() and this.getEndLine() < l.getStartLine()
|
||||
predicate isBefore(Location l) { this.isBefore(l, false) }
|
||||
|
||||
/**
|
||||
* Holds if `this` comes strictly before `l`. The boolean `sameLine` is
|
||||
* true if `l` is on the same line as `this`, but starts at a later column.
|
||||
* Otherwise, `sameLine` is false.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isBefore(Location l, boolean sameLine) {
|
||||
this.getFile() = l.getFile() and
|
||||
(
|
||||
sameLine = false and
|
||||
this.getEndLine() < l.getStartLine()
|
||||
or
|
||||
sameLine = true and
|
||||
this.getEndLine() = l.getStartLine() and
|
||||
this.getEndColumn() < l.getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if location `l` is completely contained within this one. */
|
||||
|
||||
@@ -94,6 +94,7 @@ class Type extends Locatable, @type {
|
||||
* The result of this predicate will be the type itself, except in the case of a TypedefType or a Decltype,
|
||||
* in which case the result will be type which results from (possibly recursively) resolving typedefs.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Type getUnderlyingType() { result = this }
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,8 +161,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +206,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,8 +161,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +206,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -349,7 +349,7 @@ Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind ki
|
||||
|
||||
/** Holds if `goto` jumps strictly forward in the program text. */
|
||||
private predicate isStrictlyForwardGoto(GotoStmt goto) {
|
||||
goto.getLocation().isBefore(goto.getTarget().getLocation())
|
||||
goto.getLocation().isBefore(goto.getTarget().getLocation(), _)
|
||||
}
|
||||
|
||||
Locatable getInstructionAst(TStageInstruction instr) {
|
||||
|
||||
@@ -154,13 +154,6 @@ private predicate ignoreSideEffects(Expr expr) {
|
||||
* around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed.
|
||||
*/
|
||||
private predicate isInvalidFunction(Function func) {
|
||||
exists(Literal literal |
|
||||
// Constructor field inits within a compiler-generated copy constructor have a source expression
|
||||
// that is a `Literal` with no value.
|
||||
literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and
|
||||
not exists(literal.getValue())
|
||||
)
|
||||
or
|
||||
exists(ThisExpr thisExpr |
|
||||
// An instantiation of a member function template is not treated as a `MemberFunction` if it has
|
||||
// only non-type template arguments.
|
||||
|
||||
@@ -161,8 +161,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +206,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,6 +92,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* snapshots there may be multiple results where we can't tell which is correct for a
|
||||
* particular function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Type getWideCharType() {
|
||||
result = getFormatCharType() and
|
||||
result.getSize() > 1
|
||||
|
||||
21
cpp/ql/src/Diagnostics/Internal/ExtractionErrors.ql
Normal file
21
cpp/ql/src/Diagnostics/Internal/ExtractionErrors.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @name Extraction errors
|
||||
* @description List all extraction errors for files in the source code directory.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/extraction-errors
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExtractionErrors
|
||||
|
||||
// NOTE:
|
||||
// This file looks like the other `diagnostics/extraction-errors` queries in other CodeQL supported
|
||||
// languages. However, since this diagnostic query is located in the `Internal` subdirectory it will not
|
||||
// appear in the Code Scanning suite. The related query `cpp/diagnostics/extraction-warnings` is,
|
||||
// however, included as a public diagnostics query.
|
||||
from ExtractionError error
|
||||
where
|
||||
error instanceof ExtractionUnknownError or
|
||||
exists(error.getFile().getRelativePath())
|
||||
select error, "Extraction failed in " + error.getFile() + " with error " + error.getErrorMessage(),
|
||||
error.getSeverity()
|
||||
137
cpp/ql/src/Diagnostics/Internal/ExtractionErrors.qll
Normal file
137
cpp/ql/src/Diagnostics/Internal/ExtractionErrors.qll
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Provides a common hierarchy of all types of errors that can occur during extraction.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
* A note about how the C/C++ extractor emits diagnostics:
|
||||
* When the extractor frontend encounters an error, it emits a diagnostic message,
|
||||
* that includes a message, location and severity.
|
||||
* However, that process is best-effort and may fail (e.g. due to lack of memory).
|
||||
* Thus, if the extractor emitted at least one diagnostic of severity discretionary
|
||||
* error (or higher), it *also* emits a simple "There was an error during this compilation"
|
||||
* error diagnostic, without location information.
|
||||
* In the common case, this means that a compilation during which one or more errors happened also gets
|
||||
* the catch-all diagnostic.
|
||||
* This diagnostic has the empty string as file path.
|
||||
* We filter out these useless diagnostics if there is at least one error-level diagnostic
|
||||
* for the affected compilation in the database.
|
||||
* Otherwise, we show it to indicate that something went wrong and that we
|
||||
* don't know what exactly happened.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An error that, if present, leads to a file being marked as non-successfully extracted.
|
||||
*/
|
||||
class ReportableError extends Diagnostic {
|
||||
ReportableError() {
|
||||
(
|
||||
this instanceof CompilerDiscretionaryError or
|
||||
this instanceof CompilerError or
|
||||
this instanceof CompilerCatastrophe
|
||||
) and
|
||||
// Filter for the catch-all diagnostic, see note above.
|
||||
not this.getFile().getAbsolutePath() = ""
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TExtractionError =
|
||||
TReportableError(ReportableError err) or
|
||||
TCompilationFailed(Compilation c, File f) {
|
||||
f = c.getAFileCompiled() and not c.normalTermination()
|
||||
} or
|
||||
// Show the catch-all diagnostic (see note above) only if we haven't seen any other error-level diagnostic
|
||||
// for that compilation
|
||||
TUnknownError(CompilerError err) {
|
||||
not exists(ReportableError e | e.getCompilation() = err.getCompilation())
|
||||
}
|
||||
|
||||
/**
|
||||
* Superclass for the extraction error hierarchy.
|
||||
*/
|
||||
class ExtractionError extends TExtractionError {
|
||||
/** Gets the string representation of the error. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the error message for this error. */
|
||||
string getErrorMessage() { none() }
|
||||
|
||||
/** Gets the file this error occured in. */
|
||||
File getFile() { none() }
|
||||
|
||||
/** Gets the location this error occured in. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets the SARIF severity of this error. */
|
||||
int getSeverity() {
|
||||
// Unfortunately, we can't distinguish between errors and fatal errors in SARIF,
|
||||
// so all errors have severity 2.
|
||||
result = 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unrecoverable extraction error, where extraction was unable to finish.
|
||||
* This can be caused by a multitude of reasons, for example:
|
||||
* - hitting a frontend assertion
|
||||
* - crashing due to dereferencing an invalid pointer
|
||||
* - stack overflow
|
||||
* - out of memory
|
||||
*/
|
||||
class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed {
|
||||
Compilation c;
|
||||
File f;
|
||||
|
||||
ExtractionUnrecoverableError() { this = TCompilationFailed(c, f) }
|
||||
|
||||
override string toString() {
|
||||
result = "Unrecoverable extraction error while compiling " + f.toString()
|
||||
}
|
||||
|
||||
override string getErrorMessage() { result = "unrecoverable compilation failure." }
|
||||
|
||||
override File getFile() { result = f }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A recoverable extraction error.
|
||||
* These are compiler errors from the frontend.
|
||||
* Upon encountering one of these, we still continue extraction, but the
|
||||
* database will be incomplete for that file.
|
||||
*/
|
||||
class ExtractionRecoverableError extends ExtractionError, TReportableError {
|
||||
ReportableError err;
|
||||
|
||||
ExtractionRecoverableError() { this = TReportableError(err) }
|
||||
|
||||
override string toString() { result = "Recoverable extraction error: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unknown error happened during extraction.
|
||||
* These are only displayed if we know that we encountered an error during extraction,
|
||||
* but, for some reason, failed to emit a proper diagnostic with location information
|
||||
* and error message.
|
||||
*/
|
||||
class ExtractionUnknownError extends ExtractionError, TUnknownError {
|
||||
CompilerError err;
|
||||
|
||||
ExtractionUnknownError() { this = TUnknownError(err) }
|
||||
|
||||
override string toString() { result = "Unknown extraction error: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
}
|
||||
@@ -19,9 +19,9 @@ import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking2
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import semmle.code.cpp.models.implementations.Strcat
|
||||
import DataFlow::PathGraph
|
||||
|
||||
Expr sinkAsArgumentIndirection(DataFlow::Node sink) {
|
||||
result =
|
||||
@@ -66,154 +66,70 @@ predicate interestingConcatenation(DataFlow::Node fst, DataFlow::Node snd) {
|
||||
)
|
||||
}
|
||||
|
||||
class TaintToConcatenationConfiguration extends TaintTracking::Configuration {
|
||||
TaintToConcatenationConfiguration() { this = "TaintToConcatenationConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { interestingConcatenation(sink, _) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.asInstruction().getResultType() instanceof IntegralType
|
||||
or
|
||||
node.asInstruction().getResultType() instanceof FloatingPointType
|
||||
}
|
||||
class ConcatState extends DataFlow::FlowState {
|
||||
ConcatState() { this = "ConcatState" }
|
||||
}
|
||||
|
||||
class ExecTaintConfiguration extends TaintTracking2::Configuration {
|
||||
class ExecState extends DataFlow::FlowState {
|
||||
DataFlow::Node fst;
|
||||
DataFlow::Node snd;
|
||||
|
||||
ExecState() {
|
||||
this =
|
||||
"ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and
|
||||
interestingConcatenation(fst, snd)
|
||||
}
|
||||
|
||||
DataFlow::Node getFstNode() { result = fst }
|
||||
|
||||
DataFlow::Node getSndNode() { result = snd }
|
||||
}
|
||||
|
||||
class ExecTaintConfiguration extends TaintTracking::Configuration {
|
||||
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(DataFlow::Node prevSink, TaintToConcatenationConfiguration conf |
|
||||
conf.hasFlow(_, prevSink) and
|
||||
interestingConcatenation(prevSink, source)
|
||||
)
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
source instanceof FlowSource and
|
||||
state instanceof ConcatState
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
shellCommand(sinkAsArgumentIndirection(sink), _)
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
shellCommand(sinkAsArgumentIndirection(sink), _) and
|
||||
state instanceof ExecState
|
||||
}
|
||||
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
isSink(node) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
}
|
||||
}
|
||||
|
||||
module StitchedPathGraph {
|
||||
// There's a different PathNode class for each DataFlowImplN.qll, so we can't simply combine the
|
||||
// PathGraph predicates directly. Instead, we use a newtype so there's a single type that
|
||||
// contains both sets of PathNodes.
|
||||
newtype TMergedPathNode =
|
||||
TPathNode1(DataFlow::PathNode node) or
|
||||
TPathNode2(DataFlow2::PathNode node)
|
||||
|
||||
// this wraps the toString and location predicates so we can use the merged node type in a
|
||||
// selection
|
||||
class MergedPathNode extends TMergedPathNode {
|
||||
string toString() {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
result = n.toString()
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
result = n.toString()
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::Node getNode() {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
result = n.getNode()
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
result = n.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::PathNode getPathNode1() { this = TPathNode1(result) }
|
||||
|
||||
DataFlow2::PathNode getPathNode2() { this = TPathNode2(result) }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
query predicate edges(MergedPathNode a, MergedPathNode b) {
|
||||
exists(DataFlow::PathNode an, DataFlow::PathNode bn |
|
||||
a = TPathNode1(an) and
|
||||
b = TPathNode1(bn) and
|
||||
DataFlow::PathGraph::edges(an, bn)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode an, DataFlow2::PathNode bn |
|
||||
a = TPathNode2(an) and
|
||||
b = TPathNode2(bn) and
|
||||
DataFlow2::PathGraph::edges(an, bn)
|
||||
)
|
||||
or
|
||||
// This is where paths from the two configurations are connected. `interestingConcatenation`
|
||||
// is the only thing in this module that's actually specific to the query - everything else is
|
||||
// just using types and predicates from the DataFlow library.
|
||||
interestingConcatenation(a.getNode(), b.getNode()) and
|
||||
a instanceof TPathNode1 and
|
||||
b instanceof TPathNode2
|
||||
}
|
||||
|
||||
query predicate nodes(MergedPathNode mpn, string key, string val) {
|
||||
// here we just need the union of the underlying `nodes` predicates
|
||||
exists(DataFlow::PathNode n |
|
||||
mpn = TPathNode1(n) and
|
||||
DataFlow::PathGraph::nodes(n, key, val)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
mpn = TPathNode2(n) and
|
||||
DataFlow2::PathGraph::nodes(n, key, val)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate subpaths(
|
||||
MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out
|
||||
override predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
// just forward subpaths from the underlying libraries. This might be slightly awkward when
|
||||
// the concatenation is deep in a call chain.
|
||||
DataFlow::PathGraph::subpaths(arg.getPathNode1(), par.getPathNode1(), ret.getPathNode1(),
|
||||
out.getPathNode1())
|
||||
or
|
||||
DataFlow2::PathGraph::subpaths(arg.getPathNode2(), par.getPathNode2(), ret.getPathNode2(),
|
||||
out.getPathNode2())
|
||||
state1 instanceof ConcatState and
|
||||
state2.(ExecState).getFstNode() = node1 and
|
||||
state2.(ExecState).getSndNode() = node2
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
(
|
||||
node.asInstruction().getResultType() instanceof IntegralType
|
||||
or
|
||||
node.asInstruction().getResultType() instanceof FloatingPointType
|
||||
) and
|
||||
state instanceof ConcatState
|
||||
}
|
||||
|
||||
override predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
isSink(node, state) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
}
|
||||
}
|
||||
|
||||
import StitchedPathGraph
|
||||
|
||||
from
|
||||
DataFlow::PathNode sourceNode, DataFlow::PathNode concatSink, DataFlow2::PathNode concatSource,
|
||||
DataFlow2::PathNode sinkNode, string taintCause, string callChain,
|
||||
TaintToConcatenationConfiguration conf1, ExecTaintConfiguration conf2
|
||||
ExecTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode,
|
||||
string taintCause, string callChain, DataFlow::Node concatResult
|
||||
where
|
||||
conf.hasFlowPath(sourceNode, sinkNode) and
|
||||
taintCause = sourceNode.getNode().(FlowSource).getSourceType() and
|
||||
conf1.hasFlowPath(sourceNode, concatSink) and
|
||||
interestingConcatenation(concatSink.getNode(), concatSource.getNode()) and // this loses call context
|
||||
conf2.hasFlowPath(concatSource, sinkNode) and
|
||||
shellCommand(sinkAsArgumentIndirection(sinkNode.getNode()), callChain)
|
||||
select sinkAsArgumentIndirection(sinkNode.getNode()), TPathNode1(sourceNode).(MergedPathNode),
|
||||
TPathNode2(sinkNode).(MergedPathNode),
|
||||
shellCommand(sinkAsArgumentIndirection(sinkNode.getNode()), callChain) and
|
||||
concatResult = sinkNode.getState().(ExecState).getSndNode()
|
||||
select sinkAsArgumentIndirection(sinkNode.getNode()), sourceNode, sinkNode,
|
||||
"This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to "
|
||||
+ callChain, sourceNode, "user input (" + taintCause + ")", concatSource,
|
||||
concatSource.toString()
|
||||
+ callChain, sourceNode, "user input (" + taintCause + ")", concatResult,
|
||||
concatResult.toString()
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help an adversary to learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in these technologies.</p>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information might be revealed to a user.</p>
|
||||
<p>This query finds locations where system configuration information might be revealed to a remote user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to an adversary.</p>
|
||||
<p>Do not expose system configuration information to remote users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to an adversary who does not have legitimate access to that information.</p>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="ExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Exposure of system data to an unauthorized control sphere
|
||||
* @description Exposing system data or debugging information helps
|
||||
* an adversary learn about the system and form an
|
||||
* a malicious user learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
@@ -13,284 +13,15 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to an adversary.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract Expr getAnExpr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SqlClientInfo extends SystemData {
|
||||
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, VariableAccess use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SqlConnectInfo extends SystemData {
|
||||
SqlConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { sqlConnectInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, Element use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs", "uname"]) and
|
||||
use = source.getArgument(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, Element use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
use = source.getArgument([1, 2, 4])
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
use = source.getArgument([0, 1, 3])
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixPWInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, Element use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsFolderPath(this, result) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override Expr getAnExpr() { logonUser(this, result) }
|
||||
}
|
||||
|
||||
private predicate regQuery(FunctionCall source, VariableAccess use) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
use = source.getArgument(2)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _) }
|
||||
|
||||
override Expr getAnExpr() { regQuery(this, result) }
|
||||
}
|
||||
import SystemData
|
||||
|
||||
class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asConvertedExpr() = any(SystemData sd).getAnExpr()
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc, FunctionInput input, int arg |
|
||||
|
||||
@@ -2,6 +2,5 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "A required executable file could not be found. " \
|
||||
"Please ensure that the software has been installed " \
|
||||
"correctly or contact a system administrator.\n");
|
||||
message = "An internal error has occurred. Please try again or contact a system administrator.\n";
|
||||
send(socket, message, strlen(message), 0);
|
||||
@@ -2,4 +2,5 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "cannot find exe on path %s\n", path);
|
||||
sprintf(buffer, "Cannot find exe on path: %s", path);
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information that is particularly sensitive might be revealed to a user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
<p>The message should be rephrased without this information, for example:</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataCorrect.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @name Potential exposure of sensitive system data to an unauthorized control sphere
|
||||
* @description Exposing sensitive system data helps
|
||||
* a malicious user learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.5
|
||||
* @precision medium
|
||||
* @id cpp/potential-system-data-exposure
|
||||
* @tags security
|
||||
* external/cwe/cwe-497
|
||||
*/
|
||||
|
||||
/*
|
||||
* These queries are closely related:
|
||||
* - `cpp/system-data-exposure`, which flags exposure of system information
|
||||
* to a remote sink (i.e. focusses on quality of the sink).
|
||||
* - `cpp/potential-system-data-exposure`, which flags on exposure of the most
|
||||
* sensitive information to a local sink (i.e. focusses on quality of the
|
||||
* sensitive information).
|
||||
*
|
||||
* This used to be a single query with neither focus, which was too noisy and
|
||||
* gave the user less control.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.security.OutputWrite
|
||||
import DataFlow::PathGraph
|
||||
import SystemData
|
||||
|
||||
class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
PotentiallyExposedSystemDataConfiguration() { this = "PotentiallyExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(OutputWrite ow | ow.getASource().getAChild*() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
PotentiallyExposedSystemDataConfiguration config, DataFlow::PathNode source,
|
||||
DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "This operation potentially exposes sensitive system data from $@.",
|
||||
source, source.getNode().toString()
|
||||
@@ -0,0 +1,5 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Application key not recognized. Please ensure the key is correct or contact a system administrator.\n", key);
|
||||
@@ -0,0 +1,5 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Key not recognized: %s\n", key);
|
||||
342
cpp/ql/src/Security/CWE/CWE-497/SystemData.qll
Normal file
342
cpp/ql/src/Security/CWE/CWE-497/SystemData.qll
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Classes for recognizing system data, used by the exposed system data queries.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to a malicious user.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract DataFlow::Node getAnExpr();
|
||||
|
||||
/**
|
||||
* Holds if this system data is considered especially sensitive (for example
|
||||
* a password or token).
|
||||
*/
|
||||
predicate isSensitive() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() {
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(pass|token|key).*")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SQLClientInfo extends SystemData {
|
||||
SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SQLConnectInfo extends SystemData {
|
||||
SQLConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs"]) and
|
||||
use.asDefiningArgument() = source.getArgument(1)
|
||||
or
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName("uname") and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([1, 2]) or
|
||||
use.asDefiningArgument() = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([0, 1]) or
|
||||
use.asDefiningArgument() = source.getArgument(3)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixPWInfo(this, result) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsFolderPath(this, result.asDefiningArgument()) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { logonUser(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of a registry query parameter, if it is of interest to us. This
|
||||
* is used to express information about registry query parameters in the
|
||||
* `regQuery` predicate concisely.
|
||||
*/
|
||||
private newtype TRegQueryParameter =
|
||||
TSubKeyName() or
|
||||
TValueName() or
|
||||
TReturnData()
|
||||
|
||||
/**
|
||||
* Registry query call (`source`) with information about parameters (`param`).
|
||||
*/
|
||||
private predicate regQuery(FunctionCall source, TRegQueryParameter paramType, Expr param) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(2)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
paramType = TReturnData() and
|
||||
param = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
(
|
||||
paramType = TValueName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TValueName() and param = source.getArgument(2)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(5)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { regQuery(this, TReturnData(), result.asDefiningArgument()) }
|
||||
|
||||
override predicate isSensitive() {
|
||||
exists(Expr e |
|
||||
(
|
||||
regQuery(this, TSubKeyName(), e) or
|
||||
regQuery(this, TValueName(), e)
|
||||
) and
|
||||
e.getValue().toLowerCase().regexpMatch(".*(pass|token|key).*")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/command-line-injection` query now takes into account calling contexts across string concatenations. This removes false positives due to mismatched calling contexts before and after string concatenations.
|
||||
@@ -3,4 +3,3 @@
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
- apply: lgtm-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
# These are only for IDE use.
|
||||
- exclude:
|
||||
tags contain:
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
- apply: security-and-quality-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
- apply: security-extended-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
46
cpp/ql/src/experimental/Security/CWE/CWE-362/double-fetch.ql
Normal file
46
cpp/ql/src/experimental/Security/CWE/CWE-362/double-fetch.ql
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @name Linux kernel double-fetch vulnerability detection
|
||||
* @description Double-fetch is a very common vulnerability pattern
|
||||
* in linux kernel, attacker can exploit double-fetch
|
||||
* issues to obatain root privilege.
|
||||
* Double-fetch is caused by fetching data from user
|
||||
* mode by calling copy_from_user twice, CVE-2016-6480
|
||||
* is quite a good example for your information.
|
||||
* @kind problem
|
||||
* @id cpp/linux-kernel-double-fetch-vulnerability
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @tags security
|
||||
* external/cwe/cwe-362
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
class CopyFromUserFunctionCall extends FunctionCall {
|
||||
CopyFromUserFunctionCall() {
|
||||
this.getTarget().getName() = "copy_from_user" and
|
||||
not this.getArgument(1) instanceof AddressOfExpr
|
||||
}
|
||||
|
||||
//root cause of double-fetech issue is read from
|
||||
//the same user mode memory twice, so it makes
|
||||
//sense that only check user mode pointer
|
||||
predicate readFromSameUserModePointer(CopyFromUserFunctionCall another) {
|
||||
globalValueNumber(this.getArgument(1)) = globalValueNumber(another.getArgument(1))
|
||||
}
|
||||
}
|
||||
|
||||
from CopyFromUserFunctionCall p1, CopyFromUserFunctionCall p2
|
||||
where
|
||||
not p1 = p2 and
|
||||
p1.readFromSameUserModePointer(p2) and
|
||||
exists(IfStmt ifStmt |
|
||||
p1.getBasicBlock().getAFalseSuccessor*() = ifStmt.getBasicBlock() and
|
||||
ifStmt.getBasicBlock().getAFalseSuccessor*() = p2.getBasicBlock()
|
||||
) and
|
||||
not exists(AssignPointerAddExpr assignPtrAdd |
|
||||
globalValueNumber(p1.getArgument(1)) = globalValueNumber(assignPtrAdd.getLValue()) and
|
||||
p1.getBasicBlock().getAFalseSuccessor*() = assignPtrAdd.getBasicBlock()
|
||||
)
|
||||
select p2, "Double fetch vulnerability. First fetch was $@.", p1, p1.toString()
|
||||
@@ -208,11 +208,16 @@ postWithInFlow
|
||||
| lambdas.cpp:13:7:13:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:16:3:16:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:7:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -220,6 +225,8 @@ postWithInFlow
|
||||
| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:34:7:34:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:34:13:34:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:40:7:40:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
| arrayassignment.cpp:29:8:29:13 | call to source | arrayassignment.cpp:29:2:29:15 | ... = ... | |
|
||||
| arrayassignment.cpp:29:8:29:13 | call to source | arrayassignment.cpp:33:7:33:9 | r_x | |
|
||||
| arrayassignment.cpp:32:8:32:10 | p_x | arrayassignment.cpp:32:7:32:10 | * ... | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | Unknown literal | arrayassignment.cpp:37:7:37:7 | constructor init of field i | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | i | arrayassignment.cpp:37:7:37:7 | constructor init of field i | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | i | arrayassignment.cpp:37:7:37:7 | i | |
|
||||
| arrayassignment.cpp:37:7:37:7 | this | arrayassignment.cpp:37:7:37:7 | constructor init of field i [pre-this] | |
|
||||
| arrayassignment.cpp:40:2:40:6 | this | arrayassignment.cpp:40:12:40:15 | constructor init of field i [pre-this] | |
|
||||
| arrayassignment.cpp:40:12:40:15 | 0 | arrayassignment.cpp:40:12:40:15 | constructor init of field i | TAINT |
|
||||
@@ -284,6 +285,7 @@
|
||||
| copyableclass_declonly.cpp:67:13:67:18 | call to source | copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | TAINT |
|
||||
| copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | copyableclass_declonly.cpp:67:8:67:9 | ref arg s3 | TAINT |
|
||||
| copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | copyableclass_declonly.cpp:67:11:67:11 | call to operator= | TAINT |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | arrayassignment.cpp:37:7:37:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
@@ -299,6 +301,27 @@
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:228:11:228:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:228:11:228:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:243:11:243:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:243:11:243:11 | (unnamed parameter 0) | |
|
||||
| format.cpp:16:21:16:21 | s | format.cpp:16:21:16:21 | s | |
|
||||
| format.cpp:16:21:16:21 | s | format.cpp:22:22:22:22 | s | |
|
||||
| format.cpp:16:31:16:31 | n | format.cpp:22:25:22:25 | n | |
|
||||
@@ -3554,8 +3577,10 @@
|
||||
| standalone_iterators.cpp:120:2:120:3 | it | standalone_iterators.cpp:120:5:120:5 | call to operator+= | TAINT |
|
||||
| standalone_iterators.cpp:120:2:120:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
||||
| standalone_iterators.cpp:120:8:120:13 | call to source | standalone_iterators.cpp:120:2:120:3 | ref arg it | TAINT |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
||||
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
|
||||
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
|
||||
| stl.h:95:69:95:69 | x | stl.h:95:69:95:69 | x | |
|
||||
@@ -3573,16 +3598,6 @@
|
||||
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
|
||||
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
|
||||
| stl.h:292:53:292:63 | 0 | stl.h:292:46:292:64 | (no string representation) | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
@@ -3593,6 +3608,26 @@
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
@@ -5354,10 +5389,12 @@
|
||||
| stringstream.cpp:266:54:266:58 | ref arg call to flush | stringstream.cpp:266:35:266:39 | ref arg call to write | TAINT |
|
||||
| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:54:266:58 | ref arg call to flush | TAINT |
|
||||
| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:62:266:66 | call to write | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | v | |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | v | |
|
||||
| structlikeclass.cpp:8:2:8:16 | this | structlikeclass.cpp:8:28:8:32 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:8:22:8:23 | _v | structlikeclass.cpp:8:30:8:31 | _v | |
|
||||
| structlikeclass.cpp:8:30:8:31 | _v | structlikeclass.cpp:8:28:8:32 | constructor init of field v | TAINT |
|
||||
@@ -5973,24 +6010,29 @@
|
||||
| taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | |
|
||||
| taint.cpp:228:10:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
|
||||
| taint.cpp:228:10:232:2 | {...} | taint.cpp:228:10:232:2 | [...](...){...} | |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | t | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:228:11:228:11 | t | taint.cpp:228:11:228:11 | t | |
|
||||
| taint.cpp:228:11:228:11 | this | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | u | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:228:11:228:11 | u | taint.cpp:228:11:228:11 | u | |
|
||||
| taint.cpp:228:17:228:17 | this | taint.cpp:229:3:229:6 | this | |
|
||||
| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | |
|
||||
| taint.cpp:230:3:230:6 | this | file://:0:0:0:0 | this | |
|
||||
| taint.cpp:235:10:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
|
||||
| taint.cpp:235:10:239:2 | {...} | taint.cpp:235:10:239:2 | [...](...){...} | |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [post-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [post-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | t | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:235:11:235:11 | t | taint.cpp:235:11:235:11 | t | |
|
||||
| taint.cpp:235:11:235:11 | this | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | u | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:235:11:235:11 | u | taint.cpp:235:11:235:11 | u | |
|
||||
| taint.cpp:235:11:235:11 | v | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
|
||||
| taint.cpp:235:11:235:11 | v | taint.cpp:235:11:235:11 | v | |
|
||||
| taint.cpp:235:15:235:15 | this | taint.cpp:236:3:236:6 | this | |
|
||||
| taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | |
|
||||
| taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | |
|
||||
@@ -5998,11 +6040,13 @@
|
||||
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
|
||||
| taint.cpp:243:10:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
|
||||
| taint.cpp:243:10:246:2 | {...} | taint.cpp:243:10:246:2 | [...](...){...} | |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | t | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:243:11:243:11 | t | taint.cpp:243:11:243:11 | t | |
|
||||
| taint.cpp:243:11:243:11 | this | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | u | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:243:11:243:11 | u | taint.cpp:243:11:243:11 | u | |
|
||||
| taint.cpp:243:15:243:15 | this | taint.cpp:244:3:244:6 | this | |
|
||||
| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | |
|
||||
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
| addressOf.cpp:40:15:40:15 | i | non-const address |
|
||||
| addressOf.cpp:42:19:42:22 | iref | non-const address |
|
||||
| addressOf.cpp:47:12:47:31 | captured | non-const address |
|
||||
| addressOf.cpp:47:13:47:13 | (unnamed parameter 0) | |
|
||||
| addressOf.cpp:47:13:47:13 | captured | |
|
||||
| addressOf.cpp:47:19:47:28 | captured | |
|
||||
| addressOf.cpp:48:3:48:4 | f1 | const address |
|
||||
| addressOf.cpp:49:13:49:13 | (unnamed parameter 0) | |
|
||||
| addressOf.cpp:49:13:49:13 | captured | |
|
||||
| addressOf.cpp:49:15:49:22 | captured | non-const address |
|
||||
| addressOf.cpp:49:27:49:36 | captured | |
|
||||
| addressOf.cpp:50:3:50:4 | f2 | const address |
|
||||
@@ -245,6 +249,10 @@
|
||||
| test.cpp:173:19:173:19 | x | const address |
|
||||
| test.cpp:174:20:174:20 | x | const address |
|
||||
| test.cpp:175:7:175:7 | x | |
|
||||
| test.cpp:178:8:178:8 | (unnamed parameter 0) | |
|
||||
| test.cpp:178:8:178:8 | (unnamed parameter 0) | |
|
||||
| test.cpp:178:8:178:8 | nested | |
|
||||
| test.cpp:178:8:178:8 | x_ | |
|
||||
| test.cpp:183:38:183:41 | yptr | |
|
||||
| test.cpp:183:48:183:48 | z | |
|
||||
| test.cpp:184:28:184:35 | static_y | non-const address |
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
| addressOf.cpp:61:33:61:35 | ref | addressOf.cpp:63:24:63:26 | ref |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
| indirect_use.cpp:30:28:30:30 | ppp | indirect_use.cpp:31:19:31:21 | ppp |
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:27:77:27 | x |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:48:77:48 | x |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:21:17:21:17 | p |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
| addressOf.cpp:61:23:61:25 | ptr | addressOf.cpp:63:19:63:21 | ptr |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:48:77:48 | x |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:21:17:21:17 | p |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
|
||||
@@ -155,15 +155,21 @@ bad_asts.cpp:
|
||||
# 19| getInitializer(0): [ConstructorFieldInit] constructor init of field x
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getExpr(): [Literal] Unknown literal
|
||||
# 19| getExpr(): [FieldAccess] x
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 19| Type = [LValueReferenceType] const Point &
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getInitializer(1): [ConstructorFieldInit] constructor init of field y
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getExpr(): [Literal] Unknown literal
|
||||
# 19| getExpr(): [FieldAccess] y
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 19| Type = [LValueReferenceType] const Point &
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 19| getStmt(0): [ReturnStmt] return ...
|
||||
# 19| [MoveConstructor] void Bad::Point::Point(Bad::Point&&)
|
||||
@@ -11645,51 +11651,75 @@ ir.cpp:
|
||||
# 1486| getInitializer(0): [ConstructorFieldInit] constructor init of field i
|
||||
# 1486| Type = [IntType] int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] i
|
||||
# 1486| Type = [IntType] int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(1): [ConstructorFieldInit] constructor init of field d
|
||||
# 1486| Type = [DoubleType] double
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] d
|
||||
# 1486| Type = [DoubleType] double
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(2): [ConstructorFieldInit] constructor init of field b
|
||||
# 1486| Type = [IntType] unsigned int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] b
|
||||
# 1486| Type = [IntType] unsigned int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(3): [ConstructorFieldInit] constructor init of field r
|
||||
# 1486| Type = [LValueReferenceType] int &
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] r
|
||||
# 1486| Type = [LValueReferenceType] int &
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(4): [ConstructorFieldInit] constructor init of field p
|
||||
# 1486| Type = [IntPointerType] int *
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] p
|
||||
# 1486| Type = [IntPointerType] int *
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(5): [ConstructorFieldInit] constructor init of field xs
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] ArrayType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] xs
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] ArrayType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(6): [ConstructorFieldInit] constructor init of field r_alt
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] RefType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] r_alt
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] RefType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getInitializer(7): [ConstructorFieldInit] constructor init of field m
|
||||
# 1486| Type = [Struct] StructuredBindingDataMemberMemberStruct
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| getExpr(): [FieldAccess] m
|
||||
# 1486| Type = [Struct] StructuredBindingDataMemberMemberStruct
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1486| getStmt(0): [ReturnStmt] return ...
|
||||
# 1486| [MoveConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct&&)
|
||||
@@ -12066,21 +12096,30 @@ ir.cpp:
|
||||
# 1539| getInitializer(0): [ConstructorFieldInit] constructor init of field i
|
||||
# 1539| Type = [IntType] int
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| getExpr(): [FieldAccess] i
|
||||
# 1539| Type = [IntType] int
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getInitializer(1): [ConstructorFieldInit] constructor init of field d
|
||||
# 1539| Type = [DoubleType] double
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| getExpr(): [FieldAccess] d
|
||||
# 1539| Type = [DoubleType] double
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getInitializer(2): [ConstructorFieldInit] constructor init of field r
|
||||
# 1539| Type = [LValueReferenceType] int &
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| getExpr(): [FieldAccess] r
|
||||
# 1539| Type = [LValueReferenceType] int &
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1539| getStmt(0): [ReturnStmt] return ...
|
||||
# 1539| [MoveConstructor] void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet&&)
|
||||
@@ -13035,6 +13074,23 @@ ir.cpp:
|
||||
# 1689| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1689| getStmt(0): [EmptyStmt] ;
|
||||
# 1689| getStmt(1): [ReturnStmt] return ...
|
||||
# 1693| [TopLevelFunction] int goto_on_same_line()
|
||||
# 1693| <params>:
|
||||
# 1693| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1694| getStmt(0): [DeclStmt] declaration
|
||||
# 1694| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
|
||||
# 1694| Type = [IntType] int
|
||||
# 1694| getVariable().getInitializer(): [Initializer] initializer for x
|
||||
# 1694| getExpr(): [Literal] 42
|
||||
# 1694| Type = [IntType] int
|
||||
# 1694| Value = [Literal] 42
|
||||
# 1694| ValueCategory = prvalue
|
||||
# 1695| getStmt(1): [GotoStmt] goto ...
|
||||
# 1695| getStmt(2): [LabelStmt] label ...:
|
||||
# 1696| getStmt(3): [ReturnStmt] return ...
|
||||
# 1696| getExpr(): [VariableAccess] x
|
||||
# 1696| Type = [IntType] int
|
||||
# 1696| ValueCategory = prvalue(load)
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
|
||||
@@ -1690,4 +1690,10 @@ void captured_lambda(int x, int &y, int &&z)
|
||||
};
|
||||
}
|
||||
|
||||
int goto_on_same_line() {
|
||||
int x = 42;
|
||||
goto next; next:
|
||||
return x;
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -41,6 +41,35 @@
|
||||
| bad_asts.cpp:16:7:16:23 | ChiTotal | total:m14_4 |
|
||||
| bad_asts.cpp:16:7:16:23 | SideEffect | ~m14_4 |
|
||||
| bad_asts.cpp:16:25:16:25 | Arg(0) | 0:r16_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_5 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_5 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_7 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_7 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_9 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_10 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_12 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_16 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_17 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_19 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_14 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_21 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_8 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_15 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m0_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m0_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | ~m0_4 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | ~m0_4 |
|
||||
| bad_asts.cpp:19:10:19:10 | SideEffect | m19_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | SideEffect | m19_22 |
|
||||
| bad_asts.cpp:19:10:19:10 | StoreValue | r19_13 |
|
||||
| bad_asts.cpp:19:10:19:10 | StoreValue | r19_20 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | r19_11 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | r19_18 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_5 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_5 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_7 |
|
||||
@@ -633,6 +662,12 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_2 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
@@ -643,6 +678,12 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
@@ -692,6 +733,9 @@
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m745_6 |
|
||||
| file://:0:0:0:0 | Load | m754_6 |
|
||||
| file://:0:0:0:0 | Load | m763_6 |
|
||||
@@ -706,6 +750,9 @@
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
| file://:0:0:0:0 | SideEffect | m1084_23 |
|
||||
@@ -6769,13 +6816,102 @@
|
||||
| ir.cpp:1482:8:1482:8 | SideEffect | m1482_8 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_9 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_10 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_12 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_16 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_17 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_19 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_23 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_24 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_26 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_30 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_31 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_33 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_37 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_38 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_40 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_44 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_45 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_47 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_51 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_52 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_54 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_58 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_59 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_61 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_14 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_21 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_28 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_35 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_42 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_49 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_56 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_63 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_2 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_2 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_8 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_15 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_22 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_29 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_36 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_43 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_50 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_57 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_8 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_64 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_13 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_20 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_27 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_34 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_41 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_48 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_55 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_62 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_11 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_18 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_25 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_32 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_39 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_46 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_53 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_60 |
|
||||
| ir.cpp:1499:6:1499:35 | ChiPartial | partial:m1499_3 |
|
||||
| ir.cpp:1499:6:1499:35 | ChiTotal | total:m1499_2 |
|
||||
| ir.cpp:1499:6:1499:35 | SideEffect | ~m1525_7 |
|
||||
@@ -6948,13 +7084,52 @@
|
||||
| ir.cpp:1528:17:1528:17 | StoreValue | r1528_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_9 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_10 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_12 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_16 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_17 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_19 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_23 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_24 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_26 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_14 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_21 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_28 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_2 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_2 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_8 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_15 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_22 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_8 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_29 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_13 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_20 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_27 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_11 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_18 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_25 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_5 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_5 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_7 |
|
||||
@@ -7527,6 +7702,17 @@
|
||||
| ir.cpp:1689:50:1689:50 | Load | m1689_6 |
|
||||
| ir.cpp:1689:50:1689:50 | SideEffect | m1689_3 |
|
||||
| ir.cpp:1689:50:1689:50 | SideEffect | m1689_8 |
|
||||
| ir.cpp:1693:5:1693:21 | Address | &:r1693_5 |
|
||||
| ir.cpp:1693:5:1693:21 | ChiPartial | partial:m1693_3 |
|
||||
| ir.cpp:1693:5:1693:21 | ChiTotal | total:m1693_2 |
|
||||
| ir.cpp:1693:5:1693:21 | Load | m1696_4 |
|
||||
| ir.cpp:1693:5:1693:21 | SideEffect | m1693_3 |
|
||||
| ir.cpp:1694:7:1694:7 | Address | &:r1694_1 |
|
||||
| ir.cpp:1694:10:1694:12 | StoreValue | r1694_2 |
|
||||
| ir.cpp:1696:3:1696:11 | Address | &:r1696_1 |
|
||||
| ir.cpp:1696:10:1696:10 | Address | &:r1696_2 |
|
||||
| ir.cpp:1696:10:1696:10 | Load | m1694_3 |
|
||||
| ir.cpp:1696:10:1696:10 | StoreValue | r1696_3 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -49,6 +49,38 @@ bad_asts.cpp:
|
||||
# 14| v14_5(void) = AliasedUse : ~m?
|
||||
# 14| v14_6(void) = ExitFunction :
|
||||
|
||||
# 19| void Bad::Point::Point(Bad::Point const&)
|
||||
# 19| Block 0
|
||||
# 19| v19_1(void) = EnterFunction :
|
||||
# 19| mu19_2(unknown) = AliasedDefinition :
|
||||
# 19| mu19_3(unknown) = InitializeNonLocal :
|
||||
# 19| r19_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 19| mu19_5(glval<Point>) = InitializeParameter[#this] : &:r19_4
|
||||
# 19| r19_6(glval<Point>) = Load[#this] : &:r19_4, ~m?
|
||||
# 19| mu19_7(Point) = InitializeIndirection[#this] : &:r19_6
|
||||
#-----| r0_1(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(Point &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(Point &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 19| r19_8(glval<int>) = FieldAddress[x] : mu19_5
|
||||
# 19| r19_9(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 19| r19_10(Point &) = Load[(unnamed parameter 0)] : &:r19_9, ~m?
|
||||
# 19| r19_11(glval<int>) = FieldAddress[x] : r19_10
|
||||
# 19| r19_12(int) = Load[?] : &:r19_11, ~m?
|
||||
# 19| mu19_13(int) = Store[?] : &:r19_8, r19_12
|
||||
# 19| r19_14(glval<int>) = FieldAddress[y] : mu19_5
|
||||
# 19| r19_15(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 19| r19_16(Point &) = Load[(unnamed parameter 0)] : &:r19_15, ~m?
|
||||
# 19| r19_17(glval<int>) = FieldAddress[y] : r19_16
|
||||
# 19| r19_18(int) = Load[?] : &:r19_17, ~m?
|
||||
# 19| mu19_19(int) = Store[?] : &:r19_14, r19_18
|
||||
# 19| v19_20(void) = NoOp :
|
||||
# 19| v19_21(void) = ReturnIndirection[#this] : &:r19_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 19| v19_22(void) = ReturnVoid :
|
||||
# 19| v19_23(void) = AliasedUse : ~m?
|
||||
# 19| v19_24(void) = ExitFunction :
|
||||
|
||||
# 22| void Bad::Point::Point()
|
||||
# 22| Block 0
|
||||
# 22| v22_1(void) = EnterFunction :
|
||||
@@ -8029,6 +8061,74 @@ ir.cpp:
|
||||
# 1486| v1486_16(void) = AliasedUse : ~m?
|
||||
# 1486| v1486_17(void) = ExitFunction :
|
||||
|
||||
# 1486| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&)
|
||||
# 1486| Block 0
|
||||
# 1486| v1486_1(void) = EnterFunction :
|
||||
# 1486| mu1486_2(unknown) = AliasedDefinition :
|
||||
# 1486| mu1486_3(unknown) = InitializeNonLocal :
|
||||
# 1486| r1486_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1486| mu1486_5(glval<StructuredBindingDataMemberStruct>) = InitializeParameter[#this] : &:r1486_4
|
||||
# 1486| r1486_6(glval<StructuredBindingDataMemberStruct>) = Load[#this] : &:r1486_4, ~m?
|
||||
# 1486| mu1486_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1486_6
|
||||
#-----| r0_1(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(StructuredBindingDataMemberStruct &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 1486| r1486_8(glval<int>) = FieldAddress[i] : mu1486_5
|
||||
# 1486| r1486_9(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_10(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_9, ~m?
|
||||
# 1486| r1486_11(glval<int>) = FieldAddress[i] : r1486_10
|
||||
# 1486| r1486_12(int) = Load[?] : &:r1486_11, ~m?
|
||||
# 1486| mu1486_13(int) = Store[?] : &:r1486_8, r1486_12
|
||||
# 1486| r1486_14(glval<double>) = FieldAddress[d] : mu1486_5
|
||||
# 1486| r1486_15(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_16(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_15, ~m?
|
||||
# 1486| r1486_17(glval<double>) = FieldAddress[d] : r1486_16
|
||||
# 1486| r1486_18(double) = Load[?] : &:r1486_17, ~m?
|
||||
# 1486| mu1486_19(double) = Store[?] : &:r1486_14, r1486_18
|
||||
# 1486| r1486_20(glval<unsigned int>) = FieldAddress[b] : mu1486_5
|
||||
# 1486| r1486_21(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_22(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_21, ~m?
|
||||
# 1486| r1486_23(glval<unsigned int>) = FieldAddress[b] : r1486_22
|
||||
# 1486| r1486_24(unsigned int) = Load[?] : &:r1486_23, ~m?
|
||||
# 1486| mu1486_25(unsigned int) = Store[?] : &:r1486_20, r1486_24
|
||||
# 1486| r1486_26(glval<int &>) = FieldAddress[r] : mu1486_5
|
||||
# 1486| r1486_27(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_28(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_27, ~m?
|
||||
# 1486| r1486_29(glval<int &>) = FieldAddress[r] : r1486_28
|
||||
# 1486| r1486_30(int &) = Load[?] : &:r1486_29, ~m?
|
||||
# 1486| mu1486_31(int &) = Store[?] : &:r1486_26, r1486_30
|
||||
# 1486| r1486_32(glval<int *>) = FieldAddress[p] : mu1486_5
|
||||
# 1486| r1486_33(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_34(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_33, ~m?
|
||||
# 1486| r1486_35(glval<int *>) = FieldAddress[p] : r1486_34
|
||||
# 1486| r1486_36(int *) = Load[?] : &:r1486_35, ~m?
|
||||
# 1486| mu1486_37(int *) = Store[?] : &:r1486_32, r1486_36
|
||||
# 1486| r1486_38(glval<int[2]>) = FieldAddress[xs] : mu1486_5
|
||||
# 1486| r1486_39(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_40(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_39, ~m?
|
||||
# 1486| r1486_41(glval<int[2]>) = FieldAddress[xs] : r1486_40
|
||||
# 1486| r1486_42(int[2]) = Load[?] : &:r1486_41, ~m?
|
||||
# 1486| mu1486_43(int[2]) = Store[?] : &:r1486_38, r1486_42
|
||||
# 1486| r1486_44(glval<int &>) = FieldAddress[r_alt] : mu1486_5
|
||||
# 1486| r1486_45(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_46(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_45, ~m?
|
||||
# 1486| r1486_47(glval<int &>) = FieldAddress[r_alt] : r1486_46
|
||||
# 1486| r1486_48(int &) = Load[?] : &:r1486_47, ~m?
|
||||
# 1486| mu1486_49(int &) = Store[?] : &:r1486_44, r1486_48
|
||||
# 1486| r1486_50(glval<StructuredBindingDataMemberMemberStruct>) = FieldAddress[m] : mu1486_5
|
||||
# 1486| r1486_51(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_52(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_51, ~m?
|
||||
# 1486| r1486_53(glval<StructuredBindingDataMemberMemberStruct>) = FieldAddress[m] : r1486_52
|
||||
# 1486| r1486_54(StructuredBindingDataMemberMemberStruct) = Load[?] : &:r1486_53, ~m?
|
||||
# 1486| mu1486_55(StructuredBindingDataMemberMemberStruct) = Store[?] : &:r1486_50, r1486_54
|
||||
# 1486| v1486_56(void) = NoOp :
|
||||
# 1486| v1486_57(void) = ReturnIndirection[#this] : &:r1486_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 1486| v1486_58(void) = ReturnVoid :
|
||||
# 1486| v1486_59(void) = AliasedUse : ~m?
|
||||
# 1486| v1486_60(void) = ExitFunction :
|
||||
|
||||
# 1499| void data_member_structured_binding()
|
||||
# 1499| Block 0
|
||||
# 1499| v1499_1(void) = EnterFunction :
|
||||
@@ -8209,6 +8309,44 @@ ir.cpp:
|
||||
# 1539| v1539_11(void) = AliasedUse : ~m?
|
||||
# 1539| v1539_12(void) = ExitFunction :
|
||||
|
||||
# 1539| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&)
|
||||
# 1539| Block 0
|
||||
# 1539| v1539_1(void) = EnterFunction :
|
||||
# 1539| mu1539_2(unknown) = AliasedDefinition :
|
||||
# 1539| mu1539_3(unknown) = InitializeNonLocal :
|
||||
# 1539| r1539_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1539| mu1539_5(glval<StructuredBindingTupleRefGet>) = InitializeParameter[#this] : &:r1539_4
|
||||
# 1539| r1539_6(glval<StructuredBindingTupleRefGet>) = Load[#this] : &:r1539_4, ~m?
|
||||
# 1539| mu1539_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1539_6
|
||||
#-----| r0_1(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(StructuredBindingTupleRefGet &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 1539| r1539_8(glval<int>) = FieldAddress[i] : mu1539_5
|
||||
# 1539| r1539_9(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_10(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_9, ~m?
|
||||
# 1539| r1539_11(glval<int>) = FieldAddress[i] : r1539_10
|
||||
# 1539| r1539_12(int) = Load[?] : &:r1539_11, ~m?
|
||||
# 1539| mu1539_13(int) = Store[?] : &:r1539_8, r1539_12
|
||||
# 1539| r1539_14(glval<double>) = FieldAddress[d] : mu1539_5
|
||||
# 1539| r1539_15(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_16(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_15, ~m?
|
||||
# 1539| r1539_17(glval<double>) = FieldAddress[d] : r1539_16
|
||||
# 1539| r1539_18(double) = Load[?] : &:r1539_17, ~m?
|
||||
# 1539| mu1539_19(double) = Store[?] : &:r1539_14, r1539_18
|
||||
# 1539| r1539_20(glval<int &>) = FieldAddress[r] : mu1539_5
|
||||
# 1539| r1539_21(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_22(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_21, ~m?
|
||||
# 1539| r1539_23(glval<int &>) = FieldAddress[r] : r1539_22
|
||||
# 1539| r1539_24(int &) = Load[?] : &:r1539_23, ~m?
|
||||
# 1539| mu1539_25(int &) = Store[?] : &:r1539_20, r1539_24
|
||||
# 1539| v1539_26(void) = NoOp :
|
||||
# 1539| v1539_27(void) = ReturnIndirection[#this] : &:r1539_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 1539| v1539_28(void) = ReturnVoid :
|
||||
# 1539| v1539_29(void) = AliasedUse : ~m?
|
||||
# 1539| v1539_30(void) = ExitFunction :
|
||||
|
||||
# 1567| std::tuple_element<int 0, StructuredBindingTupleRefGet>::type& StructuredBindingTupleRefGet::get<int 0>()
|
||||
# 1567| Block 0
|
||||
# 1567| v1567_1(void) = EnterFunction :
|
||||
@@ -8842,6 +8980,25 @@ ir.cpp:
|
||||
# 1689| v1689_12(void) = AliasedUse : ~m?
|
||||
# 1689| v1689_13(void) = ExitFunction :
|
||||
|
||||
# 1693| int goto_on_same_line()
|
||||
# 1693| Block 0
|
||||
# 1693| v1693_1(void) = EnterFunction :
|
||||
# 1693| mu1693_2(unknown) = AliasedDefinition :
|
||||
# 1693| mu1693_3(unknown) = InitializeNonLocal :
|
||||
# 1694| r1694_1(glval<int>) = VariableAddress[x] :
|
||||
# 1694| r1694_2(int) = Constant[42] :
|
||||
# 1694| mu1694_3(int) = Store[x] : &:r1694_1, r1694_2
|
||||
# 1695| v1695_1(void) = NoOp :
|
||||
# 1695| v1695_2(void) = NoOp :
|
||||
# 1696| r1696_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1696| r1696_2(glval<int>) = VariableAddress[x] :
|
||||
# 1696| r1696_3(int) = Load[x] : &:r1696_2, ~m?
|
||||
# 1696| mu1696_4(int) = Store[#return] : &:r1696_1, r1696_3
|
||||
# 1693| r1693_4(glval<int>) = VariableAddress[#return] :
|
||||
# 1693| v1693_5(void) = ReturnValue : &:r1693_4, ~m?
|
||||
# 1693| v1693_6(void) = AliasedUse : ~m?
|
||||
# 1693| v1693_7(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -125,8 +125,8 @@
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | Unknown literal |
|
||||
| captures.cpp:22:19:22:19 | Unknown literal |
|
||||
| captures.cpp:22:19:22:19 | (unnamed parameter 0) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed parameter 0) |
|
||||
| captures.cpp:22:19:22:19 | constructor init of field x |
|
||||
| captures.cpp:22:19:22:19 | constructor init of field y |
|
||||
| captures.cpp:22:19:22:19 | declaration of (unnamed constructor) |
|
||||
@@ -135,6 +135,8 @@
|
||||
| captures.cpp:22:19:22:19 | definition of operator= |
|
||||
| captures.cpp:22:19:22:19 | operator= |
|
||||
| captures.cpp:22:19:22:19 | return ... |
|
||||
| captures.cpp:22:19:22:19 | x |
|
||||
| captures.cpp:22:19:22:19 | y |
|
||||
| captures.cpp:22:19:22:19 | { ... } |
|
||||
| captures.cpp:22:23:22:23 | definition of x |
|
||||
| captures.cpp:22:23:22:23 | x |
|
||||
@@ -185,12 +187,13 @@
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | Unknown literal |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed parameter 0) |
|
||||
| end_pos.cpp:9:15:9:15 | constructor init of field ii |
|
||||
| end_pos.cpp:9:15:9:15 | declaration of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of operator= |
|
||||
| end_pos.cpp:9:15:9:15 | ii |
|
||||
| end_pos.cpp:9:15:9:15 | operator= |
|
||||
| end_pos.cpp:9:15:9:15 | return ... |
|
||||
| end_pos.cpp:9:15:9:15 | { ... } |
|
||||
|
||||
@@ -1498,6 +1498,8 @@ postWithInFlow
|
||||
| bad_asts.cpp:15:10:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:27:11:27:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:3:9:3:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:5:9:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1626,11 +1628,15 @@ postWithInFlow
|
||||
| cpp11.cpp:60:15:60:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:10:65:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:19:65:45 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:20:65:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:35:65:43 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:77:19:77:21 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:77:19:77:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:11:82:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:11:82:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -3,7 +3,6 @@ edges
|
||||
| tests.cpp:33:34:33:39 | call to getenv | tests.cpp:38:39:38:49 | environment indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | ReturnValue |
|
||||
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:51:12:51:20 | call to badSource | tests.cpp:53:16:53:19 | data indirection |
|
||||
nodes
|
||||
| tests.cpp:26:15:26:23 | ReturnValue | semmle.label | ReturnValue |
|
||||
|
||||
@@ -2,64 +2,55 @@ edges
|
||||
| test.cpp:16:20:16:23 | argv | test.cpp:22:45:22:52 | userName indirection |
|
||||
| test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection |
|
||||
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
|
||||
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
|
||||
| test.cpp:47:21:47:26 | call to getenv | test.cpp:50:35:50:43 | envCflags indirection |
|
||||
| test.cpp:50:11:50:17 | sprintf output argument | test.cpp:51:10:51:16 | command indirection |
|
||||
| test.cpp:50:35:50:43 | envCflags indirection | test.cpp:50:11:50:17 | sprintf output argument |
|
||||
| test.cpp:50:35:50:43 | envCflags indirection | test.cpp:50:11:50:17 | sprintf output argument |
|
||||
| test.cpp:62:9:62:16 | fread output argument | test.cpp:64:20:64:27 | filename indirection |
|
||||
| test.cpp:64:11:64:17 | strncat output argument | test.cpp:65:10:65:16 | command indirection |
|
||||
| test.cpp:64:20:64:27 | filename indirection | test.cpp:64:11:64:17 | strncat output argument |
|
||||
| test.cpp:64:20:64:27 | filename indirection | test.cpp:64:11:64:17 | strncat output argument |
|
||||
| test.cpp:82:9:82:16 | fread output argument | test.cpp:84:20:84:27 | filename indirection |
|
||||
| test.cpp:84:11:84:17 | strncat output argument | test.cpp:85:32:85:38 | command indirection |
|
||||
| test.cpp:84:20:84:27 | filename indirection | test.cpp:84:11:84:17 | strncat output argument |
|
||||
| test.cpp:84:20:84:27 | filename indirection | test.cpp:84:11:84:17 | strncat output argument |
|
||||
| test.cpp:91:9:91:16 | fread output argument | test.cpp:93:17:93:24 | filename indirection |
|
||||
| test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | path indirection |
|
||||
| test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument |
|
||||
| test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument |
|
||||
| test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | path indirection |
|
||||
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection |
|
||||
| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ |
|
||||
| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ |
|
||||
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | path indirection |
|
||||
| test.cpp:114:17:114:17 | Call | test.cpp:114:25:114:29 | call to c_str indirection |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call |
|
||||
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | path indirection |
|
||||
| test.cpp:120:17:120:17 | Call | test.cpp:120:10:120:30 | call to data indirection |
|
||||
| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call |
|
||||
| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call |
|
||||
| test.cpp:140:9:140:11 | fread output argument | test.cpp:142:31:142:33 | str indirection |
|
||||
| test.cpp:142:11:142:17 | sprintf output argument | test.cpp:143:10:143:16 | command indirection |
|
||||
| test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument |
|
||||
| test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:177:20:177:27 | filename indirection |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:178:22:178:26 | flags indirection |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:180:22:180:29 | filename indirection |
|
||||
| test.cpp:177:13:177:17 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:177:20:177:27 | filename indirection | test.cpp:177:13:177:17 | strncat output argument |
|
||||
| test.cpp:177:20:177:27 | filename indirection | test.cpp:177:13:177:17 | strncat output argument |
|
||||
| test.cpp:178:13:178:19 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:178:22:178:26 | flags indirection | test.cpp:178:13:178:19 | strncat output argument |
|
||||
| test.cpp:178:22:178:26 | flags indirection | test.cpp:178:13:178:19 | strncat output argument |
|
||||
| test.cpp:180:13:180:19 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:180:22:180:29 | filename indirection | test.cpp:180:13:180:19 | strncat output argument |
|
||||
| test.cpp:180:22:180:29 | filename indirection | test.cpp:180:13:180:19 | strncat output argument |
|
||||
| test.cpp:186:47:186:54 | *filename | test.cpp:187:18:187:25 | filename indirection |
|
||||
| test.cpp:186:47:186:54 | *filename | test.cpp:188:20:188:24 | flags indirection |
|
||||
| test.cpp:186:47:186:54 | filename | test.cpp:187:18:187:25 | filename indirection |
|
||||
| test.cpp:186:47:186:54 | filename | test.cpp:188:20:188:24 | flags indirection |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
|
||||
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:205:10:205:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:205:10:205:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument |
|
||||
@@ -67,9 +58,21 @@ edges
|
||||
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename |
|
||||
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename indirection |
|
||||
| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection |
|
||||
| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename |
|
||||
| test.cpp:205:10:205:16 | command [post update] | test.cpp:207:32:207:38 | command indirection |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection |
|
||||
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
nodes
|
||||
| test.cpp:16:20:16:23 | argv | semmle.label | argv |
|
||||
| test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument |
|
||||
@@ -115,22 +118,48 @@ nodes
|
||||
| test.cpp:180:13:180:19 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:180:22:180:29 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:186:47:186:54 | *filename | semmle.label | *filename |
|
||||
| test.cpp:186:47:186:54 | filename | semmle.label | filename |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection |
|
||||
| test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection |
|
||||
| test.cpp:194:9:194:16 | fread output argument | semmle.label | fread output argument |
|
||||
| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | semmle.label | filename |
|
||||
| test.cpp:196:26:196:33 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:205:10:205:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:207:32:207:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:218:9:218:16 | fread output argument | semmle.label | fread output argument |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:222:32:222:38 | command indirection | semmle.label | command indirection |
|
||||
subpaths
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
#select
|
||||
| test.cpp:23:12:23:19 | command1 | test.cpp:16:20:16:23 | argv | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:16:20:16:23 | argv | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
|
||||
| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:47:21:47:26 | call to getenv | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument |
|
||||
@@ -146,5 +175,5 @@ subpaths
|
||||
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:174:9:174:16 | fread output argument | user input (String read by fread) | test.cpp:180:13:180:19 | strncat output argument | strncat output argument |
|
||||
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument |
|
||||
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument |
|
||||
| test.cpp:207:32:207:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:207:32:207:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument |
|
||||
| test.cpp:207:32:207:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:207:32:207:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument |
|
||||
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
|
||||
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
|
||||
|
||||
@@ -199,7 +199,7 @@ void test17(FILE *f) {
|
||||
}
|
||||
|
||||
void test18() {
|
||||
// GOOD [FALSE POSITIVE]
|
||||
// GOOD
|
||||
char command[1000] = "ls ", flags[1000] = "-l", filename[1000] = ".";
|
||||
|
||||
concat(command, flags, filename);
|
||||
@@ -207,4 +207,19 @@ void test18() {
|
||||
execl("/bin/sh", "sh", "-c", command);
|
||||
}
|
||||
|
||||
#define CONCAT(COMMAND, FILENAME) \
|
||||
strncat(COMMAND, FILENAME, 1000); \
|
||||
strncat(COMMAND, " ", 1000); \
|
||||
strncat(COMMAND, FILENAME, 1000);
|
||||
|
||||
void test19(FILE *f) {
|
||||
// BAD: the user string is injected directly into a command
|
||||
char command[1000] = "mv ", filename[1000];
|
||||
fread(filename, 1, 1000, f);
|
||||
|
||||
CONCAT(command, filename)
|
||||
|
||||
execl("/bin/sh", "sh", "-c", command);
|
||||
}
|
||||
|
||||
// open question: do we want to report certain sources even when they're the start of the string?
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
edges
|
||||
| tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion |
|
||||
nodes
|
||||
| tests.c:57:21:57:28 | password | semmle.label | password |
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
subpaths
|
||||
#select
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password | password |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -67,6 +67,6 @@ void CWE535_Info_Exposure_Shell_Error__w32_char_01_bad()
|
||||
printLine("Unable to login.");
|
||||
}
|
||||
/* FLAW: Write sensitive data to stderr */
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password); // [NOT DETECTED]
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,26 @@ edges
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:26 | (const char *)... |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:26 | (const char *)... |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:30 | (const char *)... |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | tests2.cpp:109:14:109:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | tests2.cpp:107:3:107:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:107:6:107:8 | ptr [post update] |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | tests2.cpp:109:14:109:19 | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:34 | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | tests2.cpp:111:14:111:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | tests2.cpp:109:3:109:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:109:6:109:8 | ptr [post update] |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | tests2.cpp:111:14:111:19 | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | (const void *)... |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf |
|
||||
nodes
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
@@ -21,27 +32,49 @@ nodes
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:30 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:89:42:89:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:91:14:91:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:100:14:100:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:91:42:91:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:93:14:93:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:102:14:102:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:43:20:43:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:80:20:80:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | semmle.label | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | semmle.label | confstr output argument |
|
||||
| tests_sysconf.cpp:39:19:39:25 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | semmle.label | pathbuf |
|
||||
subpaths
|
||||
#select
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:14:91:17 | str1 | tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 | This operation exposes system data from $@. | tests2.cpp:89:42:89:45 | str1 | str1 |
|
||||
| tests2.cpp:100:14:100:15 | pw | tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw | This operation exposes system data from $@. | tests2.cpp:99:8:99:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:109:14:109:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:107:12:107:17 | call to getenv | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 |
|
||||
| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument |
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
edges
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:86:29:86:31 | msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv indirection |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | tests.cpp:86:29:86:31 | msg |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:86:29:86:31 | *msg |
|
||||
| tests.cpp:107:30:107:32 | *msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:107:30:107:32 | msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:114:30:114:32 | msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:122:30:122:32 | msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv indirection |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | tests.cpp:107:30:107:32 | msg |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | tests.cpp:107:30:107:32 | *msg |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | tests.cpp:114:30:114:32 | msg |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | tests.cpp:114:30:114:32 | *msg |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | tests.cpp:122:30:122:32 | msg |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:122:30:122:32 | *msg |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd |
|
||||
nodes
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:86:29:86:31 | msg | semmle.label | msg |
|
||||
| tests.cpp:88:15:88:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:107:30:107:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:107:30:107:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:111:15:111:17 | tmp | semmle.label | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:114:30:114:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:122:30:122:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:124:15:124:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | semmle.label | call to getpwnam |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | semmle.label | pwd |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | semmle.label | pwd |
|
||||
subpaths
|
||||
#select
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:88:15:88:17 | msg | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:88:15:88:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:111:15:111:17 | tmp | tests.cpp:131:14:131:19 | call to getenv | tests.cpp:111:15:111:17 | tmp | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | tests.cpp:132:14:132:19 | call to getenv | tests.cpp:119:7:119:12 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:132:14:132:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:124:15:124:17 | msg | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:124:15:124:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -0,0 +1,134 @@
|
||||
// test cases for rule CWE-497
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
typedef struct {} FILE;
|
||||
FILE *stdout;
|
||||
|
||||
int puts(const char *s);
|
||||
int printf(const char *format, ...);
|
||||
int sprintf(char *s, const char *format, ...);
|
||||
int snprintf(char *s, size_t n, const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
extern std::ostream someotherostream;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define NULL (0)
|
||||
|
||||
// test cases
|
||||
|
||||
void test1()
|
||||
{
|
||||
std::ostream cout_copy = std::cout;
|
||||
|
||||
std::cout << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cerr << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::clog << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
someotherostream << getenv("SECRET_TOKEN"); // GOOD: not output
|
||||
cout_copy << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
|
||||
std::cout << getenv("USERPROFILE"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
std::cout << getenv("PATH"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
|
||||
std::cout.write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
(std::cout << "SECRET_TOKEN = ").write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cout.write("SECRET_TOKEN = ", 7) << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
}
|
||||
|
||||
char *global_token = getenv("SECRET_TOKEN");
|
||||
char *global_other = "Hello, world!";
|
||||
|
||||
void test2(bool cond)
|
||||
{
|
||||
char *maybe;
|
||||
|
||||
maybe = cond ? global_token : global_other;
|
||||
|
||||
printf("token = '%s'\n", global_token); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
printf("other = '%s'\n", global_other);
|
||||
printf("maybe = '%s'\n", maybe); // BAD: may output SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test3()
|
||||
{
|
||||
char *path_string = getenv("PATH");
|
||||
char buf[4096];
|
||||
|
||||
// ...
|
||||
snprintf(buf, 4096, "invalid path '%s'\n", path_string);
|
||||
puts(buf); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void myOutputFn(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOtherFn(const char *msg)
|
||||
{
|
||||
}
|
||||
|
||||
void test4()
|
||||
{
|
||||
myOutputFn(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOtherFn(getenv("SECRET_TOKEN")); // GOOD: does not output anything.
|
||||
}
|
||||
|
||||
void myOutputFn2(const char *msg)
|
||||
{
|
||||
msg = "";
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOutputFn3(const char *msg)
|
||||
{
|
||||
const char *tmp = msg;
|
||||
|
||||
printf("%s", tmp);
|
||||
}
|
||||
|
||||
void myOutputFn4(const char *msg)
|
||||
{
|
||||
char buffer[4096];
|
||||
|
||||
sprintf(buffer, "log: %s\n", msg);
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
void myOutputFn5(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
msg = "";
|
||||
}
|
||||
|
||||
void test5()
|
||||
{
|
||||
myOutputFn2(getenv("SECRET_TOKEN")); // GOOD: myOutputFn2 doesn't actually output the parameter
|
||||
myOutputFn3(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn4(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn5(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
typedef size_t streamsize;
|
||||
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
};
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
extern ostream clog;
|
||||
}
|
||||
@@ -2,24 +2,24 @@
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
char *getenv(const char *name);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
extern ostream cout;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int socket(int p1, int p2, int p3);
|
||||
void send(int sock, const char *buffer, int p3, int p4);
|
||||
@@ -63,10 +63,12 @@ void test1()
|
||||
send(sock, getenv("HOME"), val(), val()); // BAD
|
||||
send(sock, getenv("PATH"), val(), val()); // BAD
|
||||
send(sock, getenv("USERNAME"), val(), val()); // BAD
|
||||
send(sock, getenv("APP_PASSWORD"), val(), val()); // BAD
|
||||
send(sock, getenv("HARMLESS"), val(), val()); // GOOD: harmless information
|
||||
send(sock, "HOME", val(), val()); // GOOD: not system data
|
||||
send(sock, "PATH", val(), val()); // GOOD: not system data
|
||||
send(sock, "USERNAME", val(), val()); // GOOD: not system data
|
||||
send(sock, "APP_PASSWORD", val(), val()); // GOOD: not system data
|
||||
send(sock, "HARMLESS", val(), val()); // GOOD: not system data
|
||||
|
||||
// tests for `mysql_get_client_info`, including via a global
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
struct passwd {
|
||||
char *pw_passwd;
|
||||
char *pw_dir;
|
||||
// ...
|
||||
};
|
||||
|
||||
struct passwd *getpwnam(const char *name);
|
||||
|
||||
void test6(char *username)
|
||||
{
|
||||
passwd *pwd;
|
||||
|
||||
pwd = getpwnam(username);
|
||||
|
||||
printf("pw_passwd = %s\n", pwd->pw_passwd); // BAD
|
||||
printf("pw_dir = %s\n", pwd->pw_dir); // BAD
|
||||
printf("sizeof(passwd) = %i\n", sizeof(passwd)); // GOOD
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
#define AF_INET (2)
|
||||
#define SOCK_STREAM (1)
|
||||
|
||||
struct sockaddr {
|
||||
int sa_family;
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
int socket(int domain, int type, int protocol);
|
||||
int connect(int socket, const struct sockaddr *address, size_t address_len);
|
||||
size_t send(int socket, const void *buffer, size_t length, int flags);
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
void test_sockets1()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
|
||||
int mksocket()
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void test_sockets2()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = mksocket();
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
void *malloc(size_t size);
|
||||
#define NULL (0)
|
||||
|
||||
int printf(const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
int get_fd();
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
long sysconf(int name);
|
||||
#define _SC_CHILD_MAX (2)
|
||||
|
||||
size_t confstr(int name, char *buffer, size_t length);
|
||||
#define _CS_PATH (1)
|
||||
|
||||
void test_sc_1()
|
||||
{
|
||||
int value = sysconf(_SC_CHILD_MAX);
|
||||
|
||||
printf("_SC_CHILD_MAX = %i\n", _SC_CHILD_MAX); // GOOD
|
||||
printf("_SC_CHILD_MAX = %i\n", value); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_sc_2()
|
||||
{
|
||||
char *pathbuf;
|
||||
size_t n;
|
||||
|
||||
n = confstr(_CS_PATH, NULL, (size_t)0);
|
||||
pathbuf = (char *)malloc(n);
|
||||
if (pathbuf != NULL)
|
||||
{
|
||||
confstr(_CS_PATH, pathbuf, n);
|
||||
|
||||
printf("path: %s", pathbuf); // BAD [NOT DETECTED]
|
||||
write(get_fd(), pathbuf, strlen(pathbuf)); // BAD
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Provides classes for collections. */
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.Collections
|
||||
|
||||
private string modifyMethodName() {
|
||||
result =
|
||||
@@ -66,6 +67,12 @@ class CollectionType extends RefType {
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `t` is a collection type. */
|
||||
predicate isCollectionType(ValueOrRefType t) {
|
||||
t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and
|
||||
not t instanceof StringType
|
||||
}
|
||||
|
||||
/** An object creation that creates an empty collection. */
|
||||
class EmptyCollectionCreation extends ObjectCreation {
|
||||
EmptyCollectionCreation() {
|
||||
|
||||
@@ -105,31 +105,12 @@ private module ConstantComparisonOperation {
|
||||
}
|
||||
}
|
||||
|
||||
private class StructuralComparisonConfig extends StructuralComparison::StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() { this = "CompareIdenticalValues" }
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(ComparisonTest ct |
|
||||
x = ct.getFirstArgument() and
|
||||
y = ct.getSecondArgument()
|
||||
)
|
||||
}
|
||||
|
||||
ComparisonTest getComparisonTest() {
|
||||
exists(Element x, Element y |
|
||||
result.getFirstArgument() = x and
|
||||
result.getSecondArgument() = y and
|
||||
same(x, y)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if comparison test `ct` compares two structurally identical
|
||||
* expressions.
|
||||
*/
|
||||
predicate comparesIdenticalValues(ComparisonTest ct) {
|
||||
ct = any(StructuralComparisonConfig c).getComparisonTest()
|
||||
StructuralComparison::sameGvn(ct.getFirstArgument(), ct.getSecondArgument())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -192,13 +192,18 @@ private import Cached
|
||||
|
||||
predicate toGvn = toGvnCached/1;
|
||||
|
||||
/**
|
||||
* Holds if the control flow elements `x` and `y` are structurally equal.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
|
||||
predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
|
||||
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
|
||||
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `sameGvn` instead.
|
||||
*
|
||||
* A configuration for performing structural comparisons of program elements
|
||||
* (expressions and statements).
|
||||
*
|
||||
@@ -207,7 +212,7 @@ private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
|
||||
*
|
||||
* Each use of the library is identified by a unique string value.
|
||||
*/
|
||||
abstract class StructuralComparisonConfiguration extends string {
|
||||
abstract deprecated class StructuralComparisonConfiguration extends string {
|
||||
bindingset[this]
|
||||
StructuralComparisonConfiguration() { any() }
|
||||
|
||||
@@ -235,55 +240,3 @@ abstract class StructuralComparisonConfiguration extends string {
|
||||
*/
|
||||
predicate same(ControlFlowElement x, ControlFlowElement y) { candidate(x, y) and sameGvn(x, y) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A verbatim copy of the class `StructuralComparisonConfiguration` for internal
|
||||
* use.
|
||||
*
|
||||
* A copy is needed in order to use structural comparison within the standard
|
||||
* library without running into caching issues.
|
||||
*/
|
||||
module Internal {
|
||||
// Import all uses of the internal library to make sure caching works
|
||||
private import semmle.code.csharp.controlflow.Guards as G
|
||||
|
||||
/**
|
||||
* A configuration for performing structural comparisons of program elements
|
||||
* (expressions and statements).
|
||||
*
|
||||
* The predicate `candidate()` must be overridden, in order to identify the
|
||||
* elements for which to perform structural comparison.
|
||||
*
|
||||
* Each use of the library is identified by a unique string value.
|
||||
*/
|
||||
abstract class InternalStructuralComparisonConfiguration extends string {
|
||||
bindingset[this]
|
||||
InternalStructuralComparisonConfiguration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if elements `x` and `y` are candidates for testing structural
|
||||
* equality.
|
||||
*
|
||||
* Subclasses are expected to override this predicate to identify the
|
||||
* top-level elements which they want to compare. Care should be
|
||||
* taken to avoid identifying too many pairs of elements, as in general
|
||||
* there are very many structurally equal subtrees in a program, and
|
||||
* in order to keep the computation feasible we must focus attention.
|
||||
*
|
||||
* Note that this relation is not expected to be symmetric -- it's
|
||||
* fine to include a pair `(x, y)` but not `(y, x)`.
|
||||
* In fact, not including the symmetrically implied fact will save
|
||||
* half the computation time on the structural comparison.
|
||||
*/
|
||||
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
|
||||
|
||||
/**
|
||||
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
|
||||
* flagged as candidates for structural equality, that is,
|
||||
* `candidate(x, y)` must hold.
|
||||
*/
|
||||
predicate same(ControlFlowElement x, ControlFlowElement y) { candidate(x, y) and sameGvn(x, y) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ private import dotnet
|
||||
private import ControlFlow::SuccessorTypes
|
||||
private import semmle.code.csharp.commons.Assertions
|
||||
private import semmle.code.csharp.commons.ComparisonTest
|
||||
private import semmle.code.csharp.commons.StructuralComparison::Internal
|
||||
private import semmle.code.csharp.commons.StructuralComparison as SC
|
||||
private import semmle.code.csharp.controlflow.BasicBlocks
|
||||
private import semmle.code.csharp.controlflow.internal.Completion
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
@@ -1798,32 +1798,30 @@ module Internal {
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class for calculating structurally equal access/call expressions.
|
||||
* Holds if access/call expression `e` (targeting declaration `target`)
|
||||
* is a sub expression of a guard that controls whether basic block
|
||||
* `bb` is reached.
|
||||
*/
|
||||
private class ConditionOnExprComparisonConfig extends InternalStructuralComparisonConfiguration {
|
||||
ConditionOnExprComparisonConfig() { this = "ConditionOnExprComparisonConfig" }
|
||||
pragma[noinline]
|
||||
private predicate candidateAux(AccessOrCallExpr e, Declaration target, BasicBlock bb) {
|
||||
target = e.getTarget() and
|
||||
guardControlsSub(_, bb, e)
|
||||
}
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(BasicBlock bb, Declaration d |
|
||||
this.candidateAux(x, d, bb) and
|
||||
y =
|
||||
any(AccessOrCallExpr e |
|
||||
e.getAControlFlowNode().getBasicBlock() = bb and
|
||||
e.getTarget() = d
|
||||
)
|
||||
)
|
||||
}
|
||||
private predicate candidate(AccessOrCallExpr x, AccessOrCallExpr y) {
|
||||
exists(BasicBlock bb, Declaration d |
|
||||
candidateAux(x, d, bb) and
|
||||
y =
|
||||
any(AccessOrCallExpr e |
|
||||
e.getAControlFlowNode().getBasicBlock() = bb and
|
||||
e.getTarget() = d
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if access/call expression `e` (targeting declaration `target`)
|
||||
* is a sub expression of a guard that controls whether basic block
|
||||
* `bb` is reached.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate candidateAux(AccessOrCallExpr e, Declaration target, BasicBlock bb) {
|
||||
target = e.getTarget() and
|
||||
guardControlsSub(_, bb, e)
|
||||
}
|
||||
private predicate same(AccessOrCallExpr x, AccessOrCallExpr y) {
|
||||
candidate(x, y) and
|
||||
SC::sameGvn(x, y)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -1849,7 +1847,7 @@ module Internal {
|
||||
pragma[nomagic]
|
||||
private predicate guardControlsSubSame(Guard g, BasicBlock bb, ControlGuardDescendant sub) {
|
||||
guardControlsSub(g, bb, sub) and
|
||||
any(ConditionOnExprComparisonConfig c).same(sub, _)
|
||||
same(sub, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1862,7 +1860,7 @@ module Internal {
|
||||
guardedBB = guardedCfn.getBasicBlock() and
|
||||
guardControls(g, guardedBB, v) and
|
||||
guardControlsSubSame(g, guardedBB, sub) and
|
||||
any(ConditionOnExprComparisonConfig c).same(sub, guarded)
|
||||
same(sub, guarded)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -2031,3 +2031,47 @@ abstract class SyntheticField extends string {
|
||||
* Holds if the the content `c` is a container.
|
||||
*/
|
||||
predicate containerContent(DataFlow::Content c) { c instanceof DataFlow::ElementContent }
|
||||
|
||||
/**
|
||||
* A module containing predicates related to generating models as data.
|
||||
*/
|
||||
module Csv {
|
||||
private string parameterQualifiedTypeNamesToString(DataFlowCallable c) {
|
||||
result =
|
||||
concat(Parameter p, int i |
|
||||
p = c.getParameter(i)
|
||||
|
|
||||
p.getType().getQualifiedName(), "," order by i
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the summary should apply for all overrides of `c`. */
|
||||
predicate isBaseCallableOrPrototype(DataFlowCallable c) {
|
||||
c.getDeclaringType() instanceof Interface
|
||||
or
|
||||
exists(Modifiable m | m = [c.(Modifiable), c.(Accessor).getDeclaration()] |
|
||||
m.isAbstract()
|
||||
or
|
||||
c.getDeclaringType().(Modifiable).isAbstract() and m.(Virtualizable).isVirtual()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a string representing whether the summary should apply for all overrides of `c`. */
|
||||
private string getCallableOverride(DataFlowCallable c) {
|
||||
if isBaseCallableOrPrototype(c) then result = "true" else result = "false"
|
||||
}
|
||||
|
||||
/** Computes the first 6 columns for CSV rows of `c`. */
|
||||
string asPartialModel(DataFlowCallable c) {
|
||||
exists(string namespace, string type |
|
||||
c.getDeclaringType().hasQualifiedName(namespace, type) and
|
||||
result =
|
||||
namespace + ";" //
|
||||
+ type + ";" //
|
||||
+ getCallableOverride(c) + ";" //
|
||||
+ c.getName() + ";" //
|
||||
+ "(" + parameterQualifiedTypeNamesToString(c) + ")" //
|
||||
+ /* ext + */ ";" //
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1056,7 +1056,7 @@ module Private {
|
||||
|
|
||||
c.relevantSummary(input, output, preservesValue) and
|
||||
csv =
|
||||
c.getCallableCsv() + ";;" + getComponentStackCsv(input) + ";" +
|
||||
c.getCallableCsv() + ";" + getComponentStackCsv(input) + ";" +
|
||||
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,24 +14,12 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class DoubleCheckedLock extends StructuralComparisonConfiguration {
|
||||
DoubleCheckedLock() { this = "double checked lock" }
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock |
|
||||
x = unlockedIf.getCondition() and
|
||||
y = lockedIf.getCondition() and
|
||||
lock = unlockedIf.getThen().stripSingletonBlocks() and
|
||||
lockedIf.getParent*() = lock.getBlock()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
predicate doubleCheckedLock(Field field, IfStmt ifs) {
|
||||
exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | ifs.getCondition() = eq1 |
|
||||
lock = ifs.getThen().stripSingletonBlocks() and
|
||||
config.same(eq1, eq2) and
|
||||
field.getAnAccess() = eq1.getAChildExpr*()
|
||||
predicate doubleCheckedLock(Field field, IfStmt unlockedIf) {
|
||||
exists(LockStmt lock, IfStmt lockedIf |
|
||||
lock = unlockedIf.getThen().stripSingletonBlocks() and
|
||||
lockedIf.getParent*() = lock.getBlock() and
|
||||
sameGvn(unlockedIf.getCondition(), lockedIf.getCondition()) and
|
||||
field.getAnAccess() = unlockedIf.getCondition().getAChildExpr*()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,25 +12,8 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() { this = "MissedTernaryOpportunity" }
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(IfStmt is, AssignExpr ae1 |
|
||||
ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr()
|
||||
|
|
||||
x = ae1.getLValue() and
|
||||
exists(AssignExpr ae2 | ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
y = ae2.getLValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
IfStmt getIfStmt() {
|
||||
exists(AssignExpr ae | ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
same(ae.getLValue(), _)
|
||||
)
|
||||
}
|
||||
private Expr getAssignedExpr(Stmt stmt) {
|
||||
result = stmt.stripSingletonBlocks().(ExprStmt).getExpr().(AssignExpr).getLValue()
|
||||
}
|
||||
|
||||
from IfStmt is, string what
|
||||
@@ -40,10 +23,8 @@ where
|
||||
is.getElse().stripSingletonBlocks() instanceof ReturnStmt and
|
||||
what = "return"
|
||||
or
|
||||
exists(StructuralComparisonConfig c |
|
||||
is = c.getIfStmt() and
|
||||
what = "write to the same variable"
|
||||
)
|
||||
sameGvn(getAssignedExpr(is.getThen()), getAssignedExpr(is.getElse())) and
|
||||
what = "write to the same variable"
|
||||
) and
|
||||
not exists(IfStmt other | is = other.getElse())
|
||||
select is,
|
||||
|
||||
@@ -13,35 +13,26 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() { this = "UselessIsBeforeAs" }
|
||||
private predicate candidate(AsExpr ae, IsExpr ie) {
|
||||
exists(IfStmt is, TypeAccessPatternExpr tape |
|
||||
ie = is.getCondition().getAChild*() and
|
||||
tape = ie.getPattern() and
|
||||
ae.getTargetType() = tape.getTarget()
|
||||
|
|
||||
ae = is.getThen().getAChild*()
|
||||
or
|
||||
ae = is.getElse().getAChild*()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(IfStmt is, AsExpr ae, IsExpr ie, TypeAccessPatternExpr tape |
|
||||
ie = is.getCondition().getAChild*() and
|
||||
tape = ie.getPattern() and
|
||||
ae.getTargetType() = tape.getTarget() and
|
||||
x = ie.getExpr() and
|
||||
y = ae.getExpr()
|
||||
|
|
||||
ae = is.getThen().getAChild*()
|
||||
or
|
||||
ae = is.getElse().getAChild*()
|
||||
)
|
||||
}
|
||||
|
||||
predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) {
|
||||
exists(Expr x, Expr y |
|
||||
same(x, y) and
|
||||
ie.getExpr() = x and
|
||||
ae.getExpr() = y
|
||||
)
|
||||
}
|
||||
private predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) {
|
||||
candidate(ae, ie) and
|
||||
sameGvn(ie.getExpr(), ae.getExpr())
|
||||
}
|
||||
|
||||
from AsExpr ae, IsExpr ie
|
||||
where
|
||||
exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) and
|
||||
uselessIsBeforeAs(ae, ie) and
|
||||
not exists(MethodCall mc | ae = mc.getAnArgument().getAChildExpr*())
|
||||
select ae,
|
||||
"This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.",
|
||||
|
||||
@@ -14,24 +14,22 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() { this = "UselessNullCoalescingExpression" }
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(NullCoalescingExpr nce |
|
||||
x.(Access) = nce.getLeftOperand() and
|
||||
y.(Access) = nce.getRightOperand().getAChildExpr*()
|
||||
)
|
||||
}
|
||||
|
||||
NullCoalescingExpr getUselessNullCoalescingExpr() {
|
||||
exists(AssignableAccess x |
|
||||
result.getLeftOperand() = x and
|
||||
forex(AssignableAccess y | same(x, y) | y instanceof AssignableRead and not y.isRefArgument())
|
||||
)
|
||||
}
|
||||
pragma[noinline]
|
||||
private predicate same(AssignableAccess x, AssignableAccess y) {
|
||||
exists(NullCoalescingExpr nce |
|
||||
x = nce.getLeftOperand() and
|
||||
y = nce.getRightOperand().getAChildExpr*()
|
||||
) and
|
||||
sameGvn(x, y)
|
||||
}
|
||||
|
||||
from StructuralComparisonConfig c, NullCoalescingExpr nce
|
||||
where nce = c.getUselessNullCoalescingExpr()
|
||||
private predicate uselessNullCoalescingExpr(NullCoalescingExpr nce) {
|
||||
exists(AssignableAccess x |
|
||||
nce.getLeftOperand() = x and
|
||||
forex(AssignableAccess y | same(x, y) | y instanceof AssignableRead and not y.isRefArgument())
|
||||
)
|
||||
}
|
||||
|
||||
from NullCoalescingExpr nce
|
||||
where uselessNullCoalescingExpr(nce)
|
||||
select nce, "Both operands of this null-coalescing expression access the same variable or property."
|
||||
|
||||
@@ -15,18 +15,6 @@ import csharp
|
||||
import semmle.code.csharp.commons.ComparisonTest
|
||||
import semmle.code.csharp.commons.StructuralComparison as SC
|
||||
|
||||
/** A structural comparison configuration for comparing the conditions of nested `for` loops. */
|
||||
class NestedForConditions extends SC::StructuralComparisonConfiguration {
|
||||
NestedForConditions() { this = "Compare nested for conditions" }
|
||||
|
||||
override predicate candidate(ControlFlowElement e1, ControlFlowElement e2) {
|
||||
exists(NestedForLoopSameVariable nested |
|
||||
e1 = nested.getInnerForStmt().getCondition() and
|
||||
e2 = nested.getOuterForStmt().getCondition()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate hasChild(Stmt outer, Element child) {
|
||||
outer = child.getParent() and
|
||||
(outer instanceof ForStmt or outer = any(ForStmt f).getBody())
|
||||
@@ -61,9 +49,7 @@ class NestedForLoopSameVariable extends ForStmt {
|
||||
}
|
||||
|
||||
private predicate haveSameCondition() {
|
||||
exists(NestedForConditions config |
|
||||
config.same(this.getInnerForStmt().getCondition(), this.getOuterForStmt().getCondition())
|
||||
)
|
||||
SC::sameGvn(this.getInnerForStmt().getCondition(), this.getOuterForStmt().getCondition())
|
||||
}
|
||||
|
||||
private predicate haveSameUpdate() {
|
||||
|
||||
@@ -13,37 +13,25 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() { this = "SelfAssignment" }
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(AssignExpr ae |
|
||||
// Member initializers are never self-assignments, in particular
|
||||
// not initializers such as `new C { F = F };`
|
||||
not ae instanceof MemberInitializer and
|
||||
// Enum field initializers are never self assignments. `enum E { A = 42 }`
|
||||
not ae.getParent().(Field).getDeclaringType() instanceof Enum
|
||||
|
|
||||
ae.getLValue() = x and
|
||||
ae.getRValue() = y
|
||||
) and
|
||||
forall(Expr e | e = x.(Expr).getAChildExpr*() |
|
||||
// Non-trivial property accesses may have side-effects,
|
||||
// so these are not considered
|
||||
e instanceof PropertyAccess implies e instanceof TrivialPropertyAccess
|
||||
)
|
||||
}
|
||||
|
||||
AssignExpr getSelfAssignExpr() {
|
||||
exists(Expr x, Expr y |
|
||||
same(x, y) and
|
||||
result.getLValue() = x and
|
||||
result.getRValue() = y
|
||||
)
|
||||
}
|
||||
private predicate candidate(AssignExpr ae) {
|
||||
// Member initializers are never self-assignments, in particular
|
||||
// not initializers such as `new C { F = F };`
|
||||
not ae instanceof MemberInitializer and
|
||||
// Enum field initializers are never self assignments. `enum E { A = 42 }`
|
||||
not ae.getParent().(Field).getDeclaringType() instanceof Enum and
|
||||
forall(Expr e | e = ae.getLValue().getAChildExpr*() |
|
||||
// Non-trivial property accesses may have side-effects,
|
||||
// so these are not considered
|
||||
e instanceof PropertyAccess implies e instanceof TrivialPropertyAccess
|
||||
)
|
||||
}
|
||||
|
||||
Declaration getDeclaration(Expr e) {
|
||||
private predicate selfAssignExpr(AssignExpr ae) {
|
||||
candidate(ae) and
|
||||
sameGvn(ae.getLValue(), ae.getRValue())
|
||||
}
|
||||
|
||||
private Declaration getDeclaration(Expr e) {
|
||||
result = e.(VariableAccess).getTarget()
|
||||
or
|
||||
result = e.(MemberAccess).getTarget()
|
||||
@@ -51,6 +39,6 @@ Declaration getDeclaration(Expr e) {
|
||||
result = getDeclaration(e.(ArrayAccess).getQualifier())
|
||||
}
|
||||
|
||||
from StructuralComparisonConfig c, AssignExpr ae, Declaration target
|
||||
where ae = c.getSelfAssignExpr() and target = getDeclaration(ae.getLValue())
|
||||
from AssignExpr ae, Declaration target
|
||||
where selfAssignExpr(ae) and target = getDeclaration(ae.getLValue())
|
||||
select ae, "This assignment assigns $@ to itself.", target, target.getName()
|
||||
|
||||
@@ -13,19 +13,14 @@ import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
import semmle.code.csharp.controlflow.Guards as G
|
||||
|
||||
class SameElement extends StructuralComparisonConfiguration {
|
||||
SameElement() { this = "Same element" }
|
||||
|
||||
override predicate candidate(ControlFlowElement e1, ControlFlowElement e2) {
|
||||
exists(MethodCall mc, IndexerRead access |
|
||||
mc.getTarget().hasName("ContainsKey") and
|
||||
access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _) and
|
||||
e1 = mc.getArgument(0) and
|
||||
e2 = access.getIndex(0)
|
||||
)
|
||||
}
|
||||
pragma[noinline]
|
||||
private predicate candidate(MethodCall mc, IndexerRead access) {
|
||||
mc.getTarget().hasName("ContainsKey") and
|
||||
access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _)
|
||||
}
|
||||
|
||||
from SameElement element, MethodCall call, IndexerAccess index
|
||||
where element.same(call.getArgument(0), index.getIndex(0))
|
||||
from MethodCall call, IndexerRead index
|
||||
where
|
||||
candidate(call, index) and
|
||||
sameGvn(call.getArgument(0), index.getIndex(0))
|
||||
select call, "Inefficient use of 'ContainsKey' and $@.", index, "indexer"
|
||||
|
||||
@@ -161,8 +161,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +206,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,8 +161,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +206,13 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.csharp.commons.Util
|
||||
private import semmle.code.csharp.commons.Collections
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
|
||||
private predicate isRelevantForModels(Callable api) { not api instanceof MainMethod }
|
||||
|
||||
/**
|
||||
* A class of Callables that are relevant for generating summary, source and sinks models for.
|
||||
* A class of callables that are relevant generating summary, source and sinks models for.
|
||||
*
|
||||
* In the Standard library and 3rd party libraries it the Callables that can be called
|
||||
* In the Standard library and 3rd party libraries it the callables that can be called
|
||||
* from outside the library itself.
|
||||
*/
|
||||
class TargetApi extends Callable {
|
||||
class TargetApi extends DataFlowCallable {
|
||||
TargetApi() {
|
||||
[this.(Modifiable), this.(Accessor).getDeclaration()].isEffectivelyPublic() and
|
||||
this.fromSource() and
|
||||
@@ -20,44 +21,7 @@ class TargetApi extends Callable {
|
||||
}
|
||||
}
|
||||
|
||||
private string parameterQualifiedTypeNamesToString(TargetApi api) {
|
||||
result =
|
||||
concat(Parameter p, int i |
|
||||
p = api.getParameter(i)
|
||||
|
|
||||
p.getType().getQualifiedName(), "," order by i
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the summary should apply for all overrides of this. */
|
||||
private predicate isBaseCallableOrPrototype(TargetApi api) {
|
||||
api.getDeclaringType() instanceof Interface
|
||||
or
|
||||
exists(Modifiable m | m = [api.(Modifiable), api.(Accessor).getDeclaration()] |
|
||||
m.isAbstract()
|
||||
or
|
||||
api.getDeclaringType().(Modifiable).isAbstract() and m.(Virtualizable).isVirtual()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a string representing whether the summary should apply for all overrides of this. */
|
||||
private string getCallableOverride(TargetApi api) {
|
||||
if isBaseCallableOrPrototype(api) then result = "true" else result = "false"
|
||||
}
|
||||
|
||||
/** Computes the first 6 columns for CSV rows. */
|
||||
string asPartialModel(TargetApi api) {
|
||||
exists(string namespace, string type |
|
||||
api.getDeclaringType().hasQualifiedName(namespace, type) and
|
||||
result =
|
||||
namespace + ";" //
|
||||
+ type + ";" //
|
||||
+ getCallableOverride(api) + ";" //
|
||||
+ api.getName() + ";" //
|
||||
+ "(" + parameterQualifiedTypeNamesToString(api) + ")" //
|
||||
+ /* ext + */ ";" //
|
||||
)
|
||||
}
|
||||
predicate asPartialModel = Csv::asPartialModel/1;
|
||||
|
||||
/**
|
||||
* Holds for type `t` for fields that are relevant as an intermediate
|
||||
@@ -65,14 +29,8 @@ string asPartialModel(TargetApi api) {
|
||||
*/
|
||||
predicate isRelevantType(Type t) { not t instanceof Enum }
|
||||
|
||||
private predicate isPrimitiveTypeUsedForBulkData(Type t) {
|
||||
t.getName().regexpMatch("byte|char|Byte|Char")
|
||||
}
|
||||
|
||||
private string parameterAccess(Parameter p) {
|
||||
if
|
||||
p.getType() instanceof ArrayType and
|
||||
not isPrimitiveTypeUsedForBulkData(p.getType().(ArrayType).getElementType())
|
||||
if isCollectionType(p.getType())
|
||||
then result = "Argument[" + p.getPosition() + "].Element"
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import shared.FlowSummaries
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate::Csv
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable {
|
||||
@@ -14,7 +15,7 @@ class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable {
|
||||
) {
|
||||
this.propagatesFlow(input, output, preservesValue) and
|
||||
not exists(IncludeSummarizedCallable rsc |
|
||||
rsc.isBaseCallableOrPrototype() and
|
||||
isBaseCallableOrPrototype(rsc) and
|
||||
rsc.propagatesFlow(input, output, preservesValue) and
|
||||
this.(UnboundCallable).overridesOrImplementsUnbound(rsc)
|
||||
)
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
private class StructuralComparisonTest extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonTest() { this = "StructuralComparisonTest" }
|
||||
|
||||
/**
|
||||
* All pairs of controls flow elements found in the source and within the same
|
||||
* enclosing callable excluding all instances of `ThisAccess` to reduce the size
|
||||
* of the output.
|
||||
*/
|
||||
override predicate candidate(ControlFlowElement e1, ControlFlowElement e2) {
|
||||
e1.fromSource() and
|
||||
e2.fromSource() and
|
||||
e1 != e2 and
|
||||
e1.getEnclosingCallable() = e2.getEnclosingCallable() and
|
||||
not e1 instanceof ThisAccess
|
||||
}
|
||||
/**
|
||||
* All pairs of controls flow elements found in the source and within the same
|
||||
* enclosing callable excluding all instances of `ThisAccess` to reduce the size
|
||||
* of the output.
|
||||
*/
|
||||
private predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
x.fromSource() and
|
||||
y.fromSource() and
|
||||
x != y and
|
||||
x.getEnclosingCallable() = y.getEnclosingCallable() and
|
||||
not x instanceof ThisAccess
|
||||
}
|
||||
|
||||
query predicate same(ControlFlowElement e1, ControlFlowElement e2) {
|
||||
exists(StructuralComparisonTest sct, Location l1, Location l2 |
|
||||
sct.same(e1, e2) and
|
||||
l1 = e1.getLocation() and
|
||||
l2 = e2.getLocation() and
|
||||
query predicate same(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(Location l1, Location l2 |
|
||||
candidate(x, y) and
|
||||
sameGvn(x, y) and
|
||||
l1 = x.getLocation() and
|
||||
l2 = y.getLocation() and
|
||||
(
|
||||
l1.getStartLine() < l2.getStartLine()
|
||||
or
|
||||
@@ -31,4 +28,4 @@ query predicate same(ControlFlowElement e1, ControlFlowElement e2) {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate gvn(ControlFlowElement e, Gvn gvn) { gvn = toGvn(e) and e.fromSource() }
|
||||
query predicate gvn(ControlFlowElement x, Gvn gvn) { gvn = toGvn(x) and x.fromSource() }
|
||||
|
||||
@@ -1,44 +1,12 @@
|
||||
import semmle.code.csharp.dataflow.FlowSummary
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl::Private::TestOutput
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
|
||||
abstract class IncludeSummarizedCallable extends RelevantSummarizedCallable {
|
||||
IncludeSummarizedCallable() {
|
||||
[this.(Modifiable), this.(Accessor).getDeclaration()].isEffectivelyPublic()
|
||||
}
|
||||
|
||||
/** Gets the qualified parameter types of this callable as a comma-separated string. */
|
||||
private string parameterQualifiedTypeNamesToString() {
|
||||
result =
|
||||
concat(Parameter p, int i |
|
||||
p = this.getParameter(i)
|
||||
|
|
||||
p.getType().getQualifiedName(), "," order by i
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the summary should apply for all overrides of this. */
|
||||
predicate isBaseCallableOrPrototype() {
|
||||
this.getDeclaringType() instanceof Interface
|
||||
or
|
||||
exists(Modifiable m | m = [this.(Modifiable), this.(Accessor).getDeclaration()] |
|
||||
m.isAbstract()
|
||||
or
|
||||
this.getDeclaringType().(Modifiable).isAbstract() and m.(Virtualizable).isVirtual()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a string representing whether the summary should apply for all overrides of this. */
|
||||
private string getCallableOverride() {
|
||||
if this.isBaseCallableOrPrototype() then result = "true" else result = "false"
|
||||
}
|
||||
|
||||
/** Gets a string representing the callable in semi-colon separated format for use in flow summaries. */
|
||||
final override string getCallableCsv() {
|
||||
exists(string namespace, string type |
|
||||
this.getDeclaringType().hasQualifiedName(namespace, type) and
|
||||
result =
|
||||
namespace + ";" + type + ";" + this.getCallableOverride() + ";" + this.getName() + ";" + "("
|
||||
+ this.parameterQualifiedTypeNamesToString() + ")"
|
||||
)
|
||||
}
|
||||
final override string getCallableCsv() { result = Csv::asPartialModel(this) }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
| Summaries;BasicFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
|
||||
| Summaries;BasicFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
|
||||
| NoSummaries;PublicClassFlow;false;PublicReturn;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BaseClassFlow;true;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnField;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam0;(System.String,System.Object);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam1;(System.String,System.Object);Argument[1];ReturnValue;taint |
|
||||
@@ -9,3 +8,23 @@
|
||||
| Summaries;BasicFlow;false;ReturnSubstring;(System.String);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnThis;(System.Object);Argument[Qualifier];ReturnValue;value |
|
||||
| Summaries;BasicFlow;false;SetField;(System.String);Argument[0];Argument[Qualifier];taint |
|
||||
| Summaries;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);Argument[1];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnFieldInAList;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.Int32,System.Int32);Argument[1];ReturnValue;taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.Int32,System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;GenericFlow<>;false;AddToGenericList<>;(System.Collections.Generic.List<S>,S);Argument[1];Argument[0].Element;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnFieldInGenericList;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericElement<>;(System.Collections.Generic.List<S>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericField;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericParam<>;(S);Argument[0];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;SetGenericField;(T);Argument[0];Argument[Qualifier];taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnFieldInIEnumerable;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);Argument[0].Element;ReturnValue;taint |
|
||||
|
||||
45
csharp/ql/test/utils/model-generator/NoSummaries.cs
Normal file
45
csharp/ql/test/utils/model-generator/NoSummaries.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
|
||||
namespace NoSummaries;
|
||||
|
||||
// Single class with a method that produces a flow summary.
|
||||
// Just to prove that, if a method like this is correctly exposed, a flow summary will be captured.
|
||||
public class PublicClassFlow
|
||||
{
|
||||
public int PublicReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PublicClassNoFlow
|
||||
{
|
||||
private int PrivateReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
internal int InternalReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
private class PrivateClassNoFlow
|
||||
{
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
private class PrivateClassNestedPublicClassNoFlow
|
||||
{
|
||||
public class NestedPublicClassFlow
|
||||
{
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Summaries;
|
||||
|
||||
@@ -31,6 +33,21 @@ public class BasicFlow
|
||||
return s.Substring(0, 1);
|
||||
}
|
||||
|
||||
public void SetField(string s)
|
||||
{
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
}
|
||||
|
||||
public class CollectionFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
public int ReturnArrayElement(int[] input)
|
||||
{
|
||||
return input[0];
|
||||
@@ -41,18 +58,117 @@ public class BasicFlow
|
||||
target[0] = data;
|
||||
}
|
||||
|
||||
public void SetField(string s)
|
||||
{
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
|
||||
public void AssignFieldToArray(object[] target)
|
||||
{
|
||||
target[0] = tainted;
|
||||
}
|
||||
|
||||
public object ReturnListElement(List<object> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
public void AddToList(List<object> input, object data)
|
||||
{
|
||||
input.Add(data);
|
||||
}
|
||||
|
||||
public void AddFieldToList(List<string> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
public List<string> ReturnFieldInAList()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
}
|
||||
|
||||
public class IEnumerableFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
public IEnumerable<string> ReturnIEnumerable(IEnumerable<string> input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public object ReturnIEnumerableElement(IEnumerable<object> input)
|
||||
{
|
||||
return input.First();
|
||||
}
|
||||
|
||||
public IEnumerable<string> ReturnFieldInIEnumerable()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
}
|
||||
|
||||
public class GenericFlow<T>
|
||||
{
|
||||
private T tainted;
|
||||
|
||||
public void SetGenericField(T t)
|
||||
{
|
||||
tainted = t;
|
||||
}
|
||||
|
||||
public T ReturnGenericField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
|
||||
public void AddFieldToGenericList(List<T> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
public List<T> ReturnFieldInGenericList()
|
||||
{
|
||||
return new List<T> { tainted };
|
||||
}
|
||||
|
||||
public S ReturnGenericParam<S>(S input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public S ReturnGenericElement<S>(List<S> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
public void AddToGenericList<S>(List<S> input, S data)
|
||||
{
|
||||
input.Add(data);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseClassFlow
|
||||
{
|
||||
public virtual int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass1Flow : BaseClassFlow
|
||||
{
|
||||
public int ReturnParam1(int input0, int input1)
|
||||
{
|
||||
return input1;
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass2Flow : BaseClassFlow
|
||||
{
|
||||
public override int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public int ReturnParam0(int input0, int input1)
|
||||
{
|
||||
return input0;
|
||||
}
|
||||
}
|
||||
1
csharp/ql/test/utils/model-generator/options
Normal file
1
csharp/ql/test/utils/model-generator/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: /r:System.Linq.dll
|
||||
@@ -7,8 +7,8 @@ When analyzing a Go program, CodeQL does not examine the source code for
|
||||
external packages. To track the flow of untrusted data through a library, you
|
||||
can create a model of the library.
|
||||
|
||||
You can find existing models in the ``ql/src/semmle/go/frameworks/`` folder of the
|
||||
`CodeQL for Go repository <https://github.com/github/codeql-go/tree/main/ql/src/semmle/go/frameworks>`__.
|
||||
You can find existing models in the ``ql/lib/semmle/go/frameworks/`` folder of the
|
||||
`CodeQL for Go repository <https://github.com/github/codeql-go/tree/main/ql/lib/semmle/go/frameworks>`__.
|
||||
To add a new model, you should make a new file in that folder, named after the library.
|
||||
|
||||
Sources
|
||||
@@ -102,8 +102,8 @@ Data-flow sinks are specified by queries rather than by library models.
|
||||
However, you can use library models to indicate when functions belong to
|
||||
special categories. Queries can then use these categories when specifying
|
||||
sinks. Classes representing these special categories are contained in
|
||||
``ql/src/semmle/go/Concepts.qll`` in the `CodeQL for Go repository
|
||||
<https://github.com/github/codeql-go/blob/main/ql/src/semmle/go/Concepts.qll>`__.
|
||||
``ql/lib/semmle/go/Concepts.qll`` in the `CodeQL for Go repository
|
||||
<https://github.com/github/codeql-go/blob/main/ql/lib/semmle/go/Concepts.qll>`__.
|
||||
``Concepts.qll`` includes classes for logger mechanisms,
|
||||
HTTP response writers, HTTP redirects, and marshaling and unmarshaling
|
||||
functions.
|
||||
|
||||
4
java/ql/lib/change-notes/2022-03-16-error-elements.md
Normal file
4
java/ql/lib/change-notes/2022-03-16-error-elements.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* There are now QL classes ErrorExpr and ErrorStmt. These may be generated by upgrade or downgrade scripts when databases cannot be fully converted.
|
||||
@@ -528,6 +528,7 @@ case @stmt.kind of
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
| 24 = @errorstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
@@ -628,6 +629,7 @@ case @expr.kind of
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
| 74 = @errorexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<dbstats>
|
||||
<typesizes><e>
|
||||
<typesizes>
|
||||
<e>
|
||||
<k>@compilation</k>
|
||||
<v>8629</v>
|
||||
</e>
|
||||
@@ -21,7 +22,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@location_default</k>
|
||||
<v>13306607</v>
|
||||
<v>17430587</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@file</k>
|
||||
@@ -149,7 +150,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@emptystmt</k>
|
||||
<v>886</v>
|
||||
<v>1562</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@exprstmt</k>
|
||||
@@ -191,6 +192,10 @@
|
||||
<k>@yieldstmt</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@errorstmt</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@arrayaccess</k>
|
||||
<v>181399</v>
|
||||
@@ -265,7 +270,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@mulexpr</k>
|
||||
<v>85898</v>
|
||||
<v>204610</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@divexpr</k>
|
||||
@@ -281,7 +286,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@subexpr</k>
|
||||
<v>57171</v>
|
||||
<v>84397</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@lshiftexpr</k>
|
||||
@@ -483,6 +488,10 @@
|
||||
<k>@switchexpr</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@errorexpr</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@localvar</k>
|
||||
<v>385335</v>
|
||||
@@ -519,10 +528,6 @@
|
||||
<k>@javadocTag</k>
|
||||
<v>335863</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@javadocText</k>
|
||||
<v>2503256</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmldtd</k>
|
||||
<v>569</v>
|
||||
@@ -531,6 +536,10 @@
|
||||
<k>@xmlelement</k>
|
||||
<v>1199832</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@javadocText</k>
|
||||
<v>2503256</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmlattribute</k>
|
||||
<v>1841492</v>
|
||||
@@ -560,7 +569,8 @@
|
||||
<v>1</v>
|
||||
</e>
|
||||
</typesizes>
|
||||
<stats><relation>
|
||||
<stats>
|
||||
<relation>
|
||||
<name>compilations</name>
|
||||
<cardinality>8629</cardinality>
|
||||
<columnsizes>
|
||||
@@ -16749,11 +16759,11 @@
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isParenthesized</name>
|
||||
<cardinality>84274</cardinality>
|
||||
<cardinality>94666</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>84274</v>
|
||||
<v>94666</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>parentheses</k>
|
||||
@@ -16771,7 +16781,7 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>84274</v>
|
||||
<v>94666</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -16785,13 +16795,13 @@
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>12</a>
|
||||
<b>13</b>
|
||||
<a>58</a>
|
||||
<b>59</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>31863</a>
|
||||
<b>31864</b>
|
||||
<a>34605</a>
|
||||
<b>34606</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
|
||||
@@ -377,6 +377,18 @@ class CompileTimeConstantExpr extends Expr {
|
||||
/** An expression parent is an element that may have an expression as its child. */
|
||||
class ExprParent extends @exprparent, Top { }
|
||||
|
||||
/**
|
||||
* An error expression.
|
||||
*
|
||||
* These may be generated by upgrade or downgrade scripts when databases
|
||||
* cannot be fully converted.
|
||||
*/
|
||||
class ErrorExpr extends Expr, @errorexpr {
|
||||
override string toString() { result = "<error expr>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ErrorExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An array access.
|
||||
*
|
||||
|
||||
@@ -59,6 +59,18 @@ class Stmt extends StmtParent, ExprParent, @stmt {
|
||||
/** A statement parent is any element that can have a statement as its child. */
|
||||
class StmtParent extends @stmtparent, Top { }
|
||||
|
||||
/**
|
||||
* An error statement.
|
||||
*
|
||||
* These may be generated by upgrade or downgrade scripts when databases
|
||||
* cannot be fully converted.
|
||||
*/
|
||||
class ErrorStmt extends Stmt, @errorstmt {
|
||||
override string toString() { result = "<error stmt>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ErrorStmt" }
|
||||
}
|
||||
|
||||
/** A block of statements. */
|
||||
class BlockStmt extends Stmt, @block {
|
||||
/** Gets a statement that is an immediate child of this block. */
|
||||
|
||||
@@ -1056,7 +1056,7 @@ module Private {
|
||||
|
|
||||
c.relevantSummary(input, output, preservesValue) and
|
||||
csv =
|
||||
c.getCallableCsv() + ";;" + getComponentStackCsv(input) + ";" +
|
||||
c.getCallableCsv() + ";" + getComponentStackCsv(input) + ";" +
|
||||
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,982 @@
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may be
|
||||
* compiled per invocation. For example, this command compiles three
|
||||
* source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* The `id` simply identifies the invocation, while `cwd` is the working
|
||||
* directory from which the compiler was invoked.
|
||||
*/
|
||||
compilations(
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may
|
||||
* be compiled per invocation. For example, this command compiles
|
||||
* three source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*/
|
||||
unique int id : @compilation,
|
||||
string cwd : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The arguments that were passed to the extractor for a compiler
|
||||
* invocation. If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then typically there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | *path to extractor*
|
||||
* 1 | `--javac-args`
|
||||
* 2 | A.java
|
||||
* 3 | B.java
|
||||
* 4 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_args(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
string arg : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The source files that are compiled by a compiler invocation.
|
||||
* If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | A.java
|
||||
* 1 | B.java
|
||||
* 2 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_compiling_files(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
int file : @file ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The time taken by the extractor for a compiler invocation.
|
||||
*
|
||||
* For each file `num`, there will be rows for
|
||||
*
|
||||
* kind | seconds
|
||||
* ---- | ---
|
||||
* 1 | CPU seconds used by the extractor frontend
|
||||
* 2 | Elapsed seconds during the extractor frontend
|
||||
* 3 | CPU seconds used by the extractor backend
|
||||
* 4 | Elapsed seconds during the extractor backend
|
||||
*/
|
||||
#keyset[id, num, kind]
|
||||
compilation_time(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
/* kind:
|
||||
1 = frontend_cpu_seconds
|
||||
2 = frontend_elapsed_seconds
|
||||
3 = extractor_cpu_seconds
|
||||
4 = extractor_elapsed_seconds
|
||||
*/
|
||||
int kind : int ref,
|
||||
float seconds : float ref
|
||||
);
|
||||
|
||||
/**
|
||||
* An error or warning generated by the extractor.
|
||||
* The diagnostic message `diagnostic` was generated during compiler
|
||||
* invocation `compilation`, and is the `file_number_diagnostic_number`th
|
||||
* message generated while extracting the `file_number`th file of that
|
||||
* invocation.
|
||||
*/
|
||||
#keyset[compilation, file_number, file_number_diagnostic_number]
|
||||
diagnostic_for(
|
||||
unique int diagnostic : @diagnostic ref,
|
||||
int compilation : @compilation ref,
|
||||
int file_number : int ref,
|
||||
int file_number_diagnostic_number : int ref
|
||||
);
|
||||
|
||||
/**
|
||||
* If extraction was successful, then `cpu_seconds` and
|
||||
* `elapsed_seconds` are the CPU time and elapsed time (respectively)
|
||||
* that extraction took for compiler invocation `id`.
|
||||
*/
|
||||
compilation_finished(
|
||||
unique int id : @compilation ref,
|
||||
float cpu_seconds : float ref,
|
||||
float elapsed_seconds : float ref
|
||||
);
|
||||
|
||||
diagnostics(
|
||||
unique int id: @diagnostic,
|
||||
int severity: int ref,
|
||||
string error_tag: string ref,
|
||||
string error_message: string ref,
|
||||
string full_error_message: string ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
string path : string ref,
|
||||
int column: int ref,
|
||||
string value : string ref
|
||||
);
|
||||
|
||||
snapshotDate(
|
||||
unique date snapshotDate : date ref
|
||||
);
|
||||
|
||||
sourceLocationPrefix(
|
||||
string prefix : string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* SMAP
|
||||
*/
|
||||
|
||||
smap_header(
|
||||
int outputFileId: @file ref,
|
||||
string outputFilename: string ref,
|
||||
string defaultStratum: string ref
|
||||
);
|
||||
|
||||
smap_files(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
string inputFileName: string ref,
|
||||
int inputFileId: @file ref
|
||||
);
|
||||
|
||||
smap_lines(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
int inputStartLine: int ref,
|
||||
int inputLineCount: int ref,
|
||||
int outputStartLine: int ref,
|
||||
int outputLineIncrement: int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Locations and files
|
||||
*/
|
||||
|
||||
@location = @location_default ;
|
||||
|
||||
locations_default(
|
||||
unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref
|
||||
);
|
||||
|
||||
hasLocation(
|
||||
int locatableid: @locatable ref,
|
||||
int id: @location ref
|
||||
);
|
||||
|
||||
@sourceline = @locatable ;
|
||||
|
||||
#keyset[element_id]
|
||||
numlines(
|
||||
int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
files(
|
||||
unique int id: @file,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
folders(
|
||||
unique int id: @folder,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@container = @folder | @file
|
||||
|
||||
containerparent(
|
||||
int parent: @container ref,
|
||||
unique int child: @container ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Java
|
||||
*/
|
||||
|
||||
cupackage(
|
||||
unique int id: @file ref,
|
||||
int packageid: @package ref
|
||||
);
|
||||
|
||||
#keyset[fileid,keyName]
|
||||
jarManifestMain(
|
||||
int fileid: @file ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
#keyset[fileid,entryName,keyName]
|
||||
jarManifestEntries(
|
||||
int fileid: @file ref,
|
||||
string entryName: string ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
packages(
|
||||
unique int id: @package,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
primitives(
|
||||
unique int id: @primitive,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
modifiers(
|
||||
unique int id: @modifier,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
classes(
|
||||
unique int id: @class,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @class ref
|
||||
);
|
||||
|
||||
isRecord(
|
||||
unique int id: @class ref
|
||||
);
|
||||
|
||||
interfaces(
|
||||
unique int id: @interface,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @interface ref
|
||||
);
|
||||
|
||||
fielddecls(
|
||||
unique int id: @fielddecl,
|
||||
int parentid: @reftype ref
|
||||
);
|
||||
|
||||
#keyset[fieldId] #keyset[fieldDeclId,pos]
|
||||
fieldDeclaredIn(
|
||||
int fieldId: @field ref,
|
||||
int fieldDeclId: @fielddecl ref,
|
||||
int pos: int ref
|
||||
);
|
||||
|
||||
fields(
|
||||
unique int id: @field,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @field ref
|
||||
);
|
||||
|
||||
constrs(
|
||||
unique int id: @constructor,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @constructor ref
|
||||
);
|
||||
|
||||
methods(
|
||||
unique int id: @method,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @method ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
params(
|
||||
unique int id: @param,
|
||||
int typeid: @type ref,
|
||||
int pos: int ref,
|
||||
int parentid: @callable ref,
|
||||
int sourceid: @param ref
|
||||
);
|
||||
|
||||
paramName(
|
||||
unique int id: @param ref,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
isVarargsParam(
|
||||
int param: @param ref
|
||||
);
|
||||
|
||||
exceptions(
|
||||
unique int id: @exception,
|
||||
int typeid: @type ref,
|
||||
int parentid: @callable ref
|
||||
);
|
||||
|
||||
isAnnotType(
|
||||
int interfaceid: @interface ref
|
||||
);
|
||||
|
||||
isAnnotElem(
|
||||
int methodid: @method ref
|
||||
);
|
||||
|
||||
annotValue(
|
||||
int parentid: @annotation ref,
|
||||
int id2: @method ref,
|
||||
unique int value: @expr ref
|
||||
);
|
||||
|
||||
isEnumType(
|
||||
int classid: @class ref
|
||||
);
|
||||
|
||||
isEnumConst(
|
||||
int fieldid: @field ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeVars(
|
||||
unique int id: @typevariable,
|
||||
string nodeName: string ref,
|
||||
int pos: int ref,
|
||||
int kind: int ref, // deprecated
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
wildcards(
|
||||
unique int id: @wildcard,
|
||||
string nodeName: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeBounds(
|
||||
unique int id: @typebound,
|
||||
int typeid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @boundedtype ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeArgs(
|
||||
int argumentid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
isParameterized(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
isRaw(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
erasure(
|
||||
unique int memberid: @member ref,
|
||||
int erasureid: @member ref
|
||||
);
|
||||
|
||||
#keyset[classid] #keyset[parent]
|
||||
isAnonymClass(
|
||||
int classid: @class ref,
|
||||
int parent: @classinstancexpr ref
|
||||
);
|
||||
|
||||
#keyset[typeid] #keyset[parent]
|
||||
isLocalClassOrInterface(
|
||||
int typeid: @classorinterface ref,
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
int constructorid: @constructor ref
|
||||
);
|
||||
|
||||
#keyset[exprId]
|
||||
lambdaKind(
|
||||
int exprId: @lambdaexpr ref,
|
||||
int bodyKind: int ref
|
||||
);
|
||||
|
||||
arrays(
|
||||
unique int id: @array,
|
||||
string nodeName: string ref,
|
||||
int elementtypeid: @type ref,
|
||||
int dimension: int ref,
|
||||
int componenttypeid: @type ref
|
||||
);
|
||||
|
||||
enclInReftype(
|
||||
unique int child: @reftype ref,
|
||||
int parent: @reftype ref
|
||||
);
|
||||
|
||||
extendsReftype(
|
||||
int id1: @reftype ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
implInterface(
|
||||
int id1: @classorarray ref,
|
||||
int id2: @interface ref
|
||||
);
|
||||
|
||||
permits(
|
||||
int id1: @classorinterface ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
hasModifier(
|
||||
int id1: @modifiable ref,
|
||||
int id2: @modifier ref
|
||||
);
|
||||
|
||||
imports(
|
||||
unique int id: @import,
|
||||
int holder: @classorinterfaceorpackage ref,
|
||||
string name: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parent,idx]
|
||||
stmts(
|
||||
unique int id: @stmt,
|
||||
int kind: int ref,
|
||||
int parent: @stmtparent ref,
|
||||
int idx: int ref,
|
||||
int bodydecl: @callable ref
|
||||
);
|
||||
|
||||
@stmtparent = @callable | @stmt | @switchexpr;
|
||||
|
||||
case @stmt.kind of
|
||||
0 = @block
|
||||
| 1 = @ifstmt
|
||||
| 2 = @forstmt
|
||||
| 3 = @enhancedforstmt
|
||||
| 4 = @whilestmt
|
||||
| 5 = @dostmt
|
||||
| 6 = @trystmt
|
||||
| 7 = @switchstmt
|
||||
| 8 = @synchronizedstmt
|
||||
| 9 = @returnstmt
|
||||
| 10 = @throwstmt
|
||||
| 11 = @breakstmt
|
||||
| 12 = @continuestmt
|
||||
| 13 = @emptystmt
|
||||
| 14 = @exprstmt
|
||||
| 15 = @labeledstmt
|
||||
| 16 = @assertstmt
|
||||
| 17 = @localvariabledeclstmt
|
||||
| 18 = @localtypedeclstmt
|
||||
| 19 = @constructorinvocationstmt
|
||||
| 20 = @superconstructorinvocationstmt
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
exprs(
|
||||
unique int id: @expr,
|
||||
int kind: int ref,
|
||||
int typeid: @type ref,
|
||||
int parent: @exprparent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
callableEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int callable_id: @callable ref
|
||||
);
|
||||
|
||||
statementEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int statement_id: @stmt ref
|
||||
);
|
||||
|
||||
isParenthesized(
|
||||
unique int id: @expr ref,
|
||||
int parentheses: int ref
|
||||
);
|
||||
|
||||
case @expr.kind of
|
||||
1 = @arrayaccess
|
||||
| 2 = @arraycreationexpr
|
||||
| 3 = @arrayinit
|
||||
| 4 = @assignexpr
|
||||
| 5 = @assignaddexpr
|
||||
| 6 = @assignsubexpr
|
||||
| 7 = @assignmulexpr
|
||||
| 8 = @assigndivexpr
|
||||
| 9 = @assignremexpr
|
||||
| 10 = @assignandexpr
|
||||
| 11 = @assignorexpr
|
||||
| 12 = @assignxorexpr
|
||||
| 13 = @assignlshiftexpr
|
||||
| 14 = @assignrshiftexpr
|
||||
| 15 = @assignurshiftexpr
|
||||
| 16 = @booleanliteral
|
||||
| 17 = @integerliteral
|
||||
| 18 = @longliteral
|
||||
| 19 = @floatingpointliteral
|
||||
| 20 = @doubleliteral
|
||||
| 21 = @characterliteral
|
||||
| 22 = @stringliteral
|
||||
| 23 = @nullliteral
|
||||
| 24 = @mulexpr
|
||||
| 25 = @divexpr
|
||||
| 26 = @remexpr
|
||||
| 27 = @addexpr
|
||||
| 28 = @subexpr
|
||||
| 29 = @lshiftexpr
|
||||
| 30 = @rshiftexpr
|
||||
| 31 = @urshiftexpr
|
||||
| 32 = @andbitexpr
|
||||
| 33 = @orbitexpr
|
||||
| 34 = @xorbitexpr
|
||||
| 35 = @andlogicalexpr
|
||||
| 36 = @orlogicalexpr
|
||||
| 37 = @ltexpr
|
||||
| 38 = @gtexpr
|
||||
| 39 = @leexpr
|
||||
| 40 = @geexpr
|
||||
| 41 = @eqexpr
|
||||
| 42 = @neexpr
|
||||
| 43 = @postincexpr
|
||||
| 44 = @postdecexpr
|
||||
| 45 = @preincexpr
|
||||
| 46 = @predecexpr
|
||||
| 47 = @minusexpr
|
||||
| 48 = @plusexpr
|
||||
| 49 = @bitnotexpr
|
||||
| 50 = @lognotexpr
|
||||
| 51 = @castexpr
|
||||
| 52 = @newexpr
|
||||
| 53 = @conditionalexpr
|
||||
| 54 = @parexpr // deprecated
|
||||
| 55 = @instanceofexpr
|
||||
| 56 = @localvariabledeclexpr
|
||||
| 57 = @typeliteral
|
||||
| 58 = @thisaccess
|
||||
| 59 = @superaccess
|
||||
| 60 = @varaccess
|
||||
| 61 = @methodaccess
|
||||
| 62 = @unannotatedtypeaccess
|
||||
| 63 = @arraytypeaccess
|
||||
| 64 = @packageaccess
|
||||
| 65 = @wildcardtypeaccess
|
||||
| 66 = @declannotation
|
||||
| 67 = @uniontypeaccess
|
||||
| 68 = @lambdaexpr
|
||||
| 69 = @memberref
|
||||
| 70 = @annotatedtypeaccess
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@annotation = @declannotation | @typeannotation
|
||||
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess
|
||||
|
||||
@assignment = @assignexpr
|
||||
| @assignop;
|
||||
|
||||
@unaryassignment = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr;
|
||||
|
||||
@assignop = @assignaddexpr
|
||||
| @assignsubexpr
|
||||
| @assignmulexpr
|
||||
| @assigndivexpr
|
||||
| @assignremexpr
|
||||
| @assignandexpr
|
||||
| @assignorexpr
|
||||
| @assignxorexpr
|
||||
| @assignlshiftexpr
|
||||
| @assignrshiftexpr
|
||||
| @assignurshiftexpr;
|
||||
|
||||
@literal = @booleanliteral
|
||||
| @integerliteral
|
||||
| @longliteral
|
||||
| @floatingpointliteral
|
||||
| @doubleliteral
|
||||
| @characterliteral
|
||||
| @stringliteral
|
||||
| @nullliteral;
|
||||
|
||||
@binaryexpr = @mulexpr
|
||||
| @divexpr
|
||||
| @remexpr
|
||||
| @addexpr
|
||||
| @subexpr
|
||||
| @lshiftexpr
|
||||
| @rshiftexpr
|
||||
| @urshiftexpr
|
||||
| @andbitexpr
|
||||
| @orbitexpr
|
||||
| @xorbitexpr
|
||||
| @andlogicalexpr
|
||||
| @orlogicalexpr
|
||||
| @ltexpr
|
||||
| @gtexpr
|
||||
| @leexpr
|
||||
| @geexpr
|
||||
| @eqexpr
|
||||
| @neexpr;
|
||||
|
||||
@unaryexpr = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr
|
||||
| @minusexpr
|
||||
| @plusexpr
|
||||
| @bitnotexpr
|
||||
| @lognotexpr;
|
||||
|
||||
@caller = @classinstancexpr
|
||||
| @methodaccess
|
||||
| @constructorinvocationstmt
|
||||
| @superconstructorinvocationstmt;
|
||||
|
||||
callableBinding(
|
||||
unique int callerid: @caller ref,
|
||||
int callee: @callable ref
|
||||
);
|
||||
|
||||
memberRefBinding(
|
||||
unique int id: @expr ref,
|
||||
int callable: @callable ref
|
||||
);
|
||||
|
||||
@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;
|
||||
|
||||
variableBinding(
|
||||
unique int expr: @varaccess ref,
|
||||
int variable: @variable ref
|
||||
);
|
||||
|
||||
@variable = @localscopevariable | @field;
|
||||
|
||||
@localscopevariable = @localvar | @param;
|
||||
|
||||
localvars(
|
||||
unique int id: @localvar,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @localvariabledeclexpr ref
|
||||
);
|
||||
|
||||
@namedexprorstmt = @breakstmt
|
||||
| @continuestmt
|
||||
| @labeledstmt
|
||||
| @literal;
|
||||
|
||||
namestrings(
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
unique int parent: @namedexprorstmt ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Modules
|
||||
*/
|
||||
|
||||
#keyset[name]
|
||||
modules(
|
||||
unique int id: @module,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
isOpen(
|
||||
int id: @module ref
|
||||
);
|
||||
|
||||
#keyset[fileId]
|
||||
cumodule(
|
||||
int fileId: @file ref,
|
||||
int moduleId: @module ref
|
||||
);
|
||||
|
||||
@directive = @requires
|
||||
| @exports
|
||||
| @opens
|
||||
| @uses
|
||||
| @provides
|
||||
|
||||
#keyset[directive]
|
||||
directives(
|
||||
int id: @module ref,
|
||||
int directive: @directive ref
|
||||
);
|
||||
|
||||
requires(
|
||||
unique int id: @requires,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
isTransitive(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
isStatic(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
exports(
|
||||
unique int id: @exports,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
exportsTo(
|
||||
int id: @exports ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
opens(
|
||||
unique int id: @opens,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
opensTo(
|
||||
int id: @opens ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
uses(
|
||||
unique int id: @uses,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
provides(
|
||||
unique int id: @provides,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
providesWith(
|
||||
int id: @provides ref,
|
||||
string serviceImpl: string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Javadoc
|
||||
*/
|
||||
|
||||
javadoc(
|
||||
unique int id: @javadoc
|
||||
);
|
||||
|
||||
isNormalComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
isEolComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
hasJavadoc(
|
||||
int documentableid: @member ref,
|
||||
int javadocid: @javadoc ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocTag(
|
||||
unique int id: @javadocTag,
|
||||
string name: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocText(
|
||||
unique int id: @javadocText,
|
||||
string text: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
@javadocParent = @javadoc | @javadocTag;
|
||||
@javadocElement = @javadocTag | @javadocText;
|
||||
|
||||
@classorinterface = @interface | @class;
|
||||
@classorinterfaceorpackage = @classorinterface | @package;
|
||||
@classorinterfaceorcallable = @classorinterface | @callable;
|
||||
@boundedtype = @typevariable | @wildcard;
|
||||
@reftype = @classorinterface | @array | @boundedtype;
|
||||
@classorarray = @class | @array;
|
||||
@type = @primitive | @reftype;
|
||||
@callable = @method | @constructor;
|
||||
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
|
||||
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl;
|
||||
|
||||
@modifiable = @member_modifiable| @param | @localvar ;
|
||||
|
||||
@member_modifiable = @class | @interface | @method | @constructor | @field ;
|
||||
|
||||
@member = @method | @constructor | @field | @reftype ;
|
||||
|
||||
@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
|
||||
| @boundedtype | @typebound | @array | @primitive
|
||||
| @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText
|
||||
| @xmllocatable;
|
||||
|
||||
@top = @element | @locatable | @folder;
|
||||
|
||||
/*
|
||||
* XML Files
|
||||
*/
|
||||
|
||||
xmlEncoding(
|
||||
unique int id: @file ref,
|
||||
string encoding: string ref
|
||||
);
|
||||
|
||||
xmlDTDs(
|
||||
unique int id: @xmldtd,
|
||||
string root: string ref,
|
||||
string publicId: string ref,
|
||||
string systemId: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlElements(
|
||||
unique int id: @xmlelement,
|
||||
string name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlAttrs(
|
||||
unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlNs(
|
||||
int id: @xmlnamespace,
|
||||
string prefixName: string ref,
|
||||
string URI: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlHasNs(
|
||||
int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlComments(
|
||||
unique int id: @xmlcomment,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlChars(
|
||||
unique int id: @xmlcharacters,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(
|
||||
int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
|
||||
/*
|
||||
* configuration files with key value pairs
|
||||
*/
|
||||
|
||||
configs(
|
||||
unique int id: @config
|
||||
);
|
||||
|
||||
configNames(
|
||||
unique int id: @configName,
|
||||
int config: @config ref,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
configValues(
|
||||
unique int id: @configValue,
|
||||
int config: @config ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
configLocations(
|
||||
int locatable: @configLocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@configLocatable = @config | @configName | @configValue;
|
||||
@@ -0,0 +1,984 @@
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may be
|
||||
* compiled per invocation. For example, this command compiles three
|
||||
* source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* The `id` simply identifies the invocation, while `cwd` is the working
|
||||
* directory from which the compiler was invoked.
|
||||
*/
|
||||
compilations(
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may
|
||||
* be compiled per invocation. For example, this command compiles
|
||||
* three source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*/
|
||||
unique int id : @compilation,
|
||||
string cwd : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The arguments that were passed to the extractor for a compiler
|
||||
* invocation. If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then typically there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | *path to extractor*
|
||||
* 1 | `--javac-args`
|
||||
* 2 | A.java
|
||||
* 3 | B.java
|
||||
* 4 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_args(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
string arg : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The source files that are compiled by a compiler invocation.
|
||||
* If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | A.java
|
||||
* 1 | B.java
|
||||
* 2 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_compiling_files(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
int file : @file ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The time taken by the extractor for a compiler invocation.
|
||||
*
|
||||
* For each file `num`, there will be rows for
|
||||
*
|
||||
* kind | seconds
|
||||
* ---- | ---
|
||||
* 1 | CPU seconds used by the extractor frontend
|
||||
* 2 | Elapsed seconds during the extractor frontend
|
||||
* 3 | CPU seconds used by the extractor backend
|
||||
* 4 | Elapsed seconds during the extractor backend
|
||||
*/
|
||||
#keyset[id, num, kind]
|
||||
compilation_time(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
/* kind:
|
||||
1 = frontend_cpu_seconds
|
||||
2 = frontend_elapsed_seconds
|
||||
3 = extractor_cpu_seconds
|
||||
4 = extractor_elapsed_seconds
|
||||
*/
|
||||
int kind : int ref,
|
||||
float seconds : float ref
|
||||
);
|
||||
|
||||
/**
|
||||
* An error or warning generated by the extractor.
|
||||
* The diagnostic message `diagnostic` was generated during compiler
|
||||
* invocation `compilation`, and is the `file_number_diagnostic_number`th
|
||||
* message generated while extracting the `file_number`th file of that
|
||||
* invocation.
|
||||
*/
|
||||
#keyset[compilation, file_number, file_number_diagnostic_number]
|
||||
diagnostic_for(
|
||||
unique int diagnostic : @diagnostic ref,
|
||||
int compilation : @compilation ref,
|
||||
int file_number : int ref,
|
||||
int file_number_diagnostic_number : int ref
|
||||
);
|
||||
|
||||
/**
|
||||
* If extraction was successful, then `cpu_seconds` and
|
||||
* `elapsed_seconds` are the CPU time and elapsed time (respectively)
|
||||
* that extraction took for compiler invocation `id`.
|
||||
*/
|
||||
compilation_finished(
|
||||
unique int id : @compilation ref,
|
||||
float cpu_seconds : float ref,
|
||||
float elapsed_seconds : float ref
|
||||
);
|
||||
|
||||
diagnostics(
|
||||
unique int id: @diagnostic,
|
||||
int severity: int ref,
|
||||
string error_tag: string ref,
|
||||
string error_message: string ref,
|
||||
string full_error_message: string ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
string path : string ref,
|
||||
int column: int ref,
|
||||
string value : string ref
|
||||
);
|
||||
|
||||
snapshotDate(
|
||||
unique date snapshotDate : date ref
|
||||
);
|
||||
|
||||
sourceLocationPrefix(
|
||||
string prefix : string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* SMAP
|
||||
*/
|
||||
|
||||
smap_header(
|
||||
int outputFileId: @file ref,
|
||||
string outputFilename: string ref,
|
||||
string defaultStratum: string ref
|
||||
);
|
||||
|
||||
smap_files(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
string inputFileName: string ref,
|
||||
int inputFileId: @file ref
|
||||
);
|
||||
|
||||
smap_lines(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
int inputStartLine: int ref,
|
||||
int inputLineCount: int ref,
|
||||
int outputStartLine: int ref,
|
||||
int outputLineIncrement: int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Locations and files
|
||||
*/
|
||||
|
||||
@location = @location_default ;
|
||||
|
||||
locations_default(
|
||||
unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref
|
||||
);
|
||||
|
||||
hasLocation(
|
||||
int locatableid: @locatable ref,
|
||||
int id: @location ref
|
||||
);
|
||||
|
||||
@sourceline = @locatable ;
|
||||
|
||||
#keyset[element_id]
|
||||
numlines(
|
||||
int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
files(
|
||||
unique int id: @file,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
folders(
|
||||
unique int id: @folder,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@container = @folder | @file
|
||||
|
||||
containerparent(
|
||||
int parent: @container ref,
|
||||
unique int child: @container ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Java
|
||||
*/
|
||||
|
||||
cupackage(
|
||||
unique int id: @file ref,
|
||||
int packageid: @package ref
|
||||
);
|
||||
|
||||
#keyset[fileid,keyName]
|
||||
jarManifestMain(
|
||||
int fileid: @file ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
#keyset[fileid,entryName,keyName]
|
||||
jarManifestEntries(
|
||||
int fileid: @file ref,
|
||||
string entryName: string ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
packages(
|
||||
unique int id: @package,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
primitives(
|
||||
unique int id: @primitive,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
modifiers(
|
||||
unique int id: @modifier,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
classes(
|
||||
unique int id: @class,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @class ref
|
||||
);
|
||||
|
||||
isRecord(
|
||||
unique int id: @class ref
|
||||
);
|
||||
|
||||
interfaces(
|
||||
unique int id: @interface,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @interface ref
|
||||
);
|
||||
|
||||
fielddecls(
|
||||
unique int id: @fielddecl,
|
||||
int parentid: @reftype ref
|
||||
);
|
||||
|
||||
#keyset[fieldId] #keyset[fieldDeclId,pos]
|
||||
fieldDeclaredIn(
|
||||
int fieldId: @field ref,
|
||||
int fieldDeclId: @fielddecl ref,
|
||||
int pos: int ref
|
||||
);
|
||||
|
||||
fields(
|
||||
unique int id: @field,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @field ref
|
||||
);
|
||||
|
||||
constrs(
|
||||
unique int id: @constructor,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @constructor ref
|
||||
);
|
||||
|
||||
methods(
|
||||
unique int id: @method,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @method ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
params(
|
||||
unique int id: @param,
|
||||
int typeid: @type ref,
|
||||
int pos: int ref,
|
||||
int parentid: @callable ref,
|
||||
int sourceid: @param ref
|
||||
);
|
||||
|
||||
paramName(
|
||||
unique int id: @param ref,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
isVarargsParam(
|
||||
int param: @param ref
|
||||
);
|
||||
|
||||
exceptions(
|
||||
unique int id: @exception,
|
||||
int typeid: @type ref,
|
||||
int parentid: @callable ref
|
||||
);
|
||||
|
||||
isAnnotType(
|
||||
int interfaceid: @interface ref
|
||||
);
|
||||
|
||||
isAnnotElem(
|
||||
int methodid: @method ref
|
||||
);
|
||||
|
||||
annotValue(
|
||||
int parentid: @annotation ref,
|
||||
int id2: @method ref,
|
||||
unique int value: @expr ref
|
||||
);
|
||||
|
||||
isEnumType(
|
||||
int classid: @class ref
|
||||
);
|
||||
|
||||
isEnumConst(
|
||||
int fieldid: @field ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeVars(
|
||||
unique int id: @typevariable,
|
||||
string nodeName: string ref,
|
||||
int pos: int ref,
|
||||
int kind: int ref, // deprecated
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
wildcards(
|
||||
unique int id: @wildcard,
|
||||
string nodeName: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeBounds(
|
||||
unique int id: @typebound,
|
||||
int typeid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @boundedtype ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeArgs(
|
||||
int argumentid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
isParameterized(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
isRaw(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
erasure(
|
||||
unique int memberid: @member ref,
|
||||
int erasureid: @member ref
|
||||
);
|
||||
|
||||
#keyset[classid] #keyset[parent]
|
||||
isAnonymClass(
|
||||
int classid: @class ref,
|
||||
int parent: @classinstancexpr ref
|
||||
);
|
||||
|
||||
#keyset[typeid] #keyset[parent]
|
||||
isLocalClassOrInterface(
|
||||
int typeid: @classorinterface ref,
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
int constructorid: @constructor ref
|
||||
);
|
||||
|
||||
#keyset[exprId]
|
||||
lambdaKind(
|
||||
int exprId: @lambdaexpr ref,
|
||||
int bodyKind: int ref
|
||||
);
|
||||
|
||||
arrays(
|
||||
unique int id: @array,
|
||||
string nodeName: string ref,
|
||||
int elementtypeid: @type ref,
|
||||
int dimension: int ref,
|
||||
int componenttypeid: @type ref
|
||||
);
|
||||
|
||||
enclInReftype(
|
||||
unique int child: @reftype ref,
|
||||
int parent: @reftype ref
|
||||
);
|
||||
|
||||
extendsReftype(
|
||||
int id1: @reftype ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
implInterface(
|
||||
int id1: @classorarray ref,
|
||||
int id2: @interface ref
|
||||
);
|
||||
|
||||
permits(
|
||||
int id1: @classorinterface ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
hasModifier(
|
||||
int id1: @modifiable ref,
|
||||
int id2: @modifier ref
|
||||
);
|
||||
|
||||
imports(
|
||||
unique int id: @import,
|
||||
int holder: @classorinterfaceorpackage ref,
|
||||
string name: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parent,idx]
|
||||
stmts(
|
||||
unique int id: @stmt,
|
||||
int kind: int ref,
|
||||
int parent: @stmtparent ref,
|
||||
int idx: int ref,
|
||||
int bodydecl: @callable ref
|
||||
);
|
||||
|
||||
@stmtparent = @callable | @stmt | @switchexpr;
|
||||
|
||||
case @stmt.kind of
|
||||
0 = @block
|
||||
| 1 = @ifstmt
|
||||
| 2 = @forstmt
|
||||
| 3 = @enhancedforstmt
|
||||
| 4 = @whilestmt
|
||||
| 5 = @dostmt
|
||||
| 6 = @trystmt
|
||||
| 7 = @switchstmt
|
||||
| 8 = @synchronizedstmt
|
||||
| 9 = @returnstmt
|
||||
| 10 = @throwstmt
|
||||
| 11 = @breakstmt
|
||||
| 12 = @continuestmt
|
||||
| 13 = @emptystmt
|
||||
| 14 = @exprstmt
|
||||
| 15 = @labeledstmt
|
||||
| 16 = @assertstmt
|
||||
| 17 = @localvariabledeclstmt
|
||||
| 18 = @localtypedeclstmt
|
||||
| 19 = @constructorinvocationstmt
|
||||
| 20 = @superconstructorinvocationstmt
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
| 24 = @errorstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
exprs(
|
||||
unique int id: @expr,
|
||||
int kind: int ref,
|
||||
int typeid: @type ref,
|
||||
int parent: @exprparent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
callableEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int callable_id: @callable ref
|
||||
);
|
||||
|
||||
statementEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int statement_id: @stmt ref
|
||||
);
|
||||
|
||||
isParenthesized(
|
||||
unique int id: @expr ref,
|
||||
int parentheses: int ref
|
||||
);
|
||||
|
||||
case @expr.kind of
|
||||
1 = @arrayaccess
|
||||
| 2 = @arraycreationexpr
|
||||
| 3 = @arrayinit
|
||||
| 4 = @assignexpr
|
||||
| 5 = @assignaddexpr
|
||||
| 6 = @assignsubexpr
|
||||
| 7 = @assignmulexpr
|
||||
| 8 = @assigndivexpr
|
||||
| 9 = @assignremexpr
|
||||
| 10 = @assignandexpr
|
||||
| 11 = @assignorexpr
|
||||
| 12 = @assignxorexpr
|
||||
| 13 = @assignlshiftexpr
|
||||
| 14 = @assignrshiftexpr
|
||||
| 15 = @assignurshiftexpr
|
||||
| 16 = @booleanliteral
|
||||
| 17 = @integerliteral
|
||||
| 18 = @longliteral
|
||||
| 19 = @floatingpointliteral
|
||||
| 20 = @doubleliteral
|
||||
| 21 = @characterliteral
|
||||
| 22 = @stringliteral
|
||||
| 23 = @nullliteral
|
||||
| 24 = @mulexpr
|
||||
| 25 = @divexpr
|
||||
| 26 = @remexpr
|
||||
| 27 = @addexpr
|
||||
| 28 = @subexpr
|
||||
| 29 = @lshiftexpr
|
||||
| 30 = @rshiftexpr
|
||||
| 31 = @urshiftexpr
|
||||
| 32 = @andbitexpr
|
||||
| 33 = @orbitexpr
|
||||
| 34 = @xorbitexpr
|
||||
| 35 = @andlogicalexpr
|
||||
| 36 = @orlogicalexpr
|
||||
| 37 = @ltexpr
|
||||
| 38 = @gtexpr
|
||||
| 39 = @leexpr
|
||||
| 40 = @geexpr
|
||||
| 41 = @eqexpr
|
||||
| 42 = @neexpr
|
||||
| 43 = @postincexpr
|
||||
| 44 = @postdecexpr
|
||||
| 45 = @preincexpr
|
||||
| 46 = @predecexpr
|
||||
| 47 = @minusexpr
|
||||
| 48 = @plusexpr
|
||||
| 49 = @bitnotexpr
|
||||
| 50 = @lognotexpr
|
||||
| 51 = @castexpr
|
||||
| 52 = @newexpr
|
||||
| 53 = @conditionalexpr
|
||||
| 54 = @parexpr // deprecated
|
||||
| 55 = @instanceofexpr
|
||||
| 56 = @localvariabledeclexpr
|
||||
| 57 = @typeliteral
|
||||
| 58 = @thisaccess
|
||||
| 59 = @superaccess
|
||||
| 60 = @varaccess
|
||||
| 61 = @methodaccess
|
||||
| 62 = @unannotatedtypeaccess
|
||||
| 63 = @arraytypeaccess
|
||||
| 64 = @packageaccess
|
||||
| 65 = @wildcardtypeaccess
|
||||
| 66 = @declannotation
|
||||
| 67 = @uniontypeaccess
|
||||
| 68 = @lambdaexpr
|
||||
| 69 = @memberref
|
||||
| 70 = @annotatedtypeaccess
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
| 74 = @errorexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@annotation = @declannotation | @typeannotation
|
||||
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess
|
||||
|
||||
@assignment = @assignexpr
|
||||
| @assignop;
|
||||
|
||||
@unaryassignment = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr;
|
||||
|
||||
@assignop = @assignaddexpr
|
||||
| @assignsubexpr
|
||||
| @assignmulexpr
|
||||
| @assigndivexpr
|
||||
| @assignremexpr
|
||||
| @assignandexpr
|
||||
| @assignorexpr
|
||||
| @assignxorexpr
|
||||
| @assignlshiftexpr
|
||||
| @assignrshiftexpr
|
||||
| @assignurshiftexpr;
|
||||
|
||||
@literal = @booleanliteral
|
||||
| @integerliteral
|
||||
| @longliteral
|
||||
| @floatingpointliteral
|
||||
| @doubleliteral
|
||||
| @characterliteral
|
||||
| @stringliteral
|
||||
| @nullliteral;
|
||||
|
||||
@binaryexpr = @mulexpr
|
||||
| @divexpr
|
||||
| @remexpr
|
||||
| @addexpr
|
||||
| @subexpr
|
||||
| @lshiftexpr
|
||||
| @rshiftexpr
|
||||
| @urshiftexpr
|
||||
| @andbitexpr
|
||||
| @orbitexpr
|
||||
| @xorbitexpr
|
||||
| @andlogicalexpr
|
||||
| @orlogicalexpr
|
||||
| @ltexpr
|
||||
| @gtexpr
|
||||
| @leexpr
|
||||
| @geexpr
|
||||
| @eqexpr
|
||||
| @neexpr;
|
||||
|
||||
@unaryexpr = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr
|
||||
| @minusexpr
|
||||
| @plusexpr
|
||||
| @bitnotexpr
|
||||
| @lognotexpr;
|
||||
|
||||
@caller = @classinstancexpr
|
||||
| @methodaccess
|
||||
| @constructorinvocationstmt
|
||||
| @superconstructorinvocationstmt;
|
||||
|
||||
callableBinding(
|
||||
unique int callerid: @caller ref,
|
||||
int callee: @callable ref
|
||||
);
|
||||
|
||||
memberRefBinding(
|
||||
unique int id: @expr ref,
|
||||
int callable: @callable ref
|
||||
);
|
||||
|
||||
@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;
|
||||
|
||||
variableBinding(
|
||||
unique int expr: @varaccess ref,
|
||||
int variable: @variable ref
|
||||
);
|
||||
|
||||
@variable = @localscopevariable | @field;
|
||||
|
||||
@localscopevariable = @localvar | @param;
|
||||
|
||||
localvars(
|
||||
unique int id: @localvar,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @localvariabledeclexpr ref
|
||||
);
|
||||
|
||||
@namedexprorstmt = @breakstmt
|
||||
| @continuestmt
|
||||
| @labeledstmt
|
||||
| @literal;
|
||||
|
||||
namestrings(
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
unique int parent: @namedexprorstmt ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Modules
|
||||
*/
|
||||
|
||||
#keyset[name]
|
||||
modules(
|
||||
unique int id: @module,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
isOpen(
|
||||
int id: @module ref
|
||||
);
|
||||
|
||||
#keyset[fileId]
|
||||
cumodule(
|
||||
int fileId: @file ref,
|
||||
int moduleId: @module ref
|
||||
);
|
||||
|
||||
@directive = @requires
|
||||
| @exports
|
||||
| @opens
|
||||
| @uses
|
||||
| @provides
|
||||
|
||||
#keyset[directive]
|
||||
directives(
|
||||
int id: @module ref,
|
||||
int directive: @directive ref
|
||||
);
|
||||
|
||||
requires(
|
||||
unique int id: @requires,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
isTransitive(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
isStatic(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
exports(
|
||||
unique int id: @exports,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
exportsTo(
|
||||
int id: @exports ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
opens(
|
||||
unique int id: @opens,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
opensTo(
|
||||
int id: @opens ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
uses(
|
||||
unique int id: @uses,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
provides(
|
||||
unique int id: @provides,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
providesWith(
|
||||
int id: @provides ref,
|
||||
string serviceImpl: string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Javadoc
|
||||
*/
|
||||
|
||||
javadoc(
|
||||
unique int id: @javadoc
|
||||
);
|
||||
|
||||
isNormalComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
isEolComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
hasJavadoc(
|
||||
int documentableid: @member ref,
|
||||
int javadocid: @javadoc ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocTag(
|
||||
unique int id: @javadocTag,
|
||||
string name: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocText(
|
||||
unique int id: @javadocText,
|
||||
string text: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
@javadocParent = @javadoc | @javadocTag;
|
||||
@javadocElement = @javadocTag | @javadocText;
|
||||
|
||||
@classorinterface = @interface | @class;
|
||||
@classorinterfaceorpackage = @classorinterface | @package;
|
||||
@classorinterfaceorcallable = @classorinterface | @callable;
|
||||
@boundedtype = @typevariable | @wildcard;
|
||||
@reftype = @classorinterface | @array | @boundedtype;
|
||||
@classorarray = @class | @array;
|
||||
@type = @primitive | @reftype;
|
||||
@callable = @method | @constructor;
|
||||
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
|
||||
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl;
|
||||
|
||||
@modifiable = @member_modifiable| @param | @localvar ;
|
||||
|
||||
@member_modifiable = @class | @interface | @method | @constructor | @field ;
|
||||
|
||||
@member = @method | @constructor | @field | @reftype ;
|
||||
|
||||
@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
|
||||
| @boundedtype | @typebound | @array | @primitive
|
||||
| @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText
|
||||
| @xmllocatable;
|
||||
|
||||
@top = @element | @locatable | @folder;
|
||||
|
||||
/*
|
||||
* XML Files
|
||||
*/
|
||||
|
||||
xmlEncoding(
|
||||
unique int id: @file ref,
|
||||
string encoding: string ref
|
||||
);
|
||||
|
||||
xmlDTDs(
|
||||
unique int id: @xmldtd,
|
||||
string root: string ref,
|
||||
string publicId: string ref,
|
||||
string systemId: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlElements(
|
||||
unique int id: @xmlelement,
|
||||
string name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlAttrs(
|
||||
unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlNs(
|
||||
int id: @xmlnamespace,
|
||||
string prefixName: string ref,
|
||||
string URI: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlHasNs(
|
||||
int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlComments(
|
||||
unique int id: @xmlcomment,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlChars(
|
||||
unique int id: @xmlcharacters,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(
|
||||
int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
|
||||
/*
|
||||
* configuration files with key value pairs
|
||||
*/
|
||||
|
||||
configs(
|
||||
unique int id: @config
|
||||
);
|
||||
|
||||
configNames(
|
||||
unique int id: @configName,
|
||||
int config: @config ref,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
configValues(
|
||||
unique int id: @configValue,
|
||||
int config: @config ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
configLocations(
|
||||
int locatable: @configLocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@configLocatable = @config | @configName | @configValue;
|
||||
@@ -0,0 +1,3 @@
|
||||
description: Add @errorstmt, @errorexpr
|
||||
compatibility: backwards
|
||||
|
||||
@@ -1,178 +1,15 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
# Add Model as Data script directory to sys.path.
|
||||
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
|
||||
sys.path.append(madpath)
|
||||
|
||||
def printHelp():
|
||||
print("""Usage:
|
||||
GenerateFlowModel.py <library-database> <outputQll> [--with-sinks] [--with-sources] [--with-summaries]
|
||||
import generate_flow_model as model
|
||||
|
||||
This generates summary, source and sink models for the code in the database.
|
||||
The files will be placed in `java/ql/lib/semmle/code/java/frameworks/<outputQll>` where
|
||||
outputQll is the name (and path) of the output QLL file. Usually, models are grouped by their
|
||||
respective frameworks.
|
||||
|
||||
Which models are generated is controlled by the flags:
|
||||
--with-sinks
|
||||
--with-sources
|
||||
--with-summaries
|
||||
If none of these flags are specified, all models are generated.
|
||||
|
||||
Example invocations:
|
||||
$ GenerateFlowModel.py /tmp/dbs/apache_commons-codec_45649c8 "apache/Codec.qll"
|
||||
$ GenerateFlowModel.py /tmp/dbs/jdk15_db "javase/jdk_sinks.qll" --with-sinks
|
||||
|
||||
Requirements: `codeql` should both appear on your path.
|
||||
""")
|
||||
|
||||
|
||||
if any(s == "--help" for s in sys.argv):
|
||||
printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
generateSinks = False
|
||||
generateSources = False
|
||||
generateSummaries = False
|
||||
if "--with-sinks" in sys.argv:
|
||||
sys.argv.remove("--with-sinks")
|
||||
generateSinks = True
|
||||
|
||||
if "--with-sources" in sys.argv:
|
||||
sys.argv.remove("--with-sources")
|
||||
generateSources = True
|
||||
|
||||
if "--with-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-summaries")
|
||||
generateSummaries = True
|
||||
|
||||
if not generateSinks and not generateSources and not generateSummaries:
|
||||
generateSinks = generateSources = generateSummaries = True
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
printHelp()
|
||||
sys.exit(1)
|
||||
|
||||
codeQlRoot = subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
targetQll = sys.argv[2]
|
||||
if not targetQll.endswith(".qll"):
|
||||
targetQll += ".qll"
|
||||
filename = os.path.basename(targetQll)
|
||||
shortname = filename[:-4]
|
||||
generatedFrameworks = os.path.join(
|
||||
codeQlRoot, "java/ql/lib/semmle/code/java/frameworks/")
|
||||
frameworkTarget = os.path.join(generatedFrameworks, targetQll)
|
||||
|
||||
workDir = tempfile.mkdtemp()
|
||||
os.makedirs(generatedFrameworks, exist_ok=True)
|
||||
|
||||
|
||||
def runQuery(infoMessage, query):
|
||||
print("########## Querying " + infoMessage + "...")
|
||||
database = sys.argv[1]
|
||||
queryFile = os.path.join(os.path.dirname(
|
||||
__file__), query)
|
||||
resultBqrs = os.path.join(workDir, "out.bqrs")
|
||||
cmd = ['codeql', 'query', 'run', queryFile, '--database',
|
||||
database, '--output', resultBqrs, '--threads', '8']
|
||||
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to generate " + infoMessage +
|
||||
". Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
return readRows(resultBqrs)
|
||||
|
||||
|
||||
def readRows(bqrsFile):
|
||||
generatedJson = os.path.join(workDir, "out.json")
|
||||
cmd = ['codeql', 'bqrs', 'decode', bqrsFile,
|
||||
'--format=json', '--output', generatedJson]
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to decode BQRS. Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
|
||||
with open(generatedJson) as f:
|
||||
results = json.load(f)
|
||||
|
||||
try:
|
||||
results['#select']['tuples']
|
||||
except KeyError:
|
||||
print('Unexpected JSON output - no tuples found')
|
||||
exit(1)
|
||||
|
||||
rows = ""
|
||||
for (row) in results['#select']['tuples']:
|
||||
rows += " \"" + row[0] + "\",\n"
|
||||
|
||||
return rows[:-2]
|
||||
|
||||
|
||||
def asCsvModel(superclass, kind, rows):
|
||||
classTemplate = """
|
||||
private class {0}{1}Csv extends {2} {{
|
||||
override predicate row(string row) {{
|
||||
row =
|
||||
[
|
||||
{3}
|
||||
]
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if rows.strip() == "":
|
||||
return ""
|
||||
return classTemplate.format(shortname[0].upper() + shortname[1:], kind.capitalize(), superclass, rows)
|
||||
|
||||
|
||||
if generateSummaries:
|
||||
summaryRows = runQuery("summary models", "CaptureSummaryModels.ql")
|
||||
summaryCsv = asCsvModel("SummaryModelCsv", "summary", summaryRows)
|
||||
else:
|
||||
summaryCsv = ""
|
||||
|
||||
if generateSinks:
|
||||
sinkRows = runQuery("sink models", "CaptureSinkModels.ql")
|
||||
sinkCsv = asCsvModel("SinkModelCsv", "sinks", sinkRows)
|
||||
else:
|
||||
sinkCsv = ""
|
||||
|
||||
if generateSources:
|
||||
sourceRows = runQuery("source models", "CaptureSourceModels.ql")
|
||||
sourceCsv = asCsvModel("SourceModelCsv", "sources", sourceRows)
|
||||
else:
|
||||
sourceCsv = ""
|
||||
|
||||
qllTemplate = """
|
||||
/** Definitions of taint steps in the {0} framework */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
{1}
|
||||
{2}
|
||||
{3}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
qllContents = qllTemplate.format(shortname, sinkCsv, sourceCsv, summaryCsv)
|
||||
|
||||
|
||||
with open(frameworkTarget, "w") as frameworkQll:
|
||||
frameworkQll.write(qllContents)
|
||||
|
||||
cmd = ['codeql', 'query', 'format', '--in-place', frameworkTarget]
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to format query. Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
|
||||
print("")
|
||||
print("CSV model written to " + frameworkTarget)
|
||||
language = "java"
|
||||
model.Generator.make(language).run()
|
||||
@@ -5,7 +5,7 @@ private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow
|
||||
private import semmle.code.java.dataflow.internal.DataFlowImplCommon
|
||||
|
||||
Method superImpl(Method m) {
|
||||
private Method superImpl(Method m) {
|
||||
result = m.getAnOverride() and
|
||||
not exists(result.getAnOverride()) and
|
||||
not m instanceof ToStringMethod
|
||||
|
||||
@@ -192,8 +192,8 @@ class Test {
|
||||
sink(StringUtils.rotate(taint(), 0)); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), ' ')); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,; // $hasTaintFlow")); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,; // $hasTaintFlow", 0)); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,;")); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,;", 0)); // $hasTaintFlow
|
||||
sink(StringUtils.splitByCharacterType(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.splitByCharacterTypeCamelCase(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.splitByWholeSeparator(taint(), "separator")); // $hasTaintFlow
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-experimental-atm-lib
|
||||
version: 0.1.1
|
||||
version: 0.2.1
|
||||
extractor: javascript
|
||||
library: true
|
||||
groups:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: codeql/javascript-experimental-atm-model
|
||||
version: 0.0.6
|
||||
version: 0.1.1
|
||||
groups:
|
||||
- javascript
|
||||
- experimental
|
||||
mlModels:
|
||||
- "resources/*.codeqlmodel"
|
||||
- "resources/*.codeqlmodel"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.0.6
|
||||
version: 0.1.0
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -6,4 +6,4 @@ groups:
|
||||
- experimental
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-lib: "*"
|
||||
codeql/javascript-experimental-atm-model: "0.0.6"
|
||||
codeql/javascript-experimental-atm-model: "0.1.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.0.6
|
||||
version: 0.1.0
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user