mirror of
https://github.com/github/codeql.git
synced 2026-05-26 17:11:24 +02:00
Compare commits
385 Commits
esbena/ver
...
esbena/deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e890571ed | ||
|
|
3b3c036626 | ||
|
|
e4e472ee74 | ||
|
|
25c416ec8a | ||
|
|
21bea38ec8 | ||
|
|
822f37156e | ||
|
|
22850b28df | ||
|
|
66d230a207 | ||
|
|
3dd042c38a | ||
|
|
79947956bc | ||
|
|
ba27a0d515 | ||
|
|
32d82380f1 | ||
|
|
d8a049f5cc | ||
|
|
7e6857d36b | ||
|
|
6a7b2e4aa4 | ||
|
|
fe2468e7d0 | ||
|
|
20c3984872 | ||
|
|
0e3369f93f | ||
|
|
80c5e1ea77 | ||
|
|
c30e004506 | ||
|
|
ae8e237f2c | ||
|
|
d723905035 | ||
|
|
7700210ed2 | ||
|
|
53561008a1 | ||
|
|
39bca2d4bb | ||
|
|
e204100701 | ||
|
|
17210c76a5 | ||
|
|
0ef83b3c74 | ||
|
|
d56a9f0781 | ||
|
|
fb0016e4f6 | ||
|
|
9a2ac65f53 | ||
|
|
915352861d | ||
|
|
69c3e62965 | ||
|
|
15ec0a10c9 | ||
|
|
61676277e8 | ||
|
|
0cea3f8531 | ||
|
|
1297acf5b1 | ||
|
|
9080e84fc9 | ||
|
|
5e921784fb | ||
|
|
b1ad61e27d | ||
|
|
2ddcd1d9cc | ||
|
|
8f70b55158 | ||
|
|
2edc70da79 | ||
|
|
fe57cd0784 | ||
|
|
6ab2de10e3 | ||
|
|
ed9502fd0b | ||
|
|
adb47399c7 | ||
|
|
3c34638438 | ||
|
|
9f683b8630 | ||
|
|
cf7f355fc4 | ||
|
|
31c04b50f7 | ||
|
|
4eeaf84133 | ||
|
|
ec84f072eb | ||
|
|
da933fb77a | ||
|
|
f1886320e5 | ||
|
|
69531b9f7c | ||
|
|
ef282955fd | ||
|
|
e4f567979a | ||
|
|
64fa6c8bbd | ||
|
|
5c0085880f | ||
|
|
e2a8569940 | ||
|
|
8f852f2e7d | ||
|
|
fa1e8ee426 | ||
|
|
822ba2ae59 | ||
|
|
116025c569 | ||
|
|
a4d0ef6350 | ||
|
|
a9a21aa313 | ||
|
|
1f4fcf1f31 | ||
|
|
a1c1f7b910 | ||
|
|
f38d2e1b89 | ||
|
|
c28004f2a6 | ||
|
|
07172da1bc | ||
|
|
f7b02c01dd | ||
|
|
1d9ee5da3c | ||
|
|
59c43c7904 | ||
|
|
02f73145d6 | ||
|
|
75900f05c9 | ||
|
|
114a875f3d | ||
|
|
b936e91fe9 | ||
|
|
f6570710e7 | ||
|
|
3b4ea27caf | ||
|
|
09c1c715a3 | ||
|
|
7916bd39b4 | ||
|
|
09974b5176 | ||
|
|
8a0dc31ab0 | ||
|
|
2e8a91efda | ||
|
|
534ea3ecac | ||
|
|
5fcdb9e112 | ||
|
|
286271340e | ||
|
|
e82076d558 | ||
|
|
e300440a8b | ||
|
|
dfcdb4ace8 | ||
|
|
ee2d8f84de | ||
|
|
e5e9c33005 | ||
|
|
06a600c7fb | ||
|
|
f018d83951 | ||
|
|
4cb78ab3c7 | ||
|
|
da096553a2 | ||
|
|
0e4cd7f52f | ||
|
|
1a370bfbbe | ||
|
|
4f31b5a214 | ||
|
|
ada5dcced4 | ||
|
|
e718796f23 | ||
|
|
e1b283c14a | ||
|
|
93380f8cbb | ||
|
|
12fdb3427b | ||
|
|
b8effa3a1c | ||
|
|
4e2c6ff8d7 | ||
|
|
4887c697c9 | ||
|
|
ae6af17c74 | ||
|
|
a31f946d6f | ||
|
|
7780fe9472 | ||
|
|
b6bf4d04ff | ||
|
|
442a4fe9cf | ||
|
|
7a98afe6ec | ||
|
|
a4eb3fd997 | ||
|
|
7d7d90e7e0 | ||
|
|
94b0bc1e35 | ||
|
|
6260768e6a | ||
|
|
c41676a21a | ||
|
|
477d8f8b9a | ||
|
|
96543b8337 | ||
|
|
02915582eb | ||
|
|
8a3aa2c767 | ||
|
|
267fd23b26 | ||
|
|
304d7a4395 | ||
|
|
85bb14f04f | ||
|
|
d54ab640c7 | ||
|
|
4133284bc8 | ||
|
|
aa7a667919 | ||
|
|
5e273238ca | ||
|
|
89bd00a4ec | ||
|
|
6df919a917 | ||
|
|
68d00a829e | ||
|
|
6377e92067 | ||
|
|
e99b1598d1 | ||
|
|
c587dbb72a | ||
|
|
4499048d8e | ||
|
|
877605d31b | ||
|
|
b6968d9260 | ||
|
|
8d6f985aea | ||
|
|
db9f74bc78 | ||
|
|
82483a206e | ||
|
|
38b0ed8176 | ||
|
|
ccd06c78b9 | ||
|
|
7a4382fb69 | ||
|
|
80c8259e34 | ||
|
|
f1cefc8900 | ||
|
|
496f190d70 | ||
|
|
512c10ec59 | ||
|
|
ee75b104eb | ||
|
|
72d0dcdaba | ||
|
|
6521e5165c | ||
|
|
f1266a3e81 | ||
|
|
4c6073ebce | ||
|
|
2378e31c5e | ||
|
|
be16cb4190 | ||
|
|
ce905bba41 | ||
|
|
bc1c22cda2 | ||
|
|
2d947a4f53 | ||
|
|
542d5a2451 | ||
|
|
3b777c2764 | ||
|
|
1872a937d5 | ||
|
|
fd9c1d30f9 | ||
|
|
cf0411e7e2 | ||
|
|
8e1bb4b364 | ||
|
|
0d562d4874 | ||
|
|
48ee4add08 | ||
|
|
0374414798 | ||
|
|
5c44f8bbad | ||
|
|
538df1bb6d | ||
|
|
5cb3543899 | ||
|
|
0e09420e7b | ||
|
|
4489e2bf28 | ||
|
|
2579791f51 | ||
|
|
fe60269fdd | ||
|
|
6ff8e06ace | ||
|
|
e8ac258994 | ||
|
|
f186b93c93 | ||
|
|
8af727734e | ||
|
|
ebd640da04 | ||
|
|
625e889c62 | ||
|
|
57e32b47b7 | ||
|
|
62b0ebf2fe | ||
|
|
e1b2f81f43 | ||
|
|
ef63d9dd47 | ||
|
|
cf3a62d201 | ||
|
|
4a0ab4a050 | ||
|
|
8c6a1be070 | ||
|
|
e38ba27a65 | ||
|
|
ada331588f | ||
|
|
f7bd801e00 | ||
|
|
a1d417d8b6 | ||
|
|
0258dd4fed | ||
|
|
a7ab9fd93b | ||
|
|
f48b47c656 | ||
|
|
57c757c0a6 | ||
|
|
194f918c0b | ||
|
|
c2942b37a7 | ||
|
|
e0fefce2a3 | ||
|
|
e3e8f3d7c4 | ||
|
|
689eda4dae | ||
|
|
1c9f59e491 | ||
|
|
0d992a3d1f | ||
|
|
28f8c1cc11 | ||
|
|
7c332a31a8 | ||
|
|
8a7325268a | ||
|
|
c492b5f2dd | ||
|
|
8bf6fd67d1 | ||
|
|
4bc4e0845d | ||
|
|
d261cec3cd | ||
|
|
f3e5045259 | ||
|
|
56e9eda2b9 | ||
|
|
2c0dcd3a2d | ||
|
|
4dca396106 | ||
|
|
000c1f7ec8 | ||
|
|
7ca0996912 | ||
|
|
9b6501787a | ||
|
|
0918e50b05 | ||
|
|
18e6a5491c | ||
|
|
951ed01d6b | ||
|
|
7c28528eac | ||
|
|
676179620a | ||
|
|
bc9d8cc40f | ||
|
|
691665fca8 | ||
|
|
bece2e8689 | ||
|
|
9a628d4165 | ||
|
|
8006996f46 | ||
|
|
85587413d0 | ||
|
|
c281db6b5b | ||
|
|
ec292ca4e1 | ||
|
|
7d36c23d59 | ||
|
|
b6132d2a0f | ||
|
|
dca39348ab | ||
|
|
fb10af9042 | ||
|
|
7d73808d60 | ||
|
|
aa127b1662 | ||
|
|
0b13da35eb | ||
|
|
01a1d814f4 | ||
|
|
c63f6807c4 | ||
|
|
76781e5d75 | ||
|
|
a08356979f | ||
|
|
eb3f1967a5 | ||
|
|
97b3ebe385 | ||
|
|
b231b1ccaf | ||
|
|
bbec4082c0 | ||
|
|
66637e8c03 | ||
|
|
81d4ec1e98 | ||
|
|
c79ec8c37a | ||
|
|
fdcc6b482d | ||
|
|
7ddece1560 | ||
|
|
6bea7f89a8 | ||
|
|
e31ca58a2f | ||
|
|
17894db501 | ||
|
|
20900dafc0 | ||
|
|
96f93cefba | ||
|
|
2f39ab1977 | ||
|
|
315272839d | ||
|
|
a402bfcfb0 | ||
|
|
5dd7c14d36 | ||
|
|
162c477236 | ||
|
|
9c3b72cf3f | ||
|
|
00068d6157 | ||
|
|
74368540ae | ||
|
|
9fe993bec3 | ||
|
|
b5f1296cc2 | ||
|
|
843e9ad254 | ||
|
|
40e63a63e2 | ||
|
|
0f5dd40ff1 | ||
|
|
0c2275ddb1 | ||
|
|
c3a21daf83 | ||
|
|
06ec3bbbb5 | ||
|
|
f0fb065446 | ||
|
|
5fd6dc3b87 | ||
|
|
31550b22b6 | ||
|
|
22c4b5113d | ||
|
|
9a139ea903 | ||
|
|
57d3f3f482 | ||
|
|
9df5e43fae | ||
|
|
53a291aeae | ||
|
|
6c8ae55a68 | ||
|
|
0f1711fe1e | ||
|
|
db5e0ff7a8 | ||
|
|
3d552d7d5d | ||
|
|
3265d49a98 | ||
|
|
f83456a398 | ||
|
|
c61edc13e7 | ||
|
|
0c534b69eb | ||
|
|
2863a14cd1 | ||
|
|
df1bc1a597 | ||
|
|
95363455af | ||
|
|
f0f60c3b7d | ||
|
|
5d4b542995 | ||
|
|
8d47a7b21d | ||
|
|
f3acc89900 | ||
|
|
77fd9172fa | ||
|
|
64e4c1ea6d | ||
|
|
d71d6b265a | ||
|
|
4799ba0069 | ||
|
|
188ad6a571 | ||
|
|
9975a18a29 | ||
|
|
a7a50cfc9a | ||
|
|
7d5bbc3b1e | ||
|
|
9598bb5a68 | ||
|
|
c6ad358751 | ||
|
|
c78f390128 | ||
|
|
73803eaac9 | ||
|
|
50521f7b45 | ||
|
|
cea44e2bee | ||
|
|
3febbec64e | ||
|
|
81ee932e62 | ||
|
|
293400a623 | ||
|
|
ae1072e09f | ||
|
|
811c33b016 | ||
|
|
92fdb7a35f | ||
|
|
f9a617c714 | ||
|
|
51ed824adf | ||
|
|
6be01eac04 | ||
|
|
4350060b0f | ||
|
|
839b9635b9 | ||
|
|
16ae637238 | ||
|
|
4245a38de9 | ||
|
|
fd0d194a8a | ||
|
|
b7f874d1f1 | ||
|
|
c5faddc2a4 | ||
|
|
9f9c9e0e5e | ||
|
|
e239d763dc | ||
|
|
05ab28f11d | ||
|
|
db7b1eea55 | ||
|
|
f515559e56 | ||
|
|
a45e10d64f | ||
|
|
56d99fbd8a | ||
|
|
d1caa75053 | ||
|
|
8ce79e6be8 | ||
|
|
325d6f738c | ||
|
|
5b77e7db8a | ||
|
|
2214caef4b | ||
|
|
30b30695e4 | ||
|
|
da864bf7f7 | ||
|
|
a96b0011f0 | ||
|
|
1e12a86781 | ||
|
|
2136929164 | ||
|
|
bc6a0fc776 | ||
|
|
2053ee00ab | ||
|
|
18dac9ab8a | ||
|
|
1764aa0caf | ||
|
|
8254d0dd10 | ||
|
|
6d0ba5f97b | ||
|
|
70103967ef | ||
|
|
cada523031 | ||
|
|
97c20b181a | ||
|
|
52d1e45b05 | ||
|
|
f08eb3cdf4 | ||
|
|
15b965bb3b | ||
|
|
c43d0866f6 | ||
|
|
122881ddf5 | ||
|
|
d4f6111621 | ||
|
|
153a435257 | ||
|
|
aea6eeda38 | ||
|
|
2ebe46bd05 | ||
|
|
5706bc6205 | ||
|
|
eddca7f3f6 | ||
|
|
56b646a74c | ||
|
|
5411123b8a | ||
|
|
57ae1ee3e9 | ||
|
|
1526fff085 | ||
|
|
20f1a74202 | ||
|
|
e0fae764f1 | ||
|
|
7ca6b6f9a6 | ||
|
|
53ad559da5 | ||
|
|
988a871999 | ||
|
|
a3e250aef5 | ||
|
|
50d23f145b | ||
|
|
f3ea72c234 | ||
|
|
40ff16bdaf | ||
|
|
68392e7ae7 | ||
|
|
25c60c455e | ||
|
|
17565cde75 | ||
|
|
b657301d39 | ||
|
|
e9fdbfabea | ||
|
|
6274dfafdc | ||
|
|
49aa3eb92b | ||
|
|
6d6a243776 | ||
|
|
1a1fee3088 | ||
|
|
a1782182dd |
14
.github/dependabot.yml
vendored
14
.github/dependabot.yml
vendored
@@ -17,3 +17,17 @@ updates:
|
||||
ignore:
|
||||
- dependency-name: '*'
|
||||
update-types: ['version-update:semver-patch', 'version-update:semver-minor']
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "go/extractor"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-name: "golang.org/x/mod"
|
||||
- dependency-name: "golang.org/x/tools"
|
||||
group:
|
||||
extractor-dependencies:
|
||||
patterns:
|
||||
- "golang.org/x/*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
4
.github/workflows/compile-queries.yml
vendored
4
.github/workflows/compile-queries.yml
vendored
@@ -29,9 +29,9 @@ jobs:
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
shell: bash
|
||||
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
|
||||
- name: compile queries - full
|
||||
# do full compile if running on main - this populates the cache
|
||||
if : ${{ github.event_name != 'pull_request' }}
|
||||
shell: bash
|
||||
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
|
||||
|
||||
2
.github/workflows/csharp-qltest.yml
vendored
2
.github/workflows/csharp-qltest.yml
vendored
@@ -91,7 +91,7 @@ jobs:
|
||||
run: |
|
||||
# Generate (Asp)NetCore stubs
|
||||
STUBS_PATH=stubs_output
|
||||
python3 ql/src/Stubs/make_stubs_nuget.py webapp Swashbuckle.AspNetCore.Swagger latest "$STUBS_PATH"
|
||||
python3 ql/src/Stubs/make_stubs_nuget.py webapp Swashbuckle.AspNetCore.Swagger 6.5.0 "$STUBS_PATH"
|
||||
rm -rf ql/test/resources/stubs/_frameworks
|
||||
# Update existing stubs in the repo with the freshly generated ones
|
||||
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
|
||||
|
||||
@@ -498,22 +498,6 @@
|
||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll",
|
||||
"python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.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"
|
||||
],
|
||||
"Typo database": [
|
||||
"javascript/ql/src/Expressions/TypoDatabase.qll",
|
||||
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
## 0.10.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `AnalysedString` class, use the new name `AnalyzedString`.
|
||||
* Deleted the deprecated `isBarrierGuard` predicate from the dataflow library and its uses, use `isBarrier` and the `BarrierGuard` module instead.
|
||||
|
||||
## 0.10.0
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Functions that do not return due to calling functions that don't return (e.g. `exit`) are now detected as
|
||||
non-returning in the IR and dataflow.
|
||||
* Treat functions that reach the end of the function as returning in the IR.
|
||||
They used to be treated as unreachable but it is allowed in C.
|
||||
* The `DataFlow::asDefiningArgument` predicate now takes its argument from the range starting at `1` instead of `2`. Queries that depend on the single-parameter version of `DataFlow::asDefiningArgument` should have their arguments updated accordingly.
|
||||
|
||||
## 0.9.3
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `DataFlow::asDefiningArgument` predicate now takes its argument from the range starting at `1` instead of `2`. Queries that depend on the single-parameter version of `DataFlow::asDefiningArgument` should have their arguments updated accordingly.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Treat functions that reach the end of the function as returning in the IR.
|
||||
They used to be treated as unreachable but it is allowed in C.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Functions that do not return due to calling functions that don't return (e.g. `exit`) are now detected as
|
||||
non-returning in the IR and dataflow.
|
||||
9
cpp/ql/lib/change-notes/released/0.10.0.md
Normal file
9
cpp/ql/lib/change-notes/released/0.10.0.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 0.10.0
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Functions that do not return due to calling functions that don't return (e.g. `exit`) are now detected as
|
||||
non-returning in the IR and dataflow.
|
||||
* Treat functions that reach the end of the function as returning in the IR.
|
||||
They used to be treated as unreachable but it is allowed in C.
|
||||
* The `DataFlow::asDefiningArgument` predicate now takes its argument from the range starting at `1` instead of `2`. Queries that depend on the single-parameter version of `DataFlow::asDefiningArgument` should have their arguments updated accordingly.
|
||||
6
cpp/ql/lib/change-notes/released/0.10.1.md
Normal file
6
cpp/ql/lib/change-notes/released/0.10.1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## 0.10.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `AnalysedString` class, use the new name `AnalyzedString`.
|
||||
* Deleted the deprecated `isBarrierGuard` predicate from the dataflow library and its uses, use `isBarrier` and the `BarrierGuard` module instead.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.9.3
|
||||
lastReleaseVersion: 0.10.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.10.0-dev
|
||||
version: 0.10.1
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -158,9 +158,7 @@ class NameQualifyingElement extends Element, @namequalifyingelement {
|
||||
/**
|
||||
* A special name-qualifying element. For example: `__super`.
|
||||
*/
|
||||
library class SpecialNameQualifyingElement extends NameQualifyingElement,
|
||||
@specialnamequalifyingelement
|
||||
{
|
||||
class SpecialNameQualifyingElement extends NameQualifyingElement, @specialnamequalifyingelement {
|
||||
/** Gets the name of this special qualifying element. */
|
||||
override string getName() { specialnamequalifyingelements(underlyingElement(this), result) }
|
||||
|
||||
|
||||
@@ -73,6 +73,10 @@ private int isSource(Expr bufferExpr, Element why) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `getBufferSize`, but with the `why` column projected away to prevent large duplications. */
|
||||
pragma[nomagic]
|
||||
int getBufferSizeProj(Expr bufferExpr) { result = getBufferSize(bufferExpr, _) }
|
||||
|
||||
/**
|
||||
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
|
||||
*/
|
||||
@@ -87,7 +91,7 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
why = bufferVar and
|
||||
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
|
||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||
result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
|
||||
result = getBufferSizeProj(parentPtr) + bufferSize - parentClass.getSize()
|
||||
|
|
||||
if exists(bufferVar.getType().getSize())
|
||||
then bufferSize = bufferVar.getType().getSize()
|
||||
@@ -95,7 +99,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
)
|
||||
or
|
||||
// dataflow (all sources must be the same size)
|
||||
result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSize(def, _)) and
|
||||
// find reason
|
||||
result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSizeProj(def)) and
|
||||
exists(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | exists(getBufferSize(def, why)))
|
||||
}
|
||||
|
||||
@@ -27,9 +27,6 @@ predicate canValueFlow(Expr fromExpr, Expr toExpr) {
|
||||
fromExpr = toExpr.(ConditionalExpr).getElse()
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AnalyzedString */
|
||||
deprecated class AnalysedString = AnalyzedString;
|
||||
|
||||
/**
|
||||
* An analyzed null terminated string.
|
||||
*/
|
||||
|
||||
@@ -78,7 +78,7 @@ predicate parameterUsePair(Parameter p, VariableAccess va) {
|
||||
/**
|
||||
* Utility class: A definition or use of a stack variable.
|
||||
*/
|
||||
library class DefOrUse extends ControlFlowNodeBase {
|
||||
class DefOrUse extends ControlFlowNodeBase {
|
||||
DefOrUse() {
|
||||
// Uninstantiated templates are purely syntax, and only on instantiation
|
||||
// will they be complete with information about types, conversions, call
|
||||
@@ -140,7 +140,7 @@ library class DefOrUse extends ControlFlowNodeBase {
|
||||
}
|
||||
|
||||
/** A definition of a stack variable. */
|
||||
library class Def extends DefOrUse {
|
||||
class Def extends DefOrUse {
|
||||
Def() { definition(_, this) }
|
||||
|
||||
override SemanticStackVariable getVariable(boolean isDef) {
|
||||
@@ -155,7 +155,7 @@ private predicate parameterIsOverwritten(Function f, Parameter p) {
|
||||
}
|
||||
|
||||
/** A definition of a parameter. */
|
||||
library class ParameterDef extends DefOrUse {
|
||||
class ParameterDef extends DefOrUse {
|
||||
ParameterDef() {
|
||||
// Optimization: parameters that are not overwritten do not require
|
||||
// reachability analysis
|
||||
@@ -169,7 +169,7 @@ library class ParameterDef extends DefOrUse {
|
||||
}
|
||||
|
||||
/** A use of a stack variable. */
|
||||
library class Use extends DefOrUse {
|
||||
class Use extends DefOrUse {
|
||||
Use() { useOfVar(_, this) }
|
||||
|
||||
override SemanticStackVariable getVariable(boolean isDef) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import SSAUtils
|
||||
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
|
||||
* This class provides the standard SSA logic.
|
||||
*/
|
||||
library class StandardSsa extends SsaHelper {
|
||||
class StandardSsa extends SsaHelper {
|
||||
StandardSsa() { this = 0 }
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ private predicate live_at_exit_of_bb(StackVariable v, BasicBlock b) {
|
||||
|
||||
/** Common SSA logic for standard SSA and range-analysis SSA. */
|
||||
cached
|
||||
library class SsaHelper extends int {
|
||||
class SsaHelper extends int {
|
||||
/* 0 = StandardSSA, 1 = RangeSSA */
|
||||
cached
|
||||
SsaHelper() { this in [0 .. 1] }
|
||||
|
||||
@@ -366,12 +366,12 @@ class CompileTimeConstantInt extends Expr {
|
||||
int getIntValue() { result = val }
|
||||
}
|
||||
|
||||
library class CompileTimeVariableExpr extends Expr {
|
||||
class CompileTimeVariableExpr extends Expr {
|
||||
CompileTimeVariableExpr() { not this instanceof CompileTimeConstantInt }
|
||||
}
|
||||
|
||||
/** A helper class for evaluation of expressions. */
|
||||
library class ExprEvaluator extends int {
|
||||
class ExprEvaluator extends int {
|
||||
/*
|
||||
* 0 = ConditionEvaluator,
|
||||
* 1 = SwitchEvaluator,
|
||||
@@ -956,7 +956,7 @@ private predicate returnStmt(Function f, Expr value) {
|
||||
}
|
||||
|
||||
/** A helper class for evaluation of conditions. */
|
||||
library class ConditionEvaluator extends ExprEvaluator {
|
||||
class ConditionEvaluator extends ExprEvaluator {
|
||||
ConditionEvaluator() { this = 0 }
|
||||
|
||||
override predicate interesting(Expr e) {
|
||||
@@ -967,7 +967,7 @@ library class ConditionEvaluator extends ExprEvaluator {
|
||||
}
|
||||
|
||||
/** A helper class for evaluation of switch expressions. */
|
||||
library class SwitchEvaluator extends ExprEvaluator {
|
||||
class SwitchEvaluator extends ExprEvaluator {
|
||||
SwitchEvaluator() { this = 1 }
|
||||
|
||||
override predicate interesting(Expr e) { e = getASwitchExpr(_, _) }
|
||||
@@ -976,7 +976,7 @@ library class SwitchEvaluator extends ExprEvaluator {
|
||||
private int getSwitchValue(Expr e) { exists(SwitchEvaluator x | result = x.getValue(e)) }
|
||||
|
||||
/** A helper class for evaluation of loop entry conditions. */
|
||||
library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
LoopEntryConditionEvaluator() { this in [2 .. 3] }
|
||||
|
||||
abstract override predicate interesting(Expr e);
|
||||
@@ -1149,7 +1149,7 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
}
|
||||
|
||||
/** A helper class for evaluation of while-loop entry conditions. */
|
||||
library class WhileLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator {
|
||||
class WhileLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator {
|
||||
WhileLoopEntryConditionEvaluator() { this = 2 }
|
||||
|
||||
override predicate interesting(Expr e) { exists(WhileStmt while | e = while.getCondition()) }
|
||||
@@ -1162,7 +1162,7 @@ library class WhileLoopEntryConditionEvaluator extends LoopEntryConditionEvaluat
|
||||
}
|
||||
|
||||
/** A helper class for evaluation of for-loop entry conditions. */
|
||||
library class ForLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator {
|
||||
class ForLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator {
|
||||
ForLoopEntryConditionEvaluator() { this = 3 }
|
||||
|
||||
override predicate interesting(Expr e) { exists(ForStmt for | e = for.getCondition()) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -874,28 +874,3 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||
*
|
||||
* A guard that validates some expression.
|
||||
*
|
||||
* To use this in a configuration, extend the class and provide a
|
||||
* characteristic predicate precisely specifying the guard, and override
|
||||
* `checks` to specify what is being validated and in which branch.
|
||||
*
|
||||
* It is important that all extending classes in scope are disjoint.
|
||||
*/
|
||||
deprecated class BarrierGuard extends GuardCondition {
|
||||
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
|
||||
abstract predicate checks(Expr e, boolean b);
|
||||
|
||||
/** Gets a node guarded by this guard. */
|
||||
final ExprNode getAGuardedNode() {
|
||||
exists(SsaDefinition def, Variable v, boolean branch |
|
||||
result.getExpr() = def.getAUse(v) and
|
||||
this.checks(def.getAUse(v), branch) and
|
||||
this.controls(result.getExpr().getBasicBlock(), branch)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,33 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
|
||||
*/
|
||||
|
||||
@@ -116,33 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
|
||||
*/
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -91,21 +91,6 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
@@ -225,29 +210,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private FlowState relevantState(Configuration config) {
|
||||
config.isSource(_, result) or
|
||||
config.isSink(_, result) or
|
||||
@@ -288,9 +250,7 @@ private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrier(Node node, FlowState state) {
|
||||
getConfig(state).isBarrier(node, getState(state)) or
|
||||
getConfig(state).isBarrier(node) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state))
|
||||
getConfig(state).isBarrier(node)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) }
|
||||
|
||||
@@ -555,7 +555,7 @@ predicate instructionForFullyConvertedCall(Instruction instr, CallInstruction ca
|
||||
}
|
||||
|
||||
/** Holds if `node` represents the output node for `call`. */
|
||||
private predicate simpleOutNode(Node node, CallInstruction call) {
|
||||
predicate simpleOutNode(Node node, CallInstruction call) {
|
||||
operandForFullyConvertedCall(node.asOperand(), call)
|
||||
or
|
||||
instructionForFullyConvertedCall(node.asInstruction(), call)
|
||||
|
||||
@@ -1696,16 +1696,7 @@ private module Cached {
|
||||
// Reverse flow: data that flows from the definition node back into the indirection returned
|
||||
// by a function. This allows data to flow 'in' through references returned by a modeled
|
||||
// function such as `operator[]`.
|
||||
exists(Operand address, int indirectionIndex |
|
||||
nodeHasOperand(nodeTo.(IndirectReturnOutNode), address, indirectionIndex)
|
||||
|
|
||||
exists(StoreInstruction store |
|
||||
nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and
|
||||
store.getDestinationAddressOperand() = address
|
||||
)
|
||||
or
|
||||
Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex)
|
||||
)
|
||||
reverseFlow(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) {
|
||||
@@ -1736,6 +1727,39 @@ private module Cached {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate reverseFlow(Node nodeFrom, Node nodeTo) {
|
||||
reverseFlowOperand(nodeFrom, nodeTo)
|
||||
or
|
||||
reverseFlowInstruction(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
private predicate reverseFlowOperand(Node nodeFrom, IndirectReturnOutNode nodeTo) {
|
||||
exists(Operand address, int indirectionIndex |
|
||||
nodeHasOperand(nodeTo, address, indirectionIndex)
|
||||
|
|
||||
exists(StoreInstruction store |
|
||||
nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and
|
||||
store.getDestinationAddressOperand() = address
|
||||
)
|
||||
or
|
||||
// We also want a write coming out of an `OutNode` to flow `nodeTo`.
|
||||
// This is different from `reverseFlowInstruction` since `nodeFrom` can never
|
||||
// be an `OutNode` when it's defined by an instruction.
|
||||
Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate reverseFlowInstruction(Node nodeFrom, IndirectReturnOutNode nodeTo) {
|
||||
exists(Instruction address, int indirectionIndex |
|
||||
nodeHasInstruction(nodeTo, address, indirectionIndex)
|
||||
|
|
||||
exists(StoreInstruction store |
|
||||
nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and
|
||||
store.getDestinationAddress() = address
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
@@ -2213,35 +2237,3 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||
*
|
||||
* A guard that validates some instruction.
|
||||
*
|
||||
* To use this in a configuration, extend the class and provide a
|
||||
* characteristic predicate precisely specifying the guard, and override
|
||||
* `checks` to specify what is being validated and in which branch.
|
||||
*
|
||||
* It is important that all extending classes in scope are disjoint.
|
||||
*/
|
||||
deprecated class BarrierGuard extends IRGuardCondition {
|
||||
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
|
||||
predicate checksInstr(Instruction instr, boolean b) { none() }
|
||||
|
||||
/** Override this predicate to hold if this guard validates `expr` upon evaluating to `b`. */
|
||||
predicate checks(Expr e, boolean b) { none() }
|
||||
|
||||
/** Gets a node guarded by this guard. */
|
||||
final Node getAGuardedNode() {
|
||||
exists(ValueNumber value, boolean edge |
|
||||
(
|
||||
this.checksInstr(value.getAnInstruction(), edge)
|
||||
or
|
||||
this.checks(value.getAnInstruction().getConvertedResultExpression(), edge)
|
||||
) and
|
||||
result.asInstruction() = value.getAnInstruction() and
|
||||
this.controls(result.asInstruction().getBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import DataFlowUtil
|
||||
private import DataFlowPrivate
|
||||
private import SsaInternals as Ssa
|
||||
|
||||
/**
|
||||
@@ -35,7 +36,7 @@ DataFlow::Node callInput(CallInstruction call, FunctionInput input) {
|
||||
*/
|
||||
Node callOutput(CallInstruction call, FunctionOutput output) {
|
||||
// The return value
|
||||
result.asInstruction() = call and
|
||||
simpleOutNode(result, call) and
|
||||
output.isReturnValue()
|
||||
or
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
@@ -82,7 +83,7 @@ Node callOutput(CallInstruction call, FunctionOutput output, int d) {
|
||||
// If there isn't an indirect out node for the call with indirection `d` then
|
||||
// we conflate this with the underlying `CallInstruction`.
|
||||
not exists(getIndirectReturnOutNode(call, d)) and
|
||||
n.asInstruction() = result.asInstruction()
|
||||
n = result
|
||||
or
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
exists(Operand operand, int indirectionIndex |
|
||||
|
||||
@@ -374,6 +374,8 @@ module ProductFlow {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) { Config::isBarrier1(node, state) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { Config::isBarrier1(node) }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { Config::isBarrierOut1(node) }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
@@ -408,6 +410,8 @@ module ProductFlow {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) { Config::isBarrier2(node, state) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { Config::isBarrier2(node) }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { Config::isBarrierOut2(node) }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
|
||||
@@ -116,33 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
|
||||
*/
|
||||
|
||||
@@ -116,33 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
|
||||
*/
|
||||
|
||||
@@ -116,33 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports
|
||||
import Imports::EdgeKind
|
||||
private import Cached
|
||||
|
||||
/**
|
||||
* Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the
|
||||
* sort keys of the block (derived from its first instruction)
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate blockSortKeys(
|
||||
IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2
|
||||
) {
|
||||
block.getEnclosingIRFunction() = func and
|
||||
block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if block.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
@@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
exists(IRFunction func |
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2)
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction {
|
||||
|
||||
private int getLineRank() {
|
||||
this.shouldGenerateDumpStrings() and
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr =
|
||||
getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(),
|
||||
this.getLocation().getStartLine())
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
exists(IRFunction enclosing, Language::File file, int line |
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr = getAnInstructionAtLine(enclosing, file, line)
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports
|
||||
import Imports::EdgeKind
|
||||
private import Cached
|
||||
|
||||
/**
|
||||
* Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the
|
||||
* sort keys of the block (derived from its first instruction)
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate blockSortKeys(
|
||||
IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2
|
||||
) {
|
||||
block.getEnclosingIRFunction() = func and
|
||||
block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if block.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
@@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
exists(IRFunction func |
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2)
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction {
|
||||
|
||||
private int getLineRank() {
|
||||
this.shouldGenerateDumpStrings() and
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr =
|
||||
getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(),
|
||||
this.getLocation().getStartLine())
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
exists(IRFunction enclosing, Language::File file, int line |
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr = getAnInstructionAtLine(enclosing, file, line)
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -423,7 +423,12 @@ private module CachedForDebugging {
|
||||
cached
|
||||
predicate instructionHasSortKeys(Instruction instruction, int key1, int key2) {
|
||||
key1 = getInstructionTranslatedElement(instruction).getId() and
|
||||
getInstructionTag(instruction) =
|
||||
getInstructionTag(instruction) = tagByRank(key2)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private InstructionTag tagByRank(int key2) {
|
||||
result =
|
||||
rank[key2](InstructionTag tag, string tagId |
|
||||
tagId = getInstructionTagId(tag)
|
||||
|
|
||||
|
||||
@@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports
|
||||
import Imports::EdgeKind
|
||||
private import Cached
|
||||
|
||||
/**
|
||||
* Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the
|
||||
* sort keys of the block (derived from its first instruction)
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate blockSortKeys(
|
||||
IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2
|
||||
) {
|
||||
block.getEnclosingIRFunction() = func and
|
||||
block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if block.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
@@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock {
|
||||
exists(IRConfiguration::IRConfiguration config |
|
||||
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
then sortOverride = 0
|
||||
else sortOverride = 1
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
exists(IRFunction func |
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2)
|
||||
|
|
||||
funcBlock order by sortOverride, sortKey1, sortKey2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction {
|
||||
|
||||
private int getLineRank() {
|
||||
this.shouldGenerateDumpStrings() and
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr =
|
||||
getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(),
|
||||
this.getLocation().getStartLine())
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
exists(IRFunction enclosing, Language::File file, int line |
|
||||
this =
|
||||
rank[result](Instruction instr |
|
||||
instr = getAnInstructionAtLine(enclosing, file, line)
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ private import RangeAnalysisUtils
|
||||
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
|
||||
* This class provides the range-analysis SSA logic.
|
||||
*/
|
||||
library class RangeSsa extends SsaHelper {
|
||||
class RangeSsa extends SsaHelper {
|
||||
RangeSsa() { this = 1 }
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,17 +60,31 @@ private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
|
||||
|
||||
private VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
|
||||
|
||||
/**
|
||||
* Gets a (sub)expression that may be the result of evaluating `size`.
|
||||
*
|
||||
* For example, `getASizeCandidate(a ? b : c)` gives `a ? b : c`, `b` and `c`.
|
||||
*/
|
||||
bindingset[size]
|
||||
pragma[inline_late]
|
||||
private Expr getASizeCandidate(Expr size) {
|
||||
result = size
|
||||
or
|
||||
result = [size.(ConditionalExpr).getThen(), size.(ConditionalExpr).getElse()]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `(n, state)` pair represents the source of flow for the size
|
||||
* expression associated with `alloc`.
|
||||
*/
|
||||
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
|
||||
exists(VariableAccess va, Expr size, int delta |
|
||||
exists(VariableAccess va, Expr size, int delta, Expr s |
|
||||
size = alloc.getSizeExpr() and
|
||||
s = getASizeCandidate(size) and
|
||||
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
|
||||
va = unique( | | getAVariableAccess(size)) and
|
||||
va = unique( | | getAVariableAccess(s)) and
|
||||
// Compute `delta` as the constant difference between `x` and `x + 1`.
|
||||
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
|
||||
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = s),
|
||||
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
|
||||
n.asExpr() = va and
|
||||
state = delta
|
||||
@@ -284,10 +298,33 @@ private module Config implements ProductFlow::StateConfigSig {
|
||||
pointerAddInstructionHasBounds0(_, allocSink, sizeSink, sizeAddend)
|
||||
}
|
||||
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
|
||||
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
|
||||
node = SizeBarrier::getABarrierNode(state)
|
||||
}
|
||||
|
||||
predicate isBarrier2(DataFlow::Node node) {
|
||||
// Block flow from `*p` to `*(p + n)` when `n` is not `0`. This removes
|
||||
// false positives
|
||||
// when tracking the size of the allocation as an element of an array such
|
||||
// as:
|
||||
// ```
|
||||
// size_t* p = new size_t[n];
|
||||
// ...
|
||||
// p[0] = n;
|
||||
// int i = p[1];
|
||||
// p[i] = ...
|
||||
// ```
|
||||
// In the above case, this barrier blocks flow from the indirect node
|
||||
// for `p` to `p[1]`.
|
||||
exists(Operand operand, PointerAddInstruction add |
|
||||
node.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
|
||||
add.getLeftOperand() = operand and
|
||||
add.getRight().(ConstantInstruction).getValue() != "0"
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrierIn1(DataFlow::Node node) { isSourcePair(node, _, _, _) }
|
||||
|
||||
predicate isBarrierOut2(DataFlow::Node node) {
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
## 0.8.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* The query `cpp/redundant-null-check-simple` has been promoted to Code Scanning. The query finds cases where a pointer is compared to null after it has already been dereferenced. Such comparisons likely indicate a bug at the place where the pointer is dereferenced, or where the pointer is compared to null.
|
||||
|
||||
Note: This query was incorrectly noted as being promoted to Code Scanning in CodeQL version 2.14.6.
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
* The `cpp/double-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
* The `cpp/use-after-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The queries `cpp/double-free` and `cpp/use-after-free` find fewer false positives
|
||||
in cases where a non-returning function is called.
|
||||
* The number of duplicated dataflow paths reported by queries has been significantly reduced.
|
||||
|
||||
## 0.7.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
* it should be moved before the dereference.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id cpp/redundant-null-check-simple
|
||||
* @tags reliability
|
||||
* correctness
|
||||
* security
|
||||
* external/cwe/cwe-476
|
||||
*/
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ private predicate annotatesAtPosition(SalPosition pos, DeclarationEntry d, File
|
||||
* A SAL element, that is, a SAL annotation or a declaration entry
|
||||
* that may have SAL annotations.
|
||||
*/
|
||||
library class SalElement extends Element {
|
||||
class SalElement extends Element {
|
||||
SalElement() {
|
||||
containsSalAnnotation(this.(DeclarationEntry).getFile()) or
|
||||
this instanceof SalAnnotation
|
||||
|
||||
@@ -13,15 +13,13 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
|
||||
import TaintedWithPath
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.ir.IR
|
||||
import Flow::PathGraph
|
||||
|
||||
/** A call that prints its arguments to `stdout`. */
|
||||
class PrintStdoutCall extends FunctionCall {
|
||||
PrintStdoutCall() {
|
||||
this.getTarget().hasGlobalOrStdName("puts") or
|
||||
this.getTarget().hasGlobalOrStdName("printf")
|
||||
}
|
||||
PrintStdoutCall() { this.getTarget().hasGlobalOrStdName(["puts", "printf"]) }
|
||||
}
|
||||
|
||||
/** A read of the QUERY_STRING environment variable */
|
||||
@@ -29,19 +27,25 @@ class QueryString extends EnvironmentRead {
|
||||
QueryString() { this.getEnvironmentVariable() = "QUERY_STRING" }
|
||||
}
|
||||
|
||||
class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSource(Expr source) { source instanceof QueryString }
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asIndirectExpr() instanceof QueryString }
|
||||
|
||||
override predicate isSink(Element tainted) {
|
||||
exists(PrintStdoutCall call | call.getAnArgument() = tainted)
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(PrintStdoutCall call | call.getAnArgument() = [node.asIndirectExpr(), node.asExpr()])
|
||||
}
|
||||
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
|
||||
}
|
||||
}
|
||||
|
||||
from QueryString query, Element printedArg, PathNode sourceNode, PathNode sinkNode
|
||||
where taintedWithPath(query, printedArg, sourceNode, sinkNode)
|
||||
select printedArg, sourceNode, sinkNode, "Cross-site scripting vulnerability due to $@.", query,
|
||||
"this query data"
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
from QueryString query, Flow::PathNode sourceNode, Flow::PathNode sinkNode
|
||||
where
|
||||
Flow::flowPath(sourceNode, sinkNode) and
|
||||
query = sourceNode.getNode().asIndirectExpr()
|
||||
select sinkNode.getNode(), sourceNode, sinkNode, "Cross-site scripting vulnerability due to $@.",
|
||||
query, "this query data"
|
||||
|
||||
@@ -82,36 +82,20 @@ module ValidState {
|
||||
* library will perform, and visit all the places where the size argument is modified.
|
||||
* 2. Once that dataflow traversal is done, we accumulate the offsets added at each places
|
||||
* where the offset is modified (see `validStateImpl`).
|
||||
*
|
||||
* Because we want to guarantee that each place where we modify the offset has a `PathNode`
|
||||
* we "flip" a boolean flow state in each `isAdditionalFlowStep`. This ensures that the node
|
||||
* has a corresponding `PathNode`.
|
||||
*/
|
||||
private module ValidStateConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = boolean;
|
||||
private module ValidStateConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { hasSize(_, source, _) }
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
hasSize(_, source, _) and
|
||||
state = false
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { isSinkPairImpl(_, _, sink, _, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
isSinkPairImpl(_, _, sink, _, _) and
|
||||
state = [false, true]
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
isAdditionalFlowStep2(node1, node2, _) and
|
||||
state1 = [false, true] and
|
||||
state2 = state1.booleanNot()
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalFlowStep2(node1, node2, _)
|
||||
}
|
||||
|
||||
predicate includeHiddenNodes() { any() }
|
||||
}
|
||||
|
||||
private import DataFlow::GlobalWithState<ValidStateConfig>
|
||||
private import DataFlow::Global<ValidStateConfig>
|
||||
|
||||
private predicate inLoop(PathNode n) { n.getASuccessor+() = n }
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The number of duplicated dataflow paths reported by queries has been significantly reduced.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The queries `cpp/double-free` and `cpp/use-after-free` find fewer false positives
|
||||
in cases where a non-returning function is called.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The `cpp/double-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The `cpp/use-after-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
12
cpp/ql/src/change-notes/released/0.8.0.md
Normal file
12
cpp/ql/src/change-notes/released/0.8.0.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## 0.8.0
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
* The `cpp/double-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
* The `cpp/use-after-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The queries `cpp/double-free` and `cpp/use-after-free` find fewer false positives
|
||||
in cases where a non-returning function is called.
|
||||
* The number of duplicated dataflow paths reported by queries has been significantly reduced.
|
||||
7
cpp/ql/src/change-notes/released/0.8.1.md
Normal file
7
cpp/ql/src/change-notes/released/0.8.1.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 0.8.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* The query `cpp/redundant-null-check-simple` has been promoted to Code Scanning. The query finds cases where a pointer is compared to null after it has already been dereferenced. Such comparisons likely indicate a bug at the place where the pointer is dereferenced, or where the pointer is compared to null.
|
||||
|
||||
Note: This query was incorrectly noted as being promoted to Code Scanning in CodeQL version 2.14.6.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.5
|
||||
lastReleaseVersion: 0.8.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.8.0-dev
|
||||
version: 0.8.1
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
failures
|
||||
astTypeBugs
|
||||
irTypeBugs
|
||||
failures
|
||||
|
||||
@@ -16,18 +16,18 @@ edges
|
||||
| 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:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | path indirection |
|
||||
| test.cpp:106:20:106:38 | call to getenv | test.cpp:107:33:107:36 | path indirection |
|
||||
| test.cpp:106:20:106:38 | call to getenv indirection | 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:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | path indirection |
|
||||
| test.cpp:113:20:113:38 | call to getenv | test.cpp:114:19:114:22 | path indirection |
|
||||
| test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:19:114:22 | path indirection |
|
||||
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
|
||||
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
|
||||
| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:10:114:23 | call to operator+ |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:10:114:23 | call to operator+ |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | call to operator+ |
|
||||
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | path indirection |
|
||||
| test.cpp:119:20:119:38 | call to getenv | test.cpp:120:19:120:22 | path indirection |
|
||||
| test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:19:120:22 | path indirection |
|
||||
| test.cpp:120:17:120:17 | call to operator+ | 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 to operator+ |
|
||||
@@ -91,12 +91,12 @@ nodes
|
||||
| test.cpp:93:11:93:14 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:93:17:93:24 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:94:45:94:48 | path indirection | semmle.label | path indirection |
|
||||
| test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:106:20:106:38 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:106:20:106:38 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
|
||||
| test.cpp:107:33:107:36 | path indirection | semmle.label | path indirection |
|
||||
| test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection |
|
||||
| test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:113:20:113:38 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:113:20:113:38 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
|
||||
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
|
||||
@@ -104,7 +104,7 @@ nodes
|
||||
| test.cpp:114:19:114:22 | path indirection | semmle.label | path indirection |
|
||||
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
|
||||
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
|
||||
| test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:119:20:119:38 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:119:20:119:38 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection |
|
||||
| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ |
|
||||
@@ -158,13 +158,13 @@ subpaths
|
||||
| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument |
|
||||
| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument |
|
||||
| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | path indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument |
|
||||
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
|
||||
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
|
||||
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
|
||||
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv indirection | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
|
||||
| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument |
|
||||
| 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:177:13:177:17 | strncat output argument | strncat output argument |
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
edges
|
||||
| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query |
|
||||
| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
|
||||
| search.c:55:17:55:25 | raw_query | search.c:14:24:14:28 | query |
|
||||
| search.c:57:17:57:25 | raw_query | search.c:22:24:22:28 | query |
|
||||
subpaths
|
||||
| search.c:14:24:14:28 | query indirection | search.c:17:8:17:12 | query indirection |
|
||||
| search.c:22:24:22:28 | query indirection | search.c:23:39:23:43 | query indirection |
|
||||
| search.c:55:24:55:28 | query indirection | search.c:62:8:62:17 | query_text indirection |
|
||||
| search.c:67:21:67:26 | call to getenv indirection | search.c:71:17:71:25 | raw_query indirection |
|
||||
| search.c:67:21:67:26 | call to getenv indirection | search.c:73:17:73:25 | raw_query indirection |
|
||||
| search.c:67:21:67:26 | call to getenv indirection | search.c:77:17:77:25 | raw_query indirection |
|
||||
| search.c:71:17:71:25 | raw_query indirection | search.c:14:24:14:28 | query indirection |
|
||||
| search.c:73:17:73:25 | raw_query indirection | search.c:22:24:22:28 | query indirection |
|
||||
| search.c:77:17:77:25 | raw_query indirection | search.c:55:24:55:28 | query indirection |
|
||||
nodes
|
||||
| search.c:14:24:14:28 | query | semmle.label | query |
|
||||
| search.c:17:8:17:12 | query | semmle.label | query |
|
||||
| search.c:17:8:17:12 | query | semmle.label | query |
|
||||
| search.c:22:24:22:28 | query | semmle.label | query |
|
||||
| search.c:23:39:23:43 | query | semmle.label | query |
|
||||
| search.c:23:39:23:43 | query | semmle.label | query |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:55:17:55:25 | raw_query | semmle.label | raw_query |
|
||||
| search.c:57:17:57:25 | raw_query | semmle.label | raw_query |
|
||||
| search.c:14:24:14:28 | query indirection | semmle.label | query indirection |
|
||||
| search.c:17:8:17:12 | query indirection | semmle.label | query indirection |
|
||||
| search.c:22:24:22:28 | query indirection | semmle.label | query indirection |
|
||||
| search.c:23:39:23:43 | query indirection | semmle.label | query indirection |
|
||||
| search.c:55:24:55:28 | query indirection | semmle.label | query indirection |
|
||||
| search.c:62:8:62:17 | query_text indirection | semmle.label | query_text indirection |
|
||||
| search.c:67:21:67:26 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| search.c:71:17:71:25 | raw_query indirection | semmle.label | raw_query indirection |
|
||||
| search.c:73:17:73:25 | raw_query indirection | semmle.label | raw_query indirection |
|
||||
| search.c:77:17:77:25 | raw_query indirection | semmle.label | raw_query indirection |
|
||||
subpaths
|
||||
#select
|
||||
| search.c:17:8:17:12 | query | search.c:51:21:51:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |
|
||||
| search.c:23:39:23:43 | query | search.c:51:21:51:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |
|
||||
| search.c:17:8:17:12 | query indirection | search.c:67:21:67:26 | call to getenv indirection | search.c:17:8:17:12 | query indirection | Cross-site scripting vulnerability due to $@. | search.c:67:21:67:26 | call to getenv | this query data |
|
||||
| search.c:23:39:23:43 | query indirection | search.c:67:21:67:26 | call to getenv indirection | search.c:23:39:23:43 | query indirection | Cross-site scripting vulnerability due to $@. | search.c:67:21:67:26 | call to getenv | this query data |
|
||||
| search.c:62:8:62:17 | query_text indirection | search.c:67:21:67:26 | call to getenv indirection | search.c:62:8:62:17 | query_text indirection | Cross-site scripting vulnerability due to $@. | search.c:67:21:67:26 | call to getenv | this query data |
|
||||
|
||||
@@ -47,6 +47,22 @@ void good_server2(char* query) {
|
||||
printf("\n<p>%i</p>\n", i);
|
||||
}
|
||||
|
||||
typedef unsigned long size_t;
|
||||
size_t strlen(const char *s);
|
||||
char *strcpy(char *dst, const char *src);
|
||||
char *strcat(char *s1, const char *s2);
|
||||
|
||||
void bad_server3(char* query) {
|
||||
char query_text[strlen(query) + 8];
|
||||
strcpy(query_text, "query: ");
|
||||
strcat(query_text, query);
|
||||
|
||||
puts("<p>Query results for ");
|
||||
// BAD: Printing out an HTTP parameter with no escaping
|
||||
puts(query_text);
|
||||
puts("\n<p>\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* raw_query = getenv("QUERY_STRING");
|
||||
if (strcmp("good1", argv[0]) == 0) {
|
||||
@@ -57,5 +73,7 @@ int main(int argc, char** argv) {
|
||||
bad_server2(raw_query);
|
||||
} else if (strcmp("good2", argv[0]) == 0) {
|
||||
good_server2(raw_query);
|
||||
} else if (strcmp("bad3", argv[0]) == 0) {
|
||||
bad_server3(raw_query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,33 +5,33 @@ edges
|
||||
| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size |
|
||||
| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:17:50:30 | size |
|
||||
| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... |
|
||||
| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:124:18:124:31 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... |
|
||||
| test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:133:19:133:32 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:133:19:133:32 | call to getenv indirection | test.cpp:135:10:135:27 | ... * ... |
|
||||
| test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:148:20:148:33 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:148:20:148:33 | call to getenv indirection | test.cpp:152:11:152:28 | ... * ... |
|
||||
| test.cpp:209:8:209:23 | get_tainted_size indirection | test.cpp:241:9:241:24 | call to get_tainted_size |
|
||||
| test.cpp:211:14:211:19 | call to getenv | test.cpp:209:8:209:23 | get_tainted_size indirection |
|
||||
| test.cpp:211:14:211:27 | call to getenv | test.cpp:209:8:209:23 | get_tainted_size indirection |
|
||||
| test.cpp:211:14:211:27 | call to getenv indirection | test.cpp:209:8:209:23 | get_tainted_size indirection |
|
||||
| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size |
|
||||
| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:10:247:19 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv | test.cpp:245:11:245:20 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv | test.cpp:247:10:247:19 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:239:9:239:18 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:245:11:245:20 | local_size |
|
||||
| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:247:10:247:19 | local_size |
|
||||
| test.cpp:247:10:247:19 | local_size | test.cpp:230:21:230:21 | s |
|
||||
| test.cpp:250:20:250:27 | out_size | test.cpp:289:17:289:20 | get_size output argument |
|
||||
| test.cpp:250:20:250:27 | out_size | test.cpp:305:18:305:21 | get_size output argument |
|
||||
| test.cpp:251:18:251:23 | call to getenv | test.cpp:250:20:250:27 | out_size |
|
||||
| test.cpp:251:18:251:31 | call to getenv | test.cpp:250:20:250:27 | out_size |
|
||||
| test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:250:20:250:27 | out_size |
|
||||
| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:259:20:259:33 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:259:20:259:33 | call to getenv indirection | test.cpp:263:11:263:29 | ... * ... |
|
||||
| test.cpp:289:17:289:20 | get_size output argument | test.cpp:291:11:291:28 | ... * ... |
|
||||
| test.cpp:305:18:305:21 | get_size output argument | test.cpp:308:10:308:27 | ... * ... |
|
||||
| test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size |
|
||||
| test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size |
|
||||
| test.cpp:353:18:353:31 | call to getenv | test.cpp:355:35:355:38 | size |
|
||||
| test.cpp:353:18:353:31 | call to getenv | test.cpp:356:35:356:38 | size |
|
||||
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size |
|
||||
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size |
|
||||
nodes
|
||||
@@ -42,37 +42,37 @@ nodes
|
||||
| test.cpp:49:32:49:35 | size | semmle.label | size |
|
||||
| test.cpp:50:17:50:30 | size | semmle.label | size |
|
||||
| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:124:18:124:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:124:18:124:31 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:124:18:124:31 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:133:19:133:24 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:133:19:133:32 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:133:19:133:32 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:148:20:148:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:148:20:148:33 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:148:20:148:33 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:209:8:209:23 | get_tainted_size indirection | semmle.label | get_tainted_size indirection |
|
||||
| test.cpp:211:14:211:19 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:211:14:211:27 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:211:14:211:27 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:230:21:230:21 | s | semmle.label | s |
|
||||
| test.cpp:231:21:231:21 | s | semmle.label | s |
|
||||
| test.cpp:237:24:237:29 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:237:24:237:37 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:237:24:237:37 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
|
||||
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
|
||||
| test.cpp:245:11:245:20 | local_size | semmle.label | local_size |
|
||||
| test.cpp:247:10:247:19 | local_size | semmle.label | local_size |
|
||||
| test.cpp:250:20:250:27 | out_size | semmle.label | out_size |
|
||||
| test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:251:18:251:31 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:251:18:251:31 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:259:20:259:25 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:259:20:259:33 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:259:20:259:33 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:289:17:289:20 | get_size output argument | semmle.label | get_size output argument |
|
||||
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:305:18:305:21 | get_size output argument | semmle.label | get_size output argument |
|
||||
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:353:18:353:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:353:18:353:31 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:353:18:353:31 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:355:35:355:38 | size | semmle.label | size |
|
||||
| test.cpp:356:35:356:38 | size | semmle.label | size |
|
||||
@@ -84,27 +84,27 @@ subpaths
|
||||
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
|
||||
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:17:50:30 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
|
||||
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
|
||||
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:133:19:133:24 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:32 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:133:19:133:32 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:32 | call to getenv indirection | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:133:19:133:32 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:148:20:148:25 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:33 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:148:20:148:33 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:33 | call to getenv indirection | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:148:20:148:33 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:37 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:37 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:19 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:27 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:27 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:27 | call to getenv indirection | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:27 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:37 | call to getenv | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:25 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:33 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:33 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:33 | call to getenv indirection | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:33 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:31 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:31 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:31 | call to getenv | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv indirection | user input (an environment variable) |
|
||||
| test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:31 | call to getenv | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv | user input (an environment variable) |
|
||||
| test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv indirection | user input (an environment variable) |
|
||||
|
||||
@@ -46,7 +46,6 @@ edges
|
||||
| test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | ... = ... |
|
||||
| test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | ... = ... |
|
||||
| test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:22 | ... = ... |
|
||||
| test.cpp:248:13:248:36 | call to realloc | test.cpp:254:9:254:16 | ... = ... |
|
||||
| test.cpp:260:13:260:24 | new[] | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:260:13:260:24 | new[] | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... |
|
||||
@@ -182,6 +181,12 @@ edges
|
||||
| test.cpp:833:37:833:39 | end | test.cpp:815:52:815:54 | end |
|
||||
| test.cpp:841:18:841:35 | call to malloc | test.cpp:842:3:842:20 | ... = ... |
|
||||
| test.cpp:848:20:848:37 | call to malloc | test.cpp:849:5:849:22 | ... = ... |
|
||||
| test.cpp:856:12:856:35 | call to malloc | test.cpp:857:16:857:29 | ... + ... |
|
||||
| test.cpp:856:12:856:35 | call to malloc | test.cpp:857:16:857:29 | ... + ... |
|
||||
| test.cpp:856:12:856:35 | call to malloc | test.cpp:860:5:860:11 | ... = ... |
|
||||
| test.cpp:857:16:857:29 | ... + ... | test.cpp:857:16:857:29 | ... + ... |
|
||||
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... |
|
||||
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... |
|
||||
nodes
|
||||
| test.cpp:4:15:4:33 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -215,8 +220,6 @@ nodes
|
||||
| test.cpp:232:3:232:20 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:238:20:238:32 | new[] | semmle.label | new[] |
|
||||
| test.cpp:239:5:239:22 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:248:13:248:36 | call to realloc | semmle.label | call to realloc |
|
||||
| test.cpp:254:9:254:16 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:260:13:260:24 | new[] | semmle.label | new[] |
|
||||
| test.cpp:261:14:261:21 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -310,6 +313,10 @@ nodes
|
||||
| test.cpp:842:3:842:20 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:848:20:848:37 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:849:5:849:22 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:856:12:856:35 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:860:5:860:11 | ... = ... | semmle.label | ... = ... |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:33 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:33 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
|
||||
@@ -322,7 +329,6 @@ subpaths
|
||||
| test.cpp:213:5:213:13 | ... = ... | test.cpp:205:15:205:33 | call to malloc | test.cpp:213:5:213:13 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:205:15:205:33 | call to malloc | call to malloc | test.cpp:206:21:206:23 | len | len |
|
||||
| test.cpp:232:3:232:20 | ... = ... | test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:231:18:231:30 | new[] | new[] | test.cpp:232:11:232:15 | index | index |
|
||||
| test.cpp:239:5:239:22 | ... = ... | test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:22 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:238:20:238:32 | new[] | new[] | test.cpp:239:13:239:17 | index | index |
|
||||
| test.cpp:254:9:254:16 | ... = ... | test.cpp:248:13:248:36 | call to realloc | test.cpp:254:9:254:16 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:13:248:36 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
|
||||
| test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
|
||||
| test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
|
||||
| test.cpp:358:14:358:26 | end_plus_one indirection | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | end_plus_one indirection | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
|
||||
@@ -348,3 +354,4 @@ subpaths
|
||||
| test.cpp:821:7:821:12 | ... = ... | test.cpp:793:14:793:32 | call to malloc | test.cpp:821:7:821:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:793:14:793:32 | call to malloc | call to malloc | test.cpp:794:21:794:24 | size | size |
|
||||
| test.cpp:842:3:842:20 | ... = ... | test.cpp:841:18:841:35 | call to malloc | test.cpp:842:3:842:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:841:18:841:35 | call to malloc | call to malloc | test.cpp:842:11:842:15 | index | index |
|
||||
| test.cpp:849:5:849:22 | ... = ... | test.cpp:848:20:848:37 | call to malloc | test.cpp:849:5:849:22 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:848:20:848:37 | call to malloc | call to malloc | test.cpp:849:13:849:17 | index | index |
|
||||
| test.cpp:860:5:860:11 | ... = ... | test.cpp:856:12:856:35 | call to malloc | test.cpp:860:5:860:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:856:12:856:35 | call to malloc | call to malloc | test.cpp:857:21:857:28 | ... + ... | ... + ... |
|
||||
|
||||
@@ -251,7 +251,7 @@ void test17(unsigned *p, unsigned x, unsigned k) {
|
||||
// The following access is okay because:
|
||||
// n = 3*p[0] + k >= p[0] + k >= p[1] + k > p[1] = i
|
||||
// (where p[0] denotes the original value for p[0])
|
||||
p[i] = x; // $ alloc=L248 deref=L254 // GOOD [FALSE POSITIVE]
|
||||
p[i] = x; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,4 +848,15 @@ void test16_with_malloc(size_t index) {
|
||||
int* newname = (int*)malloc(size);
|
||||
newname[index] = 0; // $ SPURIOUS: alloc=L848 deref=L849 // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
# define MyMalloc(size) malloc(((size) == 0 ? 1 : (size)))
|
||||
|
||||
void test_regression(size_t size) {
|
||||
int* p = (int*)MyMalloc(size + 1);
|
||||
int* chend = p + (size + 1); // $ alloc=L856+1
|
||||
|
||||
if(p <= chend) {
|
||||
*p = 42; // $ deref=L860 // BAD
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Exclude @void_type from @value_type
|
||||
compatibility: full
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add keyset to metadata_handle
|
||||
compatibility: full
|
||||
@@ -70,7 +70,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
foreach (var info in assemblyInfoByFileName.Values
|
||||
.OrderBy(info => info.Name)
|
||||
.ThenBy(info => info.NetCoreVersion ?? emptyVersion)
|
||||
.ThenBy(info => info.Version ?? emptyVersion))
|
||||
.ThenBy(info => info.Version ?? emptyVersion)
|
||||
.ThenBy(info => info.Filename))
|
||||
{
|
||||
foreach (var index in info.IndexStrings)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
/// <summary>
|
||||
/// The version number of the .NET Core framework that this assembly targets.
|
||||
///
|
||||
///
|
||||
/// This is extracted from the `TargetFrameworkAttribute` of the assembly, e.g.
|
||||
/// ```
|
||||
/// [assembly:TargetFramework(".NETCoreApp,Version=v7.0")]
|
||||
@@ -160,11 +160,22 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
* loading the same assembly from different locations.
|
||||
*/
|
||||
using var pereader = new System.Reflection.PortableExecutable.PEReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read));
|
||||
if (!pereader.HasMetadata)
|
||||
{
|
||||
throw new AssemblyLoadException();
|
||||
}
|
||||
|
||||
using var sha1 = SHA1.Create();
|
||||
var metadata = pereader.GetMetadata();
|
||||
|
||||
unsafe
|
||||
{
|
||||
var reader = new MetadataReader(metadata.Pointer, metadata.Length);
|
||||
if (!reader.IsAssembly)
|
||||
{
|
||||
throw new AssemblyLoadException();
|
||||
}
|
||||
|
||||
var def = reader.GetAssemblyDefinition();
|
||||
|
||||
// This is how you compute the public key token from the full public key.
|
||||
|
||||
@@ -47,9 +47,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
this.progressMonitor = new ProgressMonitor(logger);
|
||||
this.sourceDir = new DirectoryInfo(srcDir);
|
||||
|
||||
packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName));
|
||||
tempWorkingDirectory = new TemporaryDirectory(FileUtils.GetTemporaryWorkingDirectory(out cleanupTempWorkingDirectory));
|
||||
|
||||
try
|
||||
{
|
||||
this.dotnet = DotNet.Make(options, progressMonitor);
|
||||
this.dotnet = DotNet.Make(options, progressMonitor, tempWorkingDirectory);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -59,8 +62,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
this.progressMonitor.FindingFiles(srcDir);
|
||||
|
||||
packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName));
|
||||
tempWorkingDirectory = new TemporaryDirectory(FileUtils.GetTemporaryWorkingDirectory(out cleanupTempWorkingDirectory));
|
||||
|
||||
var allFiles = GetAllFiles();
|
||||
var binaryFileExtensions = new HashSet<string>(new[] { ".dll", ".exe" }); // TODO: add more binary file extensions.
|
||||
@@ -77,21 +78,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
? allFiles.SelectFileNamesByExtension(".dll").ToList()
|
||||
: options.DllDirs.Select(Path.GetFullPath).ToList();
|
||||
|
||||
// Find DLLs in the .Net / Asp.Net Framework
|
||||
if (options.ScanNetFrameworkDlls)
|
||||
{
|
||||
var runtime = new Runtime(dotnet);
|
||||
var runtimeLocation = runtime.GetRuntime(options.UseSelfContainedDotnet);
|
||||
progressMonitor.LogInfo($".NET runtime location selected: {runtimeLocation}");
|
||||
dllDirNames.Add(runtimeLocation);
|
||||
|
||||
if (fileContent.UseAspNetDlls && runtime.GetAspRuntime() is string aspRuntime)
|
||||
{
|
||||
progressMonitor.LogInfo($"ASP.NET runtime location selected: {aspRuntime}");
|
||||
dllDirNames.Add(aspRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.UseNuGet)
|
||||
{
|
||||
dllDirNames.Add(packageDirectory.DirInfo.FullName);
|
||||
@@ -111,6 +97,26 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
DownloadMissingPackages(allNonBinaryFiles);
|
||||
}
|
||||
|
||||
var existsNetCoreRefNugetPackage = false;
|
||||
var existsNetFrameworkRefNugetPackage = false;
|
||||
|
||||
// Find DLLs in the .Net / Asp.Net Framework
|
||||
// This block needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
|
||||
if (options.ScanNetFrameworkDlls)
|
||||
{
|
||||
existsNetCoreRefNugetPackage = IsNugetPackageAvailable("microsoft.netcore.app.ref");
|
||||
existsNetFrameworkRefNugetPackage = IsNugetPackageAvailable("microsoft.netframework.referenceassemblies");
|
||||
|
||||
if (existsNetCoreRefNugetPackage || existsNetFrameworkRefNugetPackage)
|
||||
{
|
||||
progressMonitor.LogInfo("Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory.");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddNetFrameworkDlls(dllDirNames);
|
||||
}
|
||||
}
|
||||
|
||||
assemblyCache = new AssemblyCache(dllDirNames, progressMonitor);
|
||||
AnalyseSolutions(solutions);
|
||||
|
||||
@@ -119,7 +125,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
UseReference(filename);
|
||||
}
|
||||
|
||||
RemoveRuntimeNugetPackageReferences();
|
||||
RemoveUnnecessaryNugetPackages(existsNetCoreRefNugetPackage, existsNetFrameworkRefNugetPackage);
|
||||
ResolveConflicts();
|
||||
|
||||
// Output the findings
|
||||
@@ -154,7 +160,30 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
DateTime.Now - startTime);
|
||||
}
|
||||
|
||||
private void RemoveRuntimeNugetPackageReferences()
|
||||
private void RemoveUnnecessaryNugetPackages(bool existsNetCoreRefNugetPackage, bool existsNetFrameworkRefNugetPackage)
|
||||
{
|
||||
RemoveNugetAnalyzerReferences();
|
||||
RemoveRuntimeNugetPackageReferences();
|
||||
|
||||
if (fileContent.IsNewProjectStructureUsed
|
||||
&& !fileContent.UseAspNetCoreDlls)
|
||||
{
|
||||
// This might have been restored by the CLI even though the project isn't an asp.net core one.
|
||||
RemoveNugetPackageReference("microsoft.aspnetcore.app.ref");
|
||||
}
|
||||
|
||||
if (existsNetCoreRefNugetPackage && existsNetFrameworkRefNugetPackage)
|
||||
{
|
||||
// Multiple packages are available, we keep only one:
|
||||
RemoveNugetPackageReference("microsoft.netframework.referenceassemblies.");
|
||||
}
|
||||
|
||||
// TODO: There could be multiple `microsoft.netframework.referenceassemblies` packages,
|
||||
// we could keep the newest one, but this is covered by the conflict resolution logic
|
||||
// (if the file names match)
|
||||
}
|
||||
|
||||
private void RemoveNugetAnalyzerReferences()
|
||||
{
|
||||
if (!options.UseNuGet)
|
||||
{
|
||||
@@ -162,23 +191,108 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
|
||||
var packageFolder = packageDirectory.DirInfo.FullName.ToLowerInvariant();
|
||||
var runtimePackageNamePrefixes = new[]
|
||||
if (packageFolder == null)
|
||||
{
|
||||
Path.Combine(packageFolder, "microsoft.netcore.app.runtime"),
|
||||
Path.Combine(packageFolder, "microsoft.aspnetcore.app.runtime"),
|
||||
Path.Combine(packageFolder, "microsoft.windowsdesktop.app.runtime"),
|
||||
|
||||
// legacy runtime packages:
|
||||
Path.Combine(packageFolder, "runtime.linux-x64.microsoft.netcore.app"),
|
||||
Path.Combine(packageFolder, "runtime.osx-x64.microsoft.netcore.app"),
|
||||
Path.Combine(packageFolder, "runtime.win-x64.microsoft.netcore.app"),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var filename in usedReferences.Keys)
|
||||
{
|
||||
var lowerFilename = filename.ToLowerInvariant();
|
||||
|
||||
if (runtimePackageNamePrefixes.Any(prefix => lowerFilename.StartsWith(prefix)))
|
||||
if (lowerFilename.StartsWith(packageFolder))
|
||||
{
|
||||
var firstDirectorySeparatorCharIndex = lowerFilename.IndexOf(Path.DirectorySeparatorChar, packageFolder.Length + 1);
|
||||
if (firstDirectorySeparatorCharIndex == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var secondDirectorySeparatorCharIndex = lowerFilename.IndexOf(Path.DirectorySeparatorChar, firstDirectorySeparatorCharIndex + 1);
|
||||
if (secondDirectorySeparatorCharIndex == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var subFolderIndex = secondDirectorySeparatorCharIndex + 1;
|
||||
var isInAnalyzersFolder = lowerFilename.IndexOf("analyzers", subFolderIndex) == subFolderIndex;
|
||||
if (isInAnalyzersFolder)
|
||||
{
|
||||
usedReferences.Remove(filename);
|
||||
progressMonitor.RemovedReference(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void AddNetFrameworkDlls(List<string> dllDirNames)
|
||||
{
|
||||
var runtime = new Runtime(dotnet);
|
||||
string? runtimeLocation = null;
|
||||
|
||||
if (options.UseSelfContainedDotnet)
|
||||
{
|
||||
runtimeLocation = runtime.ExecutingRuntime;
|
||||
}
|
||||
else if (fileContent.IsNewProjectStructureUsed)
|
||||
{
|
||||
runtimeLocation = runtime.NetCoreRuntime;
|
||||
}
|
||||
else if (fileContent.IsLegacyProjectStructureUsed)
|
||||
{
|
||||
runtimeLocation = runtime.DesktopRuntime;
|
||||
}
|
||||
|
||||
runtimeLocation ??= runtime.ExecutingRuntime;
|
||||
|
||||
progressMonitor.LogInfo($".NET runtime location selected: {runtimeLocation}");
|
||||
dllDirNames.Add(runtimeLocation);
|
||||
|
||||
if (fileContent.IsNewProjectStructureUsed
|
||||
&& fileContent.UseAspNetCoreDlls
|
||||
&& runtime.AspNetCoreRuntime is string aspRuntime)
|
||||
{
|
||||
progressMonitor.LogInfo($"ASP.NET runtime location selected: {aspRuntime}");
|
||||
dllDirNames.Add(aspRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveRuntimeNugetPackageReferences()
|
||||
{
|
||||
var runtimePackagePrefixes = new[]
|
||||
{
|
||||
"microsoft.netcore.app.runtime",
|
||||
"microsoft.aspnetcore.app.runtime",
|
||||
"microsoft.windowsdesktop.app.runtime",
|
||||
|
||||
// legacy runtime packages:
|
||||
"runtime.linux-x64.microsoft.netcore.app",
|
||||
"runtime.osx-x64.microsoft.netcore.app",
|
||||
"runtime.win-x64.microsoft.netcore.app",
|
||||
|
||||
// Internal implementation packages not meant for direct consumption:
|
||||
"runtime."
|
||||
};
|
||||
RemoveNugetPackageReference(runtimePackagePrefixes);
|
||||
}
|
||||
|
||||
private void RemoveNugetPackageReference(params string[] packagePrefixes)
|
||||
{
|
||||
if (!options.UseNuGet)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packageFolder = packageDirectory.DirInfo.FullName.ToLowerInvariant();
|
||||
if (packageFolder == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packagePathPrefixes = packagePrefixes.Select(p => Path.Combine(packageFolder, p.ToLowerInvariant()));
|
||||
|
||||
foreach (var filename in usedReferences.Keys)
|
||||
{
|
||||
var lowerFilename = filename.ToLowerInvariant();
|
||||
|
||||
if (packagePathPrefixes.Any(prefix => lowerFilename.StartsWith(prefix)))
|
||||
{
|
||||
usedReferences.Remove(filename);
|
||||
progressMonitor.RemovedReference(filename);
|
||||
@@ -186,6 +300,18 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsNugetPackageAvailable(string packagePrefix)
|
||||
{
|
||||
if (!options.UseNuGet)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return new DirectoryInfo(packageDirectory.DirInfo.FullName)
|
||||
.EnumerateDirectories(packagePrefix + "*", new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = false })
|
||||
.Any();
|
||||
}
|
||||
|
||||
private void GenerateSourceFileFromImplicitUsings()
|
||||
{
|
||||
var usings = new HashSet<string>();
|
||||
@@ -198,7 +324,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
usings.UnionWith(new[] { "System", "System.Collections.Generic", "System.IO", "System.Linq", "System.Net.Http", "System.Threading",
|
||||
"System.Threading.Tasks" });
|
||||
|
||||
if (fileContent.UseAspNetDlls)
|
||||
if (fileContent.UseAspNetCoreDlls)
|
||||
{
|
||||
usings.UnionWith(new[] { "System.Net.Http.Json", "Microsoft.AspNetCore.Builder", "Microsoft.AspNetCore.Hosting",
|
||||
"Microsoft.AspNetCore.Http", "Microsoft.AspNetCore.Routing", "Microsoft.Extensions.Configuration",
|
||||
@@ -322,7 +448,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
|
||||
var emptyVersion = new Version(0, 0);
|
||||
sortedReferences = sortedReferences.OrderBy(r => r.NetCoreVersion ?? emptyVersion).ThenBy(r => r.Version ?? emptyVersion).ToList();
|
||||
sortedReferences = sortedReferences
|
||||
.OrderBy(r => r.NetCoreVersion ?? emptyVersion)
|
||||
.ThenBy(r => r.Version ?? emptyVersion)
|
||||
.ThenBy(r => r.Filename)
|
||||
.ToList();
|
||||
|
||||
var finalAssemblyList = new Dictionary<string, AssemblyInfo>();
|
||||
|
||||
@@ -457,11 +587,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
}
|
||||
|
||||
private bool RestoreProject(string project, string? pathToNugetConfig = null) =>
|
||||
dotnet.RestoreProjectToDirectory(project, packageDirectory.DirInfo.FullName, pathToNugetConfig);
|
||||
private bool RestoreProject(string project, bool forceDotnetRefAssemblyFetching, string? pathToNugetConfig = null) =>
|
||||
dotnet.RestoreProjectToDirectory(project, packageDirectory.DirInfo.FullName, forceDotnetRefAssemblyFetching, pathToNugetConfig);
|
||||
|
||||
private bool RestoreSolution(string solution, out IEnumerable<string> projects) =>
|
||||
dotnet.RestoreSolutionToDirectory(solution, packageDirectory.DirInfo.FullName, out projects);
|
||||
dotnet.RestoreSolutionToDirectory(solution, packageDirectory.DirInfo.FullName, forceDotnetRefAssemblyFetching: true, out projects);
|
||||
|
||||
/// <summary>
|
||||
/// Executes `dotnet restore` on all solution files in solutions.
|
||||
@@ -487,7 +617,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, project =>
|
||||
{
|
||||
RestoreProject(project);
|
||||
RestoreProject(project, forceDotnetRefAssemblyFetching: true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -532,7 +662,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return;
|
||||
}
|
||||
|
||||
success = RestoreProject(tempDir.DirInfo.FullName, nugetConfig);
|
||||
success = RestoreProject(tempDir.DirInfo.FullName, forceDotnetRefAssemblyFetching: false, pathToNugetConfig: nugetConfig);
|
||||
// TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
|
||||
if (!success)
|
||||
{
|
||||
@@ -560,9 +690,25 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
packageDirectory?.Dispose();
|
||||
try
|
||||
{
|
||||
packageDirectory?.Dispose();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
progressMonitor.LogInfo("Couldn't delete package directory: " + exc.Message);
|
||||
}
|
||||
if (cleanupTempWorkingDirectory)
|
||||
tempWorkingDirectory?.Dispose();
|
||||
{
|
||||
try
|
||||
{
|
||||
tempWorkingDirectory?.Dispose();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
progressMonitor.LogInfo("Couldn't delete temporary working directory: " + exc.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
@@ -13,19 +14,21 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
private readonly IDotNetCliInvoker dotnetCliInvoker;
|
||||
private readonly ProgressMonitor progressMonitor;
|
||||
private readonly TemporaryDirectory? tempWorkingDirectory;
|
||||
|
||||
private DotNet(IDotNetCliInvoker dotnetCliInvoker, ProgressMonitor progressMonitor)
|
||||
private DotNet(IDotNetCliInvoker dotnetCliInvoker, ProgressMonitor progressMonitor, TemporaryDirectory? tempWorkingDirectory = null)
|
||||
{
|
||||
this.progressMonitor = progressMonitor;
|
||||
this.tempWorkingDirectory = tempWorkingDirectory;
|
||||
this.dotnetCliInvoker = dotnetCliInvoker;
|
||||
Info();
|
||||
}
|
||||
|
||||
private DotNet(IDependencyOptions options, ProgressMonitor progressMonitor) : this(new DotNetCliInvoker(progressMonitor, Path.Combine(options.DotNetPath ?? string.Empty, "dotnet")), progressMonitor) { }
|
||||
private DotNet(IDependencyOptions options, ProgressMonitor progressMonitor, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(progressMonitor, Path.Combine(options.DotNetPath ?? string.Empty, "dotnet")), progressMonitor, tempWorkingDirectory) { }
|
||||
|
||||
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ProgressMonitor progressMonitor) => new DotNet(dotnetCliInvoker, progressMonitor);
|
||||
|
||||
public static IDotNet Make(IDependencyOptions options, ProgressMonitor progressMonitor) => new DotNet(options, progressMonitor);
|
||||
public static IDotNet Make(IDependencyOptions options, ProgressMonitor progressMonitor, TemporaryDirectory tempWorkingDirectory) => new DotNet(options, progressMonitor, tempWorkingDirectory);
|
||||
|
||||
private void Info()
|
||||
{
|
||||
@@ -37,12 +40,29 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRestoreArgs(string projectOrSolutionFile, string packageDirectory) =>
|
||||
$"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true";
|
||||
|
||||
public bool RestoreProjectToDirectory(string projectFile, string packageDirectory, string? pathToNugetConfig = null)
|
||||
private string GetRestoreArgs(string projectOrSolutionFile, string packageDirectory, bool forceDotnetRefAssemblyFetching)
|
||||
{
|
||||
var args = GetRestoreArgs(projectFile, packageDirectory);
|
||||
var args = $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true";
|
||||
|
||||
if (forceDotnetRefAssemblyFetching)
|
||||
{
|
||||
// Ugly hack: we set the TargetFrameworkRootPath and NetCoreTargetingPackRoot properties to an empty folder:
|
||||
var path = ".empty";
|
||||
if (tempWorkingDirectory != null)
|
||||
{
|
||||
path = Path.Combine(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
args += $" /p:TargetFrameworkRootPath=\"{path}\" /p:NetCoreTargetingPackRoot=\"{path}\"";
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
public bool RestoreProjectToDirectory(string projectFile, string packageDirectory, bool forceDotnetRefAssemblyFetching, string? pathToNugetConfig = null)
|
||||
{
|
||||
var args = GetRestoreArgs(projectFile, packageDirectory, forceDotnetRefAssemblyFetching);
|
||||
if (pathToNugetConfig != null)
|
||||
{
|
||||
args += $" --configfile \"{pathToNugetConfig}\"";
|
||||
@@ -51,9 +71,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return dotnetCliInvoker.RunCommand(args);
|
||||
}
|
||||
|
||||
public bool RestoreSolutionToDirectory(string solutionFile, string packageDirectory, out IEnumerable<string> projects)
|
||||
public bool RestoreSolutionToDirectory(string solutionFile, string packageDirectory, bool forceDotnetRefAssemblyFetching, out IEnumerable<string> projects)
|
||||
{
|
||||
var args = GetRestoreArgs(solutionFile, packageDirectory);
|
||||
var args = GetRestoreArgs(solutionFile, packageDirectory, forceDotnetRefAssemblyFetching);
|
||||
args += " --verbosity normal";
|
||||
if (dotnetCliInvoker.RunCommand(args, out var output))
|
||||
{
|
||||
|
||||
@@ -31,21 +31,21 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private bool useAspNetDlls = false;
|
||||
private bool useAspNetCoreDlls = false;
|
||||
|
||||
/// <summary>
|
||||
/// True if any file in the source directory indicates that ASP.NET is used.
|
||||
/// The following heuristic is used to decide, if ASP.NET is used:
|
||||
/// True if any file in the source directory indicates that ASP.NET Core is used.
|
||||
/// The following heuristic is used to decide, if ASP.NET Core is used:
|
||||
/// If any file in the source directory contains something like (this will most like be a .csproj file)
|
||||
/// <Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
/// <FrameworkReference Include="Microsoft.AspNetCore.App"/>
|
||||
/// </summary>
|
||||
public bool UseAspNetDlls
|
||||
public bool UseAspNetCoreDlls
|
||||
{
|
||||
get
|
||||
{
|
||||
initialize.Run();
|
||||
return useAspNetDlls;
|
||||
return useAspNetCoreDlls;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,27 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private bool isLegacyProjectStructureUsed = false;
|
||||
|
||||
public bool IsLegacyProjectStructureUsed
|
||||
{
|
||||
get
|
||||
{
|
||||
initialize.Run();
|
||||
return isLegacyProjectStructureUsed;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isNewProjectStructureUsed = false;
|
||||
public bool IsNewProjectStructureUsed
|
||||
{
|
||||
get
|
||||
{
|
||||
initialize.Run();
|
||||
return isNewProjectStructureUsed;
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<string> CustomImplicitUsings
|
||||
{
|
||||
get
|
||||
@@ -141,19 +162,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
|
||||
// Determine if ASP.NET is used.
|
||||
if (!useAspNetDlls)
|
||||
{
|
||||
useAspNetDlls =
|
||||
IsGroupMatch(line, ProjectSdk(), "Sdk", "Microsoft.NET.Sdk.Web") ||
|
||||
IsGroupMatch(line, FrameworkReference(), "Include", "Microsoft.AspNetCore.App");
|
||||
}
|
||||
useAspNetCoreDlls = useAspNetCoreDlls
|
||||
|| IsGroupMatch(line, ProjectSdk(), "Sdk", "Microsoft.NET.Sdk.Web")
|
||||
|| IsGroupMatch(line, FrameworkReference(), "Include", "Microsoft.AspNetCore.App");
|
||||
|
||||
|
||||
// Determine if implicit usings are used.
|
||||
if (!useImplicitUsings)
|
||||
{
|
||||
useImplicitUsings = line.Contains("<ImplicitUsings>enable</ImplicitUsings>".AsSpan(), StringComparison.Ordinal) ||
|
||||
line.Contains("<ImplicitUsings>true</ImplicitUsings>".AsSpan(), StringComparison.Ordinal);
|
||||
}
|
||||
useImplicitUsings = useImplicitUsings
|
||||
|| line.Contains("<ImplicitUsings>enable</ImplicitUsings>".AsSpan(), StringComparison.Ordinal)
|
||||
|| line.Contains("<ImplicitUsings>true</ImplicitUsings>".AsSpan(), StringComparison.Ordinal);
|
||||
|
||||
// Find all custom implicit usings.
|
||||
foreach (var valueMatch in CustomImplicitUsingDeclarations().EnumerateMatches(line))
|
||||
@@ -164,6 +181,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
implicitUsingNamespaces.Add(ns);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine project structure:
|
||||
isLegacyProjectStructureUsed = isLegacyProjectStructureUsed || MicrosoftCSharpTargets().IsMatch(line);
|
||||
isNewProjectStructureUsed = isNewProjectStructureUsed
|
||||
|| ProjectSdk().IsMatch(line)
|
||||
|| FrameworkReference().IsMatch(line);
|
||||
// TODO: we could also check `<Sdk Name="Microsoft.NET.Sdk" />`
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -184,6 +208,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
[GeneratedRegex("<Using.*\\sInclude=\"(.*?)\".*/?>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
||||
private static partial Regex CustomImplicitUsingDeclarations();
|
||||
|
||||
[GeneratedRegex("<Import.*\\sProject=\".*Microsoft\\.CSharp\\.targets\".*/?>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
||||
private static partial Regex MicrosoftCSharpTargets();
|
||||
}
|
||||
|
||||
internal interface IUnsafeFileReader
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
internal interface IDotNet
|
||||
{
|
||||
bool RestoreProjectToDirectory(string project, string directory, string? pathToNugetConfig = null);
|
||||
bool RestoreSolutionToDirectory(string solutionFile, string packageDirectory, out IEnumerable<string> projects);
|
||||
bool RestoreProjectToDirectory(string project, string directory, bool forceDotnetRefAssemblyFetching, string? pathToNugetConfig = null);
|
||||
bool RestoreSolutionToDirectory(string solutionFile, string packageDirectory, bool forceDotnetRefAssemblyFetching, out IEnumerable<string> projects);
|
||||
bool New(string folder);
|
||||
bool AddPackage(string folder, string package);
|
||||
IList<string> GetListedRuntimes();
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
internal class NugetPackages
|
||||
{
|
||||
private readonly string nugetExe;
|
||||
private readonly string? nugetExe;
|
||||
private readonly ProgressMonitor progressMonitor;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,10 +36,18 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
this.packageDirectory = packageDirectory;
|
||||
this.progressMonitor = progressMonitor;
|
||||
|
||||
nugetExe = ResolveNugetExe(sourceDir);
|
||||
packageFiles = new DirectoryInfo(sourceDir)
|
||||
.EnumerateFiles("packages.config", SearchOption.AllDirectories)
|
||||
.ToArray();
|
||||
|
||||
if (packageFiles.Length > 0)
|
||||
{
|
||||
nugetExe = ResolveNugetExe(sourceDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
progressMonitor.LogInfo("Found no packages.config file");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,7 +119,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
string exe, args;
|
||||
if (Util.Win32.IsWindows())
|
||||
{
|
||||
exe = nugetExe;
|
||||
exe = nugetExe!;
|
||||
args = string.Format("install -OutputDirectory {0} {1}", packageDirectory, package);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -55,10 +55,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
LogInfo($"Restoring {package}...");
|
||||
|
||||
public void ResolvedReference(string filename) =>
|
||||
LogInfo($"Resolved {filename}");
|
||||
LogInfo($"Resolved reference {filename}");
|
||||
|
||||
public void RemovedReference(string filename) =>
|
||||
LogInfo($"Reference {filename} has been removed");
|
||||
LogInfo($"Removed reference {filename}");
|
||||
|
||||
public void Summary(int existingSources, int usedSources, int missingSources,
|
||||
int references, int unresolvedReferences,
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
private readonly IDotNet dotNet;
|
||||
private readonly Lazy<Dictionary<string, DotNetVersion>> newestRuntimes;
|
||||
private Dictionary<string, DotNetVersion> NewestRuntimes => newestRuntimes.Value;
|
||||
private static string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
|
||||
|
||||
public Runtime(IDotNet dotNet)
|
||||
{
|
||||
@@ -70,17 +69,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
get
|
||||
{
|
||||
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
|
||||
var monoDirs = monoPath is not null
|
||||
? new[] { monoPath }
|
||||
: new[] { "/usr/lib/mono", @"C:\Program Files\Mono\lib\mono" };
|
||||
|
||||
if (Directory.Exists(@"C:\Windows\Microsoft.NET\Framework64"))
|
||||
{
|
||||
return Directory.EnumerateDirectories(@"C:\Windows\Microsoft.NET\Framework64", "v*")
|
||||
.OrderByDescending(Path.GetFileName);
|
||||
}
|
||||
|
||||
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
|
||||
var monoDirs = monoPath is not null
|
||||
? new[] { Path.GetFullPath(Path.Combine(monoPath, "..", "lib", "mono")), monoPath }
|
||||
: new[] { "/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono" };
|
||||
|
||||
var dir = monoDirs.FirstOrDefault(Directory.Exists);
|
||||
|
||||
if (dir is not null)
|
||||
@@ -107,33 +106,23 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the .NET runtime location to use for extraction.
|
||||
/// Gets the Dotnet Core location.
|
||||
/// </summary>
|
||||
public string GetRuntime(bool useSelfContained)
|
||||
{
|
||||
if (useSelfContained)
|
||||
{
|
||||
return ExecutingRuntime;
|
||||
}
|
||||
|
||||
// Location of the newest .NET Core Runtime.
|
||||
if (GetVersion(netCoreApp) is string path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
if (DesktopRuntimes.Any())
|
||||
{
|
||||
return DesktopRuntimes.First();
|
||||
}
|
||||
|
||||
// A bad choice if it's the self-contained runtime distributed in codeql dist.
|
||||
return ExecutingRuntime;
|
||||
}
|
||||
public string? NetCoreRuntime => GetVersion(netCoreApp);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ASP.NET runtime location to use for extraction, if one exists.
|
||||
/// Gets the .NET Framework location. Either the installation folder on Windows or Mono
|
||||
/// </summary>
|
||||
public string? GetAspRuntime() => GetVersion(aspNetCoreApp);
|
||||
public string? DesktopRuntime => DesktopRuntimes?.FirstOrDefault();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the executing runtime location, this is the self contained runtime shipped in the CodeQL CLI bundle.
|
||||
/// </summary>
|
||||
public string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ASP.NET Core location.
|
||||
/// </summary>
|
||||
public string? AspNetCoreRuntime => GetVersion(aspNetCoreApp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1822</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Semmle.Extraction.Tests
|
||||
var dotnet = MakeDotnet(dotnetCliInvoker);
|
||||
|
||||
// Execute
|
||||
dotnet.RestoreProjectToDirectory("myproject.csproj", "mypackages");
|
||||
dotnet.RestoreProjectToDirectory("myproject.csproj", "mypackages", false);
|
||||
|
||||
// Verify
|
||||
var lastArgs = dotnetCliInvoker.GetLastArgs();
|
||||
@@ -114,7 +114,7 @@ namespace Semmle.Extraction.Tests
|
||||
var dotnet = MakeDotnet(dotnetCliInvoker);
|
||||
|
||||
// Execute
|
||||
dotnet.RestoreProjectToDirectory("myproject.csproj", "mypackages", "myconfig.config");
|
||||
dotnet.RestoreProjectToDirectory("myproject.csproj", "mypackages", false, "myconfig.config");
|
||||
|
||||
// Verify
|
||||
var lastArgs = dotnetCliInvoker.GetLastArgs();
|
||||
@@ -129,7 +129,7 @@ namespace Semmle.Extraction.Tests
|
||||
var dotnet = MakeDotnet(dotnetCliInvoker);
|
||||
|
||||
// Execute
|
||||
dotnet.RestoreSolutionToDirectory("mysolution.sln", "mypackages", out var projects);
|
||||
dotnet.RestoreSolutionToDirectory("mysolution.sln", "mypackages", false, out var projects);
|
||||
|
||||
// Verify
|
||||
var lastArgs = dotnetCliInvoker.GetLastArgs();
|
||||
@@ -148,7 +148,7 @@ namespace Semmle.Extraction.Tests
|
||||
dotnetCliInvoker.Success = false;
|
||||
|
||||
// Execute
|
||||
dotnet.RestoreSolutionToDirectory("mysolution.sln", "mypackages", out var projects);
|
||||
dotnet.RestoreSolutionToDirectory("mysolution.sln", "mypackages", false, out var projects);
|
||||
|
||||
// Verify
|
||||
var lastArgs = dotnetCliInvoker.GetLastArgs();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Semmle.Extraction.CSharp.DependencyFetching;
|
||||
|
||||
@@ -6,9 +7,9 @@ namespace Semmle.Extraction.Tests
|
||||
{
|
||||
internal class UnsafeFileReaderStub : IUnsafeFileReader
|
||||
{
|
||||
private readonly List<string> lines;
|
||||
private readonly IEnumerable<string> lines;
|
||||
|
||||
public UnsafeFileReaderStub(List<string> lines)
|
||||
public UnsafeFileReaderStub(IEnumerable<string> lines)
|
||||
{
|
||||
this.lines = lines;
|
||||
}
|
||||
@@ -24,7 +25,7 @@ namespace Semmle.Extraction.Tests
|
||||
|
||||
internal class TestFileContent : FileContent
|
||||
{
|
||||
public TestFileContent(List<string> lines) : base(new ProgressMonitor(new LoggerStub()),
|
||||
public TestFileContent(IEnumerable<string> lines) : base(new ProgressMonitor(new LoggerStub()),
|
||||
new List<string>() { "test1.cs" },
|
||||
new UnsafeFileReaderStub(lines))
|
||||
{ }
|
||||
@@ -48,7 +49,7 @@ namespace Semmle.Extraction.Tests
|
||||
|
||||
// Execute
|
||||
var allPackages = fileContent.AllPackages;
|
||||
var useAspNetDlls = fileContent.UseAspNetDlls;
|
||||
var useAspNetDlls = fileContent.UseAspNetCoreDlls;
|
||||
|
||||
// Verify
|
||||
Assert.False(useAspNetDlls);
|
||||
@@ -72,7 +73,7 @@ namespace Semmle.Extraction.Tests
|
||||
var fileContent = new TestFileContent(lines);
|
||||
|
||||
// Execute
|
||||
var useAspNetDlls = fileContent.UseAspNetDlls;
|
||||
var useAspNetDlls = fileContent.UseAspNetCoreDlls;
|
||||
var allPackages = fileContent.AllPackages;
|
||||
|
||||
// Verify
|
||||
@@ -136,5 +137,53 @@ namespace Semmle.Extraction.Tests
|
||||
Assert.Contains("Ns0.Ns1", customImplicitUsings);
|
||||
Assert.Contains("Ns2", customImplicitUsings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestFileContent_LegacyProjectStructure()
|
||||
{
|
||||
// Setup
|
||||
var input =
|
||||
"""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
""";
|
||||
var lines = input.Split(Environment.NewLine);
|
||||
var fileContent = new TestFileContent(lines);
|
||||
|
||||
// Execute
|
||||
var isLegacy = fileContent.IsLegacyProjectStructureUsed;
|
||||
var isNew = fileContent.IsNewProjectStructureUsed;
|
||||
|
||||
// Verify
|
||||
Assert.True(isLegacy);
|
||||
Assert.False(isNew);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestFileContent_NewProjectStructure()
|
||||
{
|
||||
// Setup
|
||||
var input =
|
||||
"""
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;net70</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
""";
|
||||
var lines = input.Split(Environment.NewLine);
|
||||
|
||||
var fileContent = new TestFileContent(lines);
|
||||
|
||||
// Execute
|
||||
var isLegacy = fileContent.IsLegacyProjectStructureUsed;
|
||||
var isNew = fileContent.IsNewProjectStructureUsed;
|
||||
|
||||
// Verify
|
||||
Assert.True(isNew);
|
||||
Assert.False(isLegacy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Semmle.Extraction.Tests
|
||||
|
||||
public bool New(string folder) => true;
|
||||
|
||||
public bool RestoreProjectToDirectory(string project, string directory, string? pathToNugetConfig = null) => true;
|
||||
public bool RestoreProjectToDirectory(string project, string directory, bool forceDotnetRefAssemblyFetching, string? pathToNugetConfig = null) => true;
|
||||
|
||||
public bool RestoreSolutionToDirectory(string solution, string directory, out IEnumerable<string> projects)
|
||||
public bool RestoreSolutionToDirectory(string solution, string directory, bool forceDotnetRefAssemblyFetching, out IEnumerable<string> projects)
|
||||
{
|
||||
projects = Array.Empty<string>();
|
||||
return true;
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 1.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.0
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.6.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.0
|
||||
|
||||
No user-facing changes.
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.6.5
|
||||
lastReleaseVersion: 1.7.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.0-dev
|
||||
version: 1.7.1
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 1.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.0
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.6.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.0
|
||||
|
||||
No user-facing changes.
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.6.5
|
||||
lastReleaseVersion: 1.7.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.0-dev
|
||||
version: 1.7.1
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
| Program.cs:0:0:0:0 | Program.cs |
|
||||
| obj/Debug/net5.0/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs:0:0:0:0 | obj/Debug/net5.0/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs |
|
||||
| obj/Debug/net5.0/autobuild.AssemblyInfo.cs:0:0:0:0 | obj/Debug/net5.0/autobuild.AssemblyInfo.cs |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from File f
|
||||
where f.fromSource()
|
||||
select f
|
||||
@@ -0,0 +1 @@
|
||||
var dummy = "dummy";
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="DeleteBinObjFolders" BeforeTargets="Clean">
|
||||
<RemoveDir Directories=".\bin" />
|
||||
<RemoveDir Directories=".\obj" />
|
||||
</Target>
|
||||
</Project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user