Compare commits

..

1220 Commits

Author SHA1 Message Date
Florin Coada
4cf5d4178f Changelogx fix for 2.18.0 c/cpp breaking changes 2024-07-29 10:11:26 +01:00
yoff
d23d138e7d Merge pull request #16923 from RasmusWL/impossible-isinstance
Python: Add test for impossible isinstance flow
2024-07-29 09:33:30 +02:00
Jeroen Ketema
e1329dff72 Merge pull request #16947 from github/calumgrant/attributes
C++: Update attributes test output
2024-07-26 21:05:46 +02:00
Florin Coada
b6aea3cde1 Merge pull request #17083 from github/changedocs/2.18.1
Update codeql changelog to version 2.18.1
2024-07-26 18:23:16 +01:00
Florin Coada
d189526283 Update docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.18.1.rst
Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com>
2024-07-26 18:16:12 +01:00
Florin Coada
707acdef08 Update codeql-cli-2.18.1.rst 2024-07-26 17:25:58 +01:00
Florin Coada
450137d2cf Update codeql changelog to version 2.18.1 2024-07-26 17:15:23 +01:00
Jami
0ba5a74f6a Merge pull request #17074 from jcogs33/jcogs33/java/fix-regex-use-comments
Java: fix comments about use of sink kind `regex-use`
2024-07-26 08:57:39 -04:00
Florin Coada
8eb3b31ee2 Merge pull request #17060 from github/changedocs/2.18.0
Update unified changelog for 2.17.6 and 2.18.0
2024-07-26 11:35:41 +01:00
Florin Coada
72e05c952e Merge branch 'main' into changedocs/2.18.0 2024-07-26 11:27:41 +01:00
Mathias Vorreiter Pedersen
c0263bef5a Merge pull request #17062 from MathiasVP/speed-up-alias-analysis-4
C++: Speed up alias analysis
2024-07-26 10:02:02 +01:00
Mathias Vorreiter Pedersen
6b68cf6bdc Merge pull request #17076 from MathiasVP/add-missing-write-side-effect-to-remquo
C++: Add missing write side effect to `std::remquo`
2024-07-26 09:56:57 +01:00
Jeroen Ketema
06a3bf8808 Merge pull request #17077 from jketema/explicit-bool2
C++: Add more `explicit(bool)` tests
2024-07-26 10:55:54 +02:00
Anders Schack-Mulligen
822f8b06f0 Merge pull request #17011 from aschackmull/dataflow/provenance-postprocess-qltest
Shared: Add support for provenance pretty-printing as a qltest postprocess step.
2024-07-26 10:51:59 +02:00
Jeroen Ketema
a944922c97 C++: Add more explicit(bool) tests 2024-07-26 09:47:01 +02:00
Owen Mansel-Chan
c051d33cc7 Merge branch 'main' into dataflow/provenance-postprocess-qltest 2024-07-26 08:04:05 +01:00
Geoffrey White
52020f7e5b Merge pull request #17028 from geoffw0/cryptodoc
C++: Improve query doc advice for using encryption
2024-07-25 21:46:16 +01:00
Mathias Vorreiter Pedersen
91edf82c8a C++: Add more missing overrides. 2024-07-25 17:13:26 +01:00
Mathias Vorreiter Pedersen
b640bdccdc C++: Accept test changes. 2024-07-25 17:13:10 +01:00
Mathias Vorreiter Pedersen
52f8f04e9d C++: Add write side effect to 'remquo'. 2024-07-25 17:12:56 +01:00
Jami
91f5f086fb Merge pull request #17025 from jcogs33/jcogs33/java/adjust-url-syntheticfield
Java: add TaintInheritingContent for URL synthetic fields
2024-07-25 12:11:39 -04:00
Mathias Vorreiter Pedersen
d2f5734ac5 C++: Add FP. 2024-07-25 17:08:47 +01:00
Mathias Vorreiter Pedersen
30abc958a8 Merge pull request #16982 from MathiasVP/promote-unsigned-difference-expression-compared-zero-to-code-scanning
C++: Promote `cpp/unsigned-difference-expression-compared-zero` to Code Scanning
2024-07-25 16:18:39 +01:00
Jami Cogswell
eea3e82cca Java: fix 'regex-use' comments 2024-07-25 10:39:03 -04:00
Geoffrey White
27314aac16 Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-07-25 15:17:21 +01:00
Jeroen Ketema
9d75782c44 Merge pull request #17073 from jketema/explicit-bool
C++: Add additional test cases for `explict` and `explicit(bool)` specifiers
2024-07-25 15:40:38 +02:00
Mathias Vorreiter Pedersen
087b0dac1d C++: Fix QLDoc. 2024-07-25 14:38:26 +01:00
Alex Ford
9fb657c4c4 Merge pull request #16781 from alexrford/rb/weak-sensitive-data-hashing
Add `rb/weak-sensitive-data-hashing` query port
2024-07-25 14:11:42 +01:00
Mathias Vorreiter Pedersen
4d3377b116 Merge branch 'main' into promote-unsigned-difference-expression-compared-zero-to-code-scanning 2024-07-25 14:00:05 +01:00
Jeroen Ketema
3e7a60c1a6 C++: Add additional test cases for explict and explicit(bool) specifiers
Note that the `explict(bool)` specifiers currently do not end up in the
database.
2024-07-25 14:41:44 +02:00
Anders Schack-Mulligen
c693f03462 Merge pull request #17070 from aschackmull/dataflow/pptype-refactor
Dataflow: Replace `ppReprType` with `DataFlowType.toString`.
2024-07-25 14:30:08 +02:00
Geoffrey White
245f43dd58 Merge pull request #17064 from geoffw0/swiftbobs
Swift: Minor fixes
2024-07-25 13:05:19 +01:00
Mathias Vorreiter Pedersen
099c282277 C++: Move large function to its own file. 2024-07-25 12:11:09 +01:00
Anders Schack-Mulligen
7a48fe1102 Dataflow: Replace ppReprType with DataFlowType.toString. 2024-07-25 13:08:47 +02:00
Mathias Vorreiter Pedersen
c5da43e691 Merge pull request #16981 from MathiasVP/phi-escape-5-follow-up-2
C++: Alias analysis follow-up to #16907
2024-07-25 11:59:44 +01:00
Mathias Vorreiter Pedersen
34ad211900 C++: Add change note. 2024-07-25 10:50:28 +01:00
Mathias Vorreiter Pedersen
032ae9e1e7 Merge pull request #17034 from MathiasVP/more-alias-and-side-effect-models
C++: Add more alias and side effect models
2024-07-25 10:40:32 +01:00
Owen Mansel-Chan
5a39610ba7 Merge pull request #17053 from owen-mc/java/fix/regex-use-sink-kind
Java: Add comments about use of sink kind `regex-use`
2024-07-24 21:08:52 +01:00
Jami Cogswell
5854e88f63 Java: add change note 2024-07-24 16:00:38 -04:00
Geoffrey White
d77d7c533b Swift: Change note. 2024-07-24 18:25:06 +01:00
Geoffrey White
ecefa3e383 Swift: Fix a corrupted model. 2024-07-24 18:16:24 +01:00
Mathias Vorreiter Pedersen
3f5b4a81cf C++: Fix more inconsistencies. 2024-07-24 17:53:28 +01:00
Geoffrey White
44e33c7be7 Swift: Fill out the empty comment for SsaDefinitionNode (contents stolen from JS). 2024-07-24 17:51:12 +01:00
Calum Grant
d8cc92068a C++: Update attributes test output 2024-07-24 17:48:35 +01:00
Mathias Vorreiter Pedersen
4a34dc125b C++: Expand the macro manually to work around an extractor bug. 2024-07-24 15:51:54 +01:00
Mathias Vorreiter Pedersen
b3bffb6826 Merge branch 'main' into phi-escape-5-follow-up-2 2024-07-24 15:22:40 +01:00
Mathias Vorreiter Pedersen
7ec3162583 C++: Sync identical files. 2024-07-24 15:20:00 +01:00
Mathias Vorreiter Pedersen
a5efe9fa09 C++: Respond to review comments. 2024-07-24 15:18:26 +01:00
Mathias Vorreiter Pedersen
90b25a6696 Merge pull request #17057 from MathiasVP/avoid-expensive-negation
C++: Avoid expensive negation
2024-07-24 15:09:52 +01:00
Mathias Vorreiter Pedersen
5e484e4006 C++: Accept test changes. 2024-07-24 14:29:42 +01:00
Mathias Vorreiter Pedersen
b1bea31720 C++: Speed up alias analysis. 2024-07-24 14:29:41 +01:00
Mathias Vorreiter Pedersen
28cff2ea20 C++: Add a testcase with many def/use pairs in alias analysis. 2024-07-24 13:46:31 +01:00
Florin Coada
1de91b4cd5 Update unified changelog for 2.17.6 and 2.18.0 2024-07-24 12:55:51 +01:00
Mathias Vorreiter Pedersen
ff60d9647f C++: Sync identical files. 2024-07-24 11:53:14 +01:00
Mathias Vorreiter Pedersen
ec134927d8 C++: Avoid expensive negation. 2024-07-24 11:53:11 +01:00
Anders Schack-Mulligen
9f79a39deb Merge pull request #17026 from Marcono1234/patch-1
Java: Update `Annotation` predicate examples in language guide
2024-07-24 12:43:50 +02:00
Mathias Vorreiter Pedersen
854a277ab5 Merge branch 'main' into more-alias-and-side-effect-models 2024-07-24 10:53:27 +01:00
Mathias Vorreiter Pedersen
b7542ee575 C++: Fix more inconsistencies (and delete unnecessary override). 2024-07-24 10:52:35 +01:00
Geoffrey White
eaf2949857 Merge pull request #17054 from geoffw0/scanf
C++: Fix false positives in cpp/incorrectly-checked-scanf
2024-07-24 10:51:25 +01:00
Geoffrey White
741a3289a1 Merge pull request #17055 from geoffw0/usefree
C++: More tests for cpp/use-after-free
2024-07-24 10:35:32 +01:00
Jeroen Ketema
4cbc3349f6 Merge pull request #17050 from jketema/destroying-deletes
C++: Support destroying deletes
2024-07-24 09:29:55 +02:00
Jeroen Ketema
acbca9c108 C++: Support destroying deletes 2024-07-24 08:21:01 +02:00
Owen Mansel-Chan
3edeb82d5b Add comment by models using regex-use sink kind 2024-07-23 21:40:45 +01:00
Owen Mansel-Chan
89f958105a Mention regex-use sink kind in QLDoc for regexSinkKindInfo 2024-07-23 21:38:30 +01:00
Geoffrey White
1456012b54 C++: Additional test cases for cpp/use-after-free. 2024-07-23 18:02:14 +01:00
Geoffrey White
4920039a00 C++: Test spacing. 2024-07-23 18:01:30 +01:00
Geoffrey White
a98fac0d7d C++: Change note. 2024-07-23 17:27:42 +01:00
Geoffrey White
6026f65f8b C++: Fix FPs in cpp/incorrectly-checked-scanf. 2024-07-23 17:27:37 +01:00
Mathias Vorreiter Pedersen
43df4a9393 C++: Fix inconsistencies. 2024-07-23 17:22:04 +01:00
Geoffrey White
c3f2faff76 C++: Add another pattern I found in the wild. 2024-07-23 17:19:01 +01:00
Geoffrey White
a9f6b2110e C++: Add new test cases for cpp/incorrectly-checked-scanf. 2024-07-23 15:27:22 +01:00
Owen Mansel-Chan
4c8da54b64 Merge pull request #17036 from chmodxxx/sbaddou/fix
Java: Move SensitiveLoggerConfig source to extensible format
2024-07-23 14:55:26 +01:00
Chuan-kai Lin
67dac96e80 Merge pull request #17041 from github/post-release-prep/codeql-cli-2.18.1
Post-release preparation for codeql-cli-2.18.1
2024-07-23 06:48:30 -07:00
Geoffrey White
e467cc033e Merge pull request #17037 from geoffw0/sizecheck
C++: Fix issue with cpp/suspicious-allocation-size
2024-07-23 14:47:17 +01:00
Geoffrey White
1ed5af1d6a Merge pull request #17035 from geoffw0/allocerr
C++: Fix issue with cpp/incorrect-allocation-error-handling
2024-07-23 14:36:05 +01:00
Alexandre Boulgakov
db53be39fe Merge pull request #17047 from github/sashabu/using-enum
C++: Add `UsingEnumDeclarationEntry` changenote.
2024-07-23 14:19:18 +01:00
Alexandre Boulgakov
37ceb0118a Merge pull request #17048 from github/sashabu/ame
Docs: Document preference for American English in change notes.
2024-07-23 14:05:57 +01:00
Alexandre Boulgakov
e461691c85 C++: Move UsingEnumDeclarationEntry change note. 2024-07-23 13:57:07 +01:00
Alexandre Boulgakov
5e6c9fb661 Docs: Document preference for American English in change notes. 2024-07-23 13:49:30 +01:00
Alexandre Boulgakov
5a5c5d1012 C++: Translate change note to American English.
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2024-07-23 13:47:44 +01:00
Alexandre Boulgakov
29bda5a805 C++: Add UsingEnumDeclarationEntry changenote. 2024-07-23 13:43:57 +01:00
Geoffrey White
c1bd892a13 Update cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2024-07-23 13:14:07 +01:00
Salah Baddou
4f80ae2190 Merge branch 'main' into sbaddou/fix 2024-07-23 12:03:13 +01:00
Salah Baddou
092de640fe add change-notes 2024-07-23 11:04:56 +01:00
Owen Mansel-Chan
ff8bb2b1f8 Merge pull request #16760 from owen-mc/java/reverse-dns-separate-threat-model-kind
Java: make a separate threat model kind for reverse DNS sources
2024-07-23 10:08:52 +01:00
Jeroen Ketema
d2573310c6 Merge pull request #17006 from github/sashabu/using-enum
C++: Support `using enum` declarations.
2024-07-23 10:25:06 +02:00
Anders Schack-Mulligen
b5b9c4d931 Update java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll
Java: Make class private
2024-07-23 10:07:51 +02:00
Anders Schack-Mulligen
bb86a07a93 Update java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll
fix typo
2024-07-23 10:03:07 +02:00
Anders Schack-Mulligen
5912a17ab4 Update java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll
Autoformat
2024-07-23 10:01:49 +02:00
github-actions[bot]
49cc8f8ff8 Post-release preparation for codeql-cli-2.18.1 2024-07-22 22:00:48 +00:00
Chuan-kai Lin
54ac18092d Merge pull request #17040 from github/release-prep/2.18.1
Release preparation for version 2.18.1
2024-07-22 14:36:26 -07:00
Chuan-kai Lin
a5fe3f4d9c Minor changelog improvements 2024-07-22 14:34:56 -07:00
github-actions[bot]
368bcb684a Release preparation for version 2.18.1 2024-07-22 21:30:50 +00:00
Chuan-kai Lin
09f5e19c71 Merge pull request #17039 from github/revert-17032-release-prep/2.18.1
Revert "Release preparation for version 2.18.1"
2024-07-22 13:51:37 -07:00
Edward Minnix III
8038796207 Merge pull request #16993 from egregius313/egregius313/java/model-lastaflute-framework
Add models for the `lastaflute` framework
2024-07-22 16:40:16 -04:00
Chuan-kai Lin
23320b6e5e Revert "Release preparation for version 2.18.1" 2024-07-22 13:22:49 -07:00
Alexandre Boulgakov
3defc8b5de C++: Fix typo - remove unbound and unused variable in downgrade script. 2024-07-22 18:27:39 +01:00
Geoffrey White
437c679266 C++: Switch to using the Buffer.qll implementation directly. 2024-07-22 18:09:08 +01:00
Alexandre Boulgakov
af562f15f3 C++: Handle using_container in using-enum downgrade script. 2024-07-22 18:02:14 +01:00
Geoffrey White
e8718f9d2f C++: Change note. 2024-07-22 18:01:47 +01:00
Geoffrey White
7b03f3268f C++: Fix false positives. 2024-07-22 18:00:15 +01:00
Chuan-kai Lin
81ab2025a1 Merge pull request #17032 from github/release-prep/2.18.1
Release preparation for version 2.18.1
2024-07-22 09:46:06 -07:00
Alexandre Boulgakov
06a9599906 C++: Update stats for using enum. 2024-07-22 17:42:31 +01:00
Chuan-kai Lin
cda4339056 Minor changelog improvements 2024-07-22 09:42:31 -07:00
Alexandre Boulgakov
11f5663afc C++: Add using enum upgrade and downgrade scripts. 2024-07-22 17:42:28 +01:00
Alexandre Boulgakov
a0954f15c0 C++: Support using enum declarations. 2024-07-22 17:42:25 +01:00
Geoffrey White
45e92cec6a C++: Extend tests for cpp/suspicious-allocation-size. 2024-07-22 17:34:49 +01:00
Salah Baddou
2ad70cbee2 Move SensitiveLoggerConfig source to extensible format 2024-07-22 17:34:00 +01:00
Mathias Vorreiter Pedersen
db9cd1f612 C++: Fix QLDoc copy-paste fails. 2024-07-22 17:08:01 +01:00
Geoffrey White
b1608d815b C++: Change note. 2024-07-22 16:34:41 +01:00
Geoffrey White
b4fa23d731 C++: Address false positive results in template instantiations. 2024-07-22 16:34:39 +01:00
Mathias Vorreiter Pedersen
c256c87a7e Update cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll 2024-07-22 16:34:23 +01:00
Mathias Vorreiter Pedersen
281212a22c C++: Accept test changes. 2024-07-22 16:23:26 +01:00
Mathias Vorreiter Pedersen
999fb07931 C++: Add more alias models. 2024-07-22 16:19:19 +01:00
github-actions[bot]
55935fc123 Release preparation for version 2.18.1 2024-07-22 14:56:15 +00:00
Geoffrey White
8262330e4d C++: Extend the placement new test cases for cpp/incorrect-allocation-error-handling. 2024-07-22 12:38:19 +01:00
Geoffrey White
b00e312569 C++: Replace placeholder key in the example for cpp/cleartext-storage-database. 2024-07-22 11:17:34 +01:00
Geoffrey White
f931dab14a C++: Improve the cpp/cleartext-* query examples by using libsodium rather than pseudocode. 2024-07-22 11:17:33 +01:00
Geoffrey White
ffc61ae1bb C++: Make memset_s a clearer recommendation in the .qhelp for cpp/memset-may-be-deleted. 2024-07-22 09:51:22 +01:00
Marcono1234
6d468c1bae Java: Update Annotation predicate examples in language guide 2024-07-21 19:31:55 +02:00
Jami Cogswell
4790656b79 Java: add TaintInheritingContent for URL synthetic fields 2024-07-20 23:03:32 -04:00
Owen Mansel-Chan
2a5144d9d9 Improve tests for reverse DNS sources 2024-07-20 21:40:02 +01:00
Owen Mansel-Chan
a64eafca2b Do not mention subcategories of remote
They are not in use by any language yet.
2024-07-20 21:31:08 +01:00
Owen Mansel-Chan
38aac1f444 Merge pull request #17024 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-20 21:15:45 +01:00
github-actions[bot]
f83b70dbc2 Add changed framework coverage reports 2024-07-20 00:17:36 +00:00
Geoffrey White
183b3fe6b0 Merge pull request #16570 from geoffw0/swiftssn
Swift: Use shared library for sensitive private information heuristics
2024-07-19 16:06:47 +01:00
Geoffrey White
1ca0de9067 Swift: Autoformat. 2024-07-19 13:55:33 +01:00
Geoffrey White
68a21663d9 Merge branch 'main' into swiftssn 2024-07-19 13:49:40 +01:00
Cornelius Riemenschneider
a63e70d173 Merge pull request #17015 from github/criemen/pytest-js
Integration tests: port to pytest.
2024-07-19 11:33:55 +02:00
Owen Mansel-Chan
24261b29d5 Merge pull request #17012 from owen-mc/go/mad/convert-sources-websockets
Go: convert models for websocket readers as remote flow sources to models-as-data
2024-07-19 10:04:27 +01:00
Cornelius Riemenschneider
620582fc09 Address review. 2024-07-19 10:50:11 +02:00
Ed Minnix
ad4bca9975 Fix provenance in tests 2024-07-18 18:18:24 -04:00
Ed Minnix
0990a370c7 Convert QL classes for Lastaflute to MaD 2024-07-18 17:41:06 -04:00
Ed Minnix
9713551448 Missing QLDoc 2024-07-18 17:41:05 -04:00
Ed Minnix
4fa45bb81c Change note 2024-07-18 17:41:03 -04:00
Ed Minnix
62944ee473 Add tests for lastaflute framework 2024-07-18 17:41:02 -04:00
Ed Minnix
3bd330423d Add some models for the org.lastaflute.web library
Methods annotated `@Execute` are handlers for URLs. Therefore, the
parameters of the methods annotated with the
`org.lastaflute.web.Execute` annotation are likely either URL parameters
or forms.
2024-07-18 17:41:00 -04:00
Cornelius Riemenschneider
4d943f8d94 Merge branch 'main' into criemen/pytest-js 2024-07-18 21:51:33 +02:00
Michael B. Gale
9a729144e8 Merge pull request #17016 from github/mbg/go/log-output-for-go-version
Go: Output stdout/stderr for `go version` if something goes wrong
2024-07-18 16:50:09 +01:00
Michael B. Gale
3a9ff64780 Go: Output stdout/stderr for go version if something goes wrong 2024-07-18 15:37:59 +01:00
Cornelius Riemenschneider
3badd61a56 Integration tests: port to pytest.
Requires an internal PR.
2024-07-18 16:36:11 +02:00
Cornelius Riemenschneider
8fa575d79b Merge pull request #17010 from github/criemen/disable-remote-cache-zipmerge
pkg.bzl: Disable remote caching of zipmerge steps.
2024-07-18 16:18:37 +02:00
Anders Schack-Mulligen
94078e851c Shared: Add support for provenance pretty-printing as a qltest postprocess step. 2024-07-18 15:34:30 +02:00
Chris Smowton
c1853e04f5 Merge pull request #17013 from smowton/smowton/admin/maven-enforcer-test
Java: Add test for autobuild with maven-enforcer
2024-07-18 12:51:06 +01:00
Owen Mansel-Chan
a717c30c02 Merge pull request #16958 from github/max-schaefer-patch-1
Java: Tag `java/non-https-url` with CWE-345 ("Insufficient Verification of Data Authenticity")
2024-07-18 12:29:56 +01:00
Owen Mansel-Chan
cb0589dfb7 Tests: accept model numbering changes 2024-07-18 11:35:52 +01:00
Chris Smowton
1abe0d0f6d Add test for autobuild with maven-enforcer 2024-07-18 11:16:46 +01:00
Owen Mansel-Chan
fc17b905f0 Convert WebSocketReaderAsSource to MaD 2024-07-18 10:53:13 +01:00
Owen Mansel-Chan
e6c1ff573a Merge branch 'main' into max-schaefer-patch-1 2024-07-18 10:39:42 +01:00
Cornelius Riemenschneider
afb6e412f0 pkg.bzl: Disable remote caching of zipmerge steps. 2024-07-18 08:52:04 +02:00
Owen Mansel-Chan
0a2ed8302a Add test for websocket remote flow sources 2024-07-18 07:45:03 +01:00
Owen Mansel-Chan
1e4aadfbfd Trivial: improve variable name 2024-07-18 07:44:19 +01:00
Owen Mansel-Chan
8bc883274f Minor improvement to jsoniter test 2024-07-18 07:38:23 +01:00
Owen Mansel-Chan
a9bf17ef49 Merge pull request #17000 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-18 06:48:28 +01:00
github-actions[bot]
ca42eac589 Add changed framework coverage reports 2024-07-18 00:17:53 +00:00
Owen Mansel-Chan
433137ada6 Merge pull request #16960 from owen-mc/go/mad-sources-fasthttp
Go: Convert fasthttp sources to MaD
2024-07-17 21:31:49 +01:00
Geoffrey White
98319be3a7 Merge pull request #16985 from geoffw0/madprov
C++: Support MaD alert provenance
2024-07-17 16:25:49 +01:00
Mathias Vorreiter Pedersen
7b8301ac7a C++: Accept more test changes. 2024-07-17 15:44:52 +01:00
Mathias Vorreiter Pedersen
1c8e0c453c C++: Fix more inconsistencies. 2024-07-17 15:44:50 +01:00
Mathias Vorreiter Pedersen
45ba0c3319 Merge pull request #16907 from MathiasVP/phi-escape-5
C++: Add a new `MemoryLocation` to represent sets of `Allocation`s
2024-07-17 15:44:04 +01:00
Geoffrey White
7029de5989 Swift: Attempt to speed up evaluation of the private information regex for Swift. 2024-07-17 15:43:30 +01:00
Mathias Vorreiter Pedersen
8a3a3fa263 C++: Sync identical files. 2024-07-17 14:39:08 +01:00
Mathias Vorreiter Pedersen
d5ccb2e396 C++: Add a large QLDoc with example to 'getInstructionSuccessor'. 2024-07-17 14:39:02 +01:00
Michael B. Gale
784a07353e Merge pull request #16916 from github/dependabot/go_modules/go/extractor/extractor-dependencies-5727fbca95
Bump the extractor-dependencies group across 1 directory with 2 updates
2024-07-17 13:40:16 +01:00
dependabot[bot]
3641dfebff Bump the extractor-dependencies group across 1 directory with 2 updates
Bumps the extractor-dependencies group with 2 updates in the /go/extractor directory: [golang.org/x/mod](https://github.com/golang/mod) and [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/mod` from 0.15.0 to 0.19.0
- [Commits](https://github.com/golang/mod/compare/v0.15.0...v0.19.0)

Updates `golang.org/x/tools` from 0.18.0 to 0.23.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.18.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
- dependency-name: golang.org/x/tools
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-17 11:46:01 +00:00
Paolo Tranquilli
bf69c76829 Merge pull request #16987 from github/redsun82/go
Go/Bazel: use gazelle `go_deps` instead of a vendor directory
2024-07-17 13:44:23 +02:00
Owen Mansel-Chan
d109b1e20d Accept model numbering changes in tests 2024-07-17 12:37:23 +01:00
Owen Mansel-Chan
6b52cd4957 Do not use "request" threat model kind
It is not supported yet.
2024-07-17 12:12:00 +01:00
Owen Mansel-Chan
cfdd48711b Convert Fasthttp::RequestHeader::RemoteFlowSource to MaD 2024-07-17 12:11:59 +01:00
Owen Mansel-Chan
abeca3d9f9 Convert Fasthttp::RequestCtx::RemoteFlowSource to MaD 2024-07-17 12:11:58 +01:00
Owen Mansel-Chan
729069e3d9 Convert Fasthttp::Request::RemoteFlowSource to MaD 2024-07-17 12:11:57 +01:00
Owen Mansel-Chan
c3169d258f Convert Fasthttp::Args::RemoteFlowSource to MaD 2024-07-17 12:11:57 +01:00
Owen Mansel-Chan
5a00b5ec96 Convert Fasthttp::URI::RemoteFlowSource to MaD 2024-07-17 12:11:56 +01:00
Owen Mansel-Chan
f33927457f Adapt test to work better for MaD
In MaD, `Argument[n]` corresponds to the post-update node of the
argument, which in the old version of the test will be the definition of
`dstReader` for the tests for `ReadBody`, `ReadLimitBody`,
`ContinueReadBodyStream`, `ContinueReadBody`.
2024-07-17 12:11:55 +01:00
Owen Mansel-Chan
a8a4a201bd Merge pull request #16992 from owen-mc/go/mad/use-package-grouping
Go: use package grouping in existing models-as-data models
2024-07-17 12:08:26 +01:00
Mathias Vorreiter Pedersen
5f70c44270 C++: Add change note. 2024-07-17 11:44:38 +01:00
Mathias Vorreiter Pedersen
9dd43d8e6f C++: Promote 'cpp/unsigned-difference-expression-compared-zero' to Code Scanning. 2024-07-17 11:44:37 +01:00
Mathias Vorreiter Pedersen
dc32806f3f Merge pull request #16988 from MathiasVP/unsigned-difference-compares-eq-zero-fp-fixes
C++: Fix FPs in `cpp/unsigned-difference-expression-compared-zero`
2024-07-17 11:39:17 +01:00
Owen Mansel-Chan
238c6ccb2e Merge pull request #17003 from owen-mc/go/update-library-coverage-frameworks
Go: Add frameworks to frameworks.csv
2024-07-17 11:26:11 +01:00
Owen Mansel-Chan
f67026f2ad Accept model numbering changes in tests 2024-07-17 11:02:28 +01:00
Owen Mansel-Chan
4c3220ea9d Use package grouping in models for gocb 2024-07-17 10:36:38 +01:00
Owen Mansel-Chan
4b2075bfb1 Split models for separate protobuf packages into separate files 2024-07-17 10:36:37 +01:00
Owen Mansel-Chan
aa0749e4ba Use package grouping for go-jose/jwt models 2024-07-17 10:36:37 +01:00
Owen Mansel-Chan
8a5a9418c7 Add frameworks to frameworks.csv 2024-07-17 10:20:44 +01:00
Owen Mansel-Chan
e6c7e1a0bc Merge pull request #16990 from owen-mc/go/change-string-prefix-check
Go: Change string prefix check
2024-07-17 09:57:45 +01:00
Owen Mansel-Chan
12fe998a4e Merge pull request #16986 from owen-mc/go/mad-sources-revel-nethttp
Go: Convert Revel and net/http sources to MaD
2024-07-16 22:13:50 +01:00
Jami
39f0288e09 Merge pull request #16964 from jcogs33/jcogs33/add-toByteArray-summaries
Java: add `IOUtils.toByteArray` summaries
2024-07-16 17:03:30 -04:00
Owen Mansel-Chan
e2356d9820 Merge pull request #16914 from owen-mc/java/android-app-detection
Java: Improve Android app detection
2024-07-16 21:52:43 +01:00
Owen Mansel-Chan
fc6b17ad64 Test: accept model numbers changing 2024-07-16 21:36:12 +01:00
Mathias Vorreiter Pedersen
dbe0fceea6 C++: Sync identical files. 2024-07-16 17:42:39 +01:00
Mathias Vorreiter Pedersen
083b9b77c9 C++: Delete redundant conjuncts. 2024-07-16 17:42:31 +01:00
Jami Cogswell
f90df85722 Java: update provenance numbers in tests again 2024-07-16 11:55:46 -04:00
Owen Mansel-Chan
535b4ea986 Convert net/http UserControlledRequestField sources to MaD 2024-07-16 16:53:02 +01:00
Owen Mansel-Chan
873fd6646b Convert Revel::UserControlledRequestMethod sources to MaD 2024-07-16 16:53:01 +01:00
Owen Mansel-Chan
034f2d4221 Convert Revel field read sources to MaD 2024-07-16 16:53:01 +01:00
Owen Mansel-Chan
2da1de7b13 Use packageGrouping in Revel models 2024-07-16 16:53:00 +01:00
Ian Lynagh
bf4a202cbd Merge pull request #16932 from igfoo/igfoo/kotlin-2.0.20
Kotlin: Add 2.0.20 support
2024-07-16 16:38:30 +01:00
Mathias Vorreiter Pedersen
9504e0f119 C++: Accept test changes. 2024-07-16 16:24:00 +01:00
Mathias Vorreiter Pedersen
8894fba17a C++: Sync identical files. 2024-07-16 16:19:04 +01:00
Mathias Vorreiter Pedersen
950d70ffed C++: Replace 'InitializeGroup' with 'UninitializedGroup'. 2024-07-16 16:16:50 +01:00
Owen Mansel-Chan
8647f69720 Change string prefix check
This avoids putting all the prefixes in the string pool.
2024-07-16 15:56:28 +01:00
Owen Mansel-Chan
0793c589f7 Merge pull request #16963 from owen-mc/go/mad-sources/go-restful-gin-mux
Go: Convert go-restful, Gin and Mux sources to MaD
2024-07-16 15:50:49 +01:00
Jami
a73170df49 Merge branch 'main' into jcogs33/add-toByteArray-summaries 2024-07-16 10:46:36 -04:00
Ian Lynagh
91dd99d7a6 Kotlin: Fixes for 2.0.20-Beta2 2024-07-16 15:07:34 +01:00
Ian Lynagh
06cc74f3aa Kotlin: Switch from 2.0.20-Beta1 to -Beta2 2024-07-16 15:07:33 +01:00
Ian Lynagh
adaeb01906 Kotlin: Update deps to 2.0.20-Beta2 2024-07-16 15:07:33 +01:00
Ian Lynagh
64ebfc6297 Kotlin: Add 2.0.20-Beta1 2024-07-16 15:07:32 +01:00
Ian Lynagh
eb0bcdd9b2 Kotlin: Add 2.0.20-Beta1 deps 2024-07-16 15:07:32 +01:00
Ian Lynagh
777cc357ee Kotlin: Support 2.0.20 2024-07-16 15:07:30 +01:00
Alexandre Boulgakov
f293b77bce Merge pull request #16972 from github/sashabu/templates
C++: Update tests to reflect on-demand indexing of special member functions.
2024-07-16 14:34:08 +01:00
Mathias Vorreiter Pedersen
4e916dedb1 C++: Add change note. 2024-07-16 13:17:31 +01:00
Mathias Vorreiter Pedersen
510bfb911a C++: Accept test changes. 2024-07-16 13:05:45 +01:00
Mathias Vorreiter Pedersen
3d88f08264 C++: Include more expressions in the base case. 2024-07-16 13:04:45 +01:00
Mathias Vorreiter Pedersen
983acf23bc C++: Add more FPs. 2024-07-16 13:04:42 +01:00
Mathias Vorreiter Pedersen
68e3be187a C++: Accept test changes. 2024-07-16 13:03:22 +01:00
Mathias Vorreiter Pedersen
d539ce0a01 C++: Use GVN for base case. 2024-07-16 13:02:43 +01:00
Mathias Vorreiter Pedersen
575fbd2578 C++: Prepatory simplification. 2024-07-16 13:02:41 +01:00
Mathias Vorreiter Pedersen
f5ec2315d7 C++: Add a FP from DCA. 2024-07-16 13:02:38 +01:00
Owen Mansel-Chan
db6cd1877c Accept suggested QLDoc fix
Co-authored-by: Chris Smowton <smowton@github.com>
2024-07-16 12:24:42 +01:00
Anders Schack-Mulligen
0d0b69eee0 Merge pull request #16835 from aschackmull/java/proper-clone-model
Java: Replace the MaD Object.clone() models with a non-aliasing value step.
2024-07-16 13:21:58 +02:00
Owen Mansel-Chan
ca06589386 Make comments clearer 2024-07-16 12:14:21 +01:00
Owen Mansel-Chan
cafb1181a0 Tests: Accept model numbering changes 2024-07-16 12:14:09 +01:00
Paolo Tranquilli
e469534b84 Go/Bazel: use gazelle go_deps instead of a vendor directory 2024-07-16 13:12:37 +02:00
Owen Mansel-Chan
124567caa4 Convert Mux::RequestVars to MaD 2024-07-16 11:18:19 +01:00
Owen Mansel-Chan
b3744ef230 Sort Gin source models 2024-07-16 11:18:18 +01:00
Owen Mansel-Chan
061c187a8e Convert GithubComGinGonicGinContextBindSource to MaD 2024-07-16 11:18:18 +01:00
Owen Mansel-Chan
ef833de123 Convert GithubComGinGonicGinContextSource to MaD 2024-07-16 11:18:17 +01:00
Owen Mansel-Chan
06a2a40f50 Convert GoRestfulReadEntitySource to MaD 2024-07-16 11:18:16 +01:00
Owen Mansel-Chan
7bfa4c1947 Convert GoRestfulSource to MaD 2024-07-16 11:18:14 +01:00
Anders Schack-Mulligen
37d78249e7 Java: Update provenance ids. 2024-07-16 11:11:54 +02:00
Anders Schack-Mulligen
2bfd65f145 Java: update expected output 2024-07-16 11:11:54 +02:00
Anders Schack-Mulligen
b2f57b4b48 Java: Update expected output. 2024-07-16 11:11:53 +02:00
Anders Schack-Mulligen
938f46b888 Java: Remove superfluous clone models. 2024-07-16 11:11:53 +02:00
Anders Schack-Mulligen
dc64a08467 Java: Update test expectations for Object.clone(). 2024-07-16 11:11:52 +02:00
Anders Schack-Mulligen
12d6875cc4 Java: Replace the MaD Object.clone() models with a non-aliasing value step. 2024-07-16 11:11:50 +02:00
Geoffrey White
e39e7656da C++: Change note. 2024-07-16 09:59:42 +01:00
Anders Schack-Mulligen
0fb27fb6fc Merge pull request #16979 from aschackmull/dataflow/internsets
Dataflow: Replace MakeSets with QlBuiltins::InternSets.
2024-07-16 10:47:07 +02:00
Geoffrey White
195c20cfd5 C++: Fix provenance for sources/sinks. 2024-07-16 09:33:51 +01:00
Geoffrey White
eefbb676e9 C++: Support alert provenance. 2024-07-16 09:33:48 +01:00
Owen Mansel-Chan
2dc63ef8d1 Merge pull request #16856 from owen-mc/go/mad-sources-chi-echo-elazarl
Go: Convert  chi echo and elazarl sources to MaD
2024-07-16 08:00:51 +01:00
Jami Cogswell
8f6d4be256 Java: update tests 2024-07-15 14:33:40 -04:00
Geoffrey White
391816c9e7 C++: Add path graph to one of the external models tests. 2024-07-15 17:37:55 +01:00
Jami
b70a4c839c Merge branch 'main' into jcogs33/add-toByteArray-summaries 2024-07-15 12:35:05 -04:00
Jami Cogswell
7f34dd1e0a Java: update change note 2024-07-15 12:15:02 -04:00
Jami Cogswell
cd82ada239 Java: add manual models for all overloads of IOUtils.toByteArray 2024-07-15 12:12:31 -04:00
Michael Nebel
18cde3bd78 Merge pull request #16873 from michaelnebel/csharp/narrowsourcegeneration
C#: Narrow source model generation.
2024-07-15 15:53:13 +02:00
Mathias Vorreiter Pedersen
1c336985e0 Merge pull request #16502 from github/MathiasVP-patch-1
Swift: Remove beta label
2024-07-15 13:54:34 +01:00
Mathias Vorreiter Pedersen
29e9c05f26 Merge branch 'main' into MathiasVP-patch-1 2024-07-15 13:27:42 +01:00
Anders Schack-Mulligen
da5abc8321 Dataflow: Replace MakeSets with QlBuiltins::InternSets. 2024-07-15 13:35:57 +02:00
Mathias Vorreiter Pedersen
5da3fb5e05 Merge pull request #16959 from MathiasVP/promote-iterator-to-expired-container-to-code-scanning
C++: Promote `cp/iterator-to-expired-container` to Code Scanning
2024-07-15 11:55:32 +01:00
Ian Lynagh
a951718f2e Merge pull request #16955 from igfoo/igfoo/kotlin-ga
Kotlin: Kotlin support is now out of beta, and generally available
2024-07-15 11:30:20 +01:00
Michael Nebel
8eba4a3e51 C#: Code quality improvement. 2024-07-15 08:05:13 +02:00
Owen Mansel-Chan
cd9b364e5a Merge pull request #16974 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-14 22:31:55 +01:00
Owen Mansel-Chan
3efbee0d81 Accept provenance numbering changes 2024-07-14 16:06:29 +01:00
Owen Mansel-Chan
99ed3c2ac1 Convert ElazarlGoproxy::UserControlledRequestData to MaD 2024-07-14 14:28:48 +01:00
Owen Mansel-Chan
2ec64a9ca8 Convert EchoContextBinder to MaD 2024-07-14 14:28:47 +01:00
Owen Mansel-Chan
3fc598dbe9 Convert EchoContextSource to MaD 2024-07-14 14:28:46 +01:00
Owen Mansel-Chan
5b38d51f62 Convert Chi::UserControlledMethod to MaD 2024-07-14 14:28:46 +01:00
Owen Mansel-Chan
3bd4a203bb Convert Chi::UserControlledFunction to MaD 2024-07-14 14:28:44 +01:00
github-actions[bot]
7fc95b8eff Add changed framework coverage reports 2024-07-14 00:20:23 +00:00
Owen Mansel-Chan
dd1d5ecab4 Merge pull request #16967 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-13 17:24:36 +01:00
Jami
9c98296ad2 Merge pull request #16965 from jcogs33/jcogs33/add-FilePath-exists-sink
Java: add path-injection sink for `hudson.FilePath.exists()`
2024-07-13 10:15:37 -04:00
Owen Mansel-Chan
b7a5252cb0 Refactor inAndroidApplication 2024-07-13 07:35:02 +01:00
Owen Mansel-Chan
8dcef8223f Tweak change note 2024-07-13 07:31:18 +01:00
github-actions[bot]
5d657ba99a Add changed framework coverage reports 2024-07-13 00:18:24 +00:00
Alexandre Boulgakov
faf77d5526 C++: Update special members test results. 2024-07-12 18:10:32 +01:00
Alexandre Boulgakov
b3b04b4e5b C++: Extend template member test to better test on-demand indexing of special member functions. 2024-07-12 18:08:18 +01:00
Alexandre Boulgakov
18d9310a61 C++: Update tests to reflect on-demand indexing of special member functions.
None of these tests were relying on the removed rows.
2024-07-12 18:06:56 +01:00
Sid Shankar
772344dfa4 Merge pull request #16886 from aegilops/aegilops/polyfill-io-compromised-script 2024-07-12 11:34:17 -04:00
Paul Hodgkinson
de5ec1fc01 Merge branch 'main' into aegilops/polyfill-io-compromised-script 2024-07-12 14:22:15 +01:00
aegilops
79980a98a2 Added links to eventual location of CUSTOMIZING.md 2024-07-12 14:21:50 +01:00
Paul Hodgkinson
11249e7182 Apply suggestions from code review - docs tweaks of CUSTOMIZING.md
Co-authored-by: Felicity Chapman <felicitymay@github.com>
2024-07-12 14:20:03 +01:00
Rasmus Wriedt Larsen
1de2943a9b Merge pull request #16940 from RasmusWL/rasmuswl/BuiltinModuleExtractable
Python: Handle diagnostics writing for `BuiltinModuleExtractable`
2024-07-12 14:46:30 +02:00
Tom Hvitved
8a9f0bf433 Merge pull request #16966 from hvitved/ssa/reduce-caching
SSA: Reduce caching in data-flow integration layer
2024-07-12 14:22:49 +02:00
Paul Hodgkinson
c9af53f050 Merge branch 'main' into aegilops/polyfill-io-compromised-script 2024-07-12 12:53:44 +01:00
aegilops
61df4d2f04 Merge branch 'aegilops/polyfill-io-compromised-script' of https://github.com/aegilops/codeql into aegilops/polyfill-io-compromised-script 2024-07-12 12:49:18 +01:00
aegilops
00d91dc6ba Created guide on customizing these queries, and referenced it in the query help 2024-07-12 12:49:09 +01:00
aegilops
040f948e65 Added a note that SRI can be considered for some dynamic services 2024-07-12 12:48:36 +01:00
Tamás Vajk
0839742daa Merge pull request #16968 from tamasvajk/feature/buildless-deterministic-file-order-2
C#: Order syntax trees before creating compilation
2024-07-12 13:47:21 +02:00
Rasmus Wriedt Larsen
354394d4c2 Python: Don't use fake locations in diagnostics
Some of the internal tooling would not be too happy about this :D
2024-07-12 13:36:41 +02:00
Paul Hodgkinson
3f37fe6add Apply suggestions from code review - docs and wording
Docs suggestions accepted, thank you 🙏

Co-authored-by: Felicity Chapman <felicitymay@github.com>
2024-07-12 11:48:39 +01:00
Mathias Vorreiter Pedersen
f6627cc092 Merge pull request #16969 from MathiasVP/add-missing-underlying-type
C++: Strip specifiers and typedefs when finding iterator parameter for string taint function
2024-07-12 11:35:52 +01:00
Tom Hvitved
04f173d14e SSA: Reduce caching in data-flow integration layer 2024-07-12 11:04:03 +02:00
Mathias Vorreiter Pedersen
7a2b170da2 C++: Accept test changes. 2024-07-12 09:54:20 +01:00
Mathias Vorreiter Pedersen
813f08ef57 C++: Strip away specifiers and typedefs when finding iterator parameters for a string taint function. 2024-07-12 09:54:04 +01:00
Tamas Vajk
5a41b2c5fb C#: Order syntax trees before creating compilation 2024-07-12 10:12:20 +02:00
Tamas Vajk
d689ab0916 Revert "C#: Order files in buildless extraction"
This reverts commit ccf56a21c2.
2024-07-12 10:11:13 +02:00
Jami Cogswell
6b497da15f Java: fix line number changes in tests 2024-07-11 15:33:09 -04:00
Jami Cogswell
ab9a6faaf3 Java: add change note 2024-07-11 15:10:11 -04:00
Jami Cogswell
77a8ba934c Java: add path-injection sink for hudson.FilePath.exists() 2024-07-11 15:03:40 -04:00
Jami Cogswell
744a1a9b72 Java: fix line number changes in tests 2024-07-11 14:07:23 -04:00
Jami Cogswell
5cf05ec863 Java: add change note 2024-07-11 13:40:50 -04:00
Jami Cogswell
4a1497f367 Java: add IOUtils.toByteArray(InputStream) summary 2024-07-11 13:33:08 -04:00
Mathias Vorreiter Pedersen
1a2b4a30bb Merge pull request #16939 from geoffw0/docsforautofix
C++: Assorted minor doc improvements
2024-07-11 18:30:45 +01:00
Calum Grant
24914efcb8 Merge pull request #16956 from github/calumgrant/cpp20-array-sizes
C++: Test C++20 implicit array sizes.
2024-07-11 17:44:08 +01:00
Calum Grant
13c25a494f C++: Move change notes to correct location 2024-07-11 16:49:17 +01:00
Geoffrey White
bf47574796 Merge branch 'main' into docsforautofix 2024-07-11 16:42:27 +01:00
Ian Lynagh
5c97a5f667 Kotlin: Kotlin support is now out of beta, and generally available 2024-07-11 16:11:40 +01:00
Mathias Vorreiter Pedersen
a2a065c04e Merge pull request #16962 from geoffw0/ga-note
Swift: Add GA change note.
2024-07-11 16:04:19 +01:00
Geoffrey White
f5bfdbf5ef Swift: Fix change note file. 2024-07-11 16:01:52 +01:00
Tom Hvitved
9794269550 Merge pull request #16952 from hvitved/ssa/barrier-guards-param-mod
SSA: Make barrier guards a parameterized module
2024-07-11 16:46:02 +02:00
Geoffrey White
e5761d6524 Swift: Add GA change note. 2024-07-11 15:36:28 +01:00
Rasmus Wriedt Larsen
f41d2a896c Merge pull request #16771 from porcupineyhairs/js2py
Python : Arbitrary code execution due to Js2Py
2024-07-11 15:31:57 +02:00
Mathias Vorreiter Pedersen
64513fb6c2 C++: Add change note. 2024-07-11 14:26:47 +01:00
Mathias Vorreiter Pedersen
8012f3b2f7 C++: Increase the precision of 'cpp/iterator-to-expired-container' to high. 2024-07-11 14:26:05 +01:00
Joe Farebrother
8152ec7472 Merge pull request #16696 from joefarebrother/python-cookie-write-headers
Python: Model CookieWrites from HeaderWrites
2024-07-11 14:25:54 +01:00
Angela P Wen
0b6714e06f Merge pull request #16954 from github/angelapwen/remove-ci-workaround
Remove CI workaround for `DatabaseQualityDiagnostics.ql`
2024-07-11 15:21:31 +02:00
Calum Grant
c6fb50095b C++: Change note and autoformat 2024-07-11 14:21:09 +01:00
Rasmus Wriedt Larsen
5ecde387af Python: Fix .expected 2024-07-11 14:42:26 +02:00
Max Schaefer
d5d0cf5d90 Java: Tag java/non-https-url with CWE-345 2024-07-11 13:37:09 +01:00
Calum Grant
29df3cb5b3 C++: Add test for C++20 implicit array sizes
Implement NewArrayExpr.getArraySize()
2024-07-11 12:59:52 +01:00
Ian Lynagh
311799c798 Merge pull request #16899 from igfoo/igfoo/semmle_dist
Java/Kotlin: Remove legacy $SEMMLE_DIST support
2024-07-11 12:48:53 +01:00
Erik Krogh Kristensen
de9370ae95 Merge pull request #16540 from aegilops/aegilops/js/insecure-helmet-middleware
JS/TS: insecure Helmet middleware (new query)
2024-07-11 13:48:09 +02:00
Owen Mansel-Chan
5bdef38dd9 Merge pull request #16941 from owen-mc/go/mad-package-alias
Go: Allow grouping import paths for models-as-data
2024-07-11 12:27:43 +01:00
Angela P Wen
90641a5152 Remove CI workaround for DatabaseQualityDiagnostics.ql 2024-07-11 13:22:06 +02:00
Jeroen Ketema
87d9218369 Merge pull request #16951 from jketema/builtin-op
C++: Support more builtin operations
2024-07-11 12:50:46 +02:00
aegilops
d71be8aeaf Moved from experimental into default queries 2024-07-11 11:44:01 +01:00
Michael B. Gale
45b782554c Merge pull request #16925 from github/mbg/go/add-vendor-env-var
Go: Add environment variable to include `vendor` directories in extraction
2024-07-11 11:06:31 +01:00
Paul Hodgkinson
412ad177c2 Merge branch 'main' into aegilops/js/insecure-helmet-middleware 2024-07-11 11:01:38 +01:00
Jeroen Ketema
5e0ce7efc4 C++: Fix test 2024-07-11 11:58:25 +02:00
Jeroen Ketema
ed42c3cd6f C++: Fix class extension 2024-07-11 11:48:01 +02:00
Tom Hvitved
16b142d332 SSA: Make barrier guards a parameterized module 2024-07-11 11:34:56 +02:00
Tom Hvitved
a452eadb33 Merge pull request #16946 from hvitved/csharp/fewer-version-regexps
C#: Perform fewer `regexpCapture`s when matching version numbers
2024-07-11 11:22:36 +02:00
Tamás Vajk
fd8cda36e5 Merge pull request #16924 from tamasvajk/feature/winforms-linux
C#: Restore Windows dependencies when Windows Forms or WPF usage is detected
2024-07-11 11:01:37 +02:00
Jeroen Ketema
48bf06f1aa C++: Fix getAPrimaryQlClass 2024-07-11 10:43:17 +02:00
Jeroen Ketema
0413e0e090 C++: Clean up QLDoc and add change note 2024-07-11 10:37:26 +02:00
Owen Mansel-Chan
3417605b6d Tests: update provenance numbering 2024-07-11 06:42:58 +01:00
Jeroen Ketema
3f789bad60 C++: Support more builtin operations 2024-07-10 21:27:09 +02:00
Owen Mansel-Chan
2c7fbda2ec Accept review suggestion for QLDoc 2024-07-10 16:48:11 +01:00
Owen Mansel-Chan
32acff76c2 Make groupPrefix() private
This could be made public in future. But I expect that we will want to
use this logic for QL models as well then we will want to move it into a
different file, which will be much easier if it's all private at the
moment.
2024-07-10 16:48:10 +01:00
Owen Mansel-Chan
b64ef84393 Use prefix() method on string to check for group prefix 2024-07-10 16:48:10 +01:00
Owen Mansel-Chan
3e2ebf436c Move logic for dealing with groups into a predicate 2024-07-10 16:48:09 +01:00
Owen Mansel-Chan
f6b9195a61 Add validation of package groups 2024-07-10 16:48:08 +01:00
Owen Mansel-Chan
ab991af2a5 Fix package validation errors 2024-07-10 16:48:07 +01:00
Owen Mansel-Chan
f650e3f72b Update MaD documentation explain "group:" in package column 2024-07-10 16:48:06 +01:00
Owen Mansel-Chan
01afa360d7 Tests: accept model numbering changes 2024-07-10 16:48:05 +01:00
Owen Mansel-Chan
1e448d547d Rename Beego MaD files using path from current version 2024-07-10 16:48:04 +01:00
Owen Mansel-Chan
fde7d7b969 Use packageGrouping for Beego models 2024-07-10 16:48:03 +01:00
Michael Nebel
4193b7e591 Allow grouping import paths for models-as-data 2024-07-10 16:48:02 +01:00
Tamás Vajk
57efb84b98 Merge pull request #16945 from tamasvajk/feature/buildless-deterministic-file-order
C#: Order files in buildless extraction
2024-07-10 16:25:01 +02:00
Tom Hvitved
39b5dbfaf7 C#: Perform fewer regexpCaptures when matching version numbers 2024-07-10 14:50:39 +02:00
Tom Hvitved
f18338259f Merge pull request #16884 from hvitved/ssa/dataflow-integration
SSA: Add data flow integration layer
2024-07-10 12:47:37 +02:00
Geoffrey White
0344381120 Merge remote-tracking branch 'upstream/main' into docsforautofix 2024-07-10 11:17:52 +01:00
Geoffrey White
74384625f6 C++: Autoformat. 2024-07-10 11:17:44 +01:00
Tom Hvitved
8979bac4d8 Update shared/ssa/codeql/ssa/Ssa.qll
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2024-07-10 10:55:13 +02:00
Tamas Vajk
ccf56a21c2 C#: Order files in buildless extraction 2024-07-10 10:53:53 +02:00
Tom Hvitved
7928d751d1 Address review comment 2024-07-10 09:52:09 +02:00
aegilops
01ec7c22df Fixed test 2024-07-09 19:19:06 +01:00
aegilops
0aab2aef3b Formatting of QLL 2024-07-09 18:16:37 +01:00
aegilops
dae2aeb7d3 QLDoc 2024-07-09 18:16:02 +01:00
Mathias Vorreiter Pedersen
81593ece5a Merge pull request #16935 from MathiasVP/iterator-to-expired-container-fp-5
C++: Add `cpp/iterator-to-expired-container` FP
2024-07-09 17:07:19 +01:00
aegilops
86afd54a9b Moved new query to 'experimental'
Moved lists of domains to data extensions, including adding those to the overall qlpack.yml

Expanded scope of new query to further domains operated by the untrusted owners of polyfill.io
2024-07-09 16:38:01 +01:00
Rasmus Wriedt Larsen
60d1dc8af8 Python: Bump extractor version 2024-07-09 14:15:52 +02:00
Rasmus Wriedt Larsen
6b3625e24e Python: Handle diagnostics writing for BuiltinModuleExtractable 2024-07-09 14:15:52 +02:00
Rasmus Wriedt Larsen
c1da2c1d2f Python: Gracefully handle exceptions in diagnostics writing 2024-07-09 14:15:51 +02:00
Rasmus Wriedt Larsen
a8b976b389 Python: Always log errors before writing diagnostics
So we have the info in the logs if the diagnostics processing fails
2024-07-09 13:47:53 +02:00
Tom Hvitved
d41eae6fc3 SSA: Add data-flow integration layer 2024-07-09 12:49:22 +02:00
Mathias Vorreiter Pedersen
48edb77300 C++: Add 'cpp/iterator-to-expired-container' FP. 2024-07-09 11:24:18 +01:00
Mathias Vorreiter Pedersen
6359388cea Merge pull request #16915 from MathiasVP/fix-iterator-to-expired-container-fp-4
C++: Fix `cpp/iterator-to-expired-container` FPs
2024-07-09 11:23:46 +01:00
Owen Mansel-Chan
d4bfab4735 Accept minor copy-editing suggestions. 2024-07-09 07:00:01 +01:00
Mathias Vorreiter Pedersen
39ad4d4a89 Merge pull request #16930 from MathiasVP/promote-unsafe-strncat-to-code-scanning 2024-07-08 21:51:57 +01:00
Mathias Vorreiter Pedersen
2c5f007687 Merge pull request #16929 from MathiasVP/add-unsafe-strncat-fp 2024-07-08 18:54:58 +01:00
Cornelius Riemenschneider
f87e680185 Merge pull request #16928 from github/criemen/install-remove
Install script: Windows-compatible cleanup path.
2024-07-08 17:53:18 +02:00
Owen Mansel-Chan
496e76c1c5 Merge pull request #16931 from owen-mc/go/fix/clear-sanitizer
Go: fix `clear` sanitizer
2024-07-08 16:52:37 +01:00
Cornelius Riemenschneider
16660ab1df address review 2024-07-08 17:37:33 +02:00
Cornelius Riemenschneider
8df2e4952c address review 2024-07-08 17:27:17 +02:00
Owen Mansel-Chan
a774aacfa8 Add change note 2024-07-08 16:09:17 +01:00
Mathias Vorreiter Pedersen
9cfd06c761 C++: Increase the precision of 'cpp/unsafe-strncat' to high. 2024-07-08 16:06:58 +01:00
Owen Mansel-Chan
68929d1f73 Fix definition of ClearSanitizer 2024-07-08 16:05:17 +01:00
Owen Mansel-Chan
eec2aa82a6 Add failing tests for ClearSanitizer 2024-07-08 16:05:04 +01:00
Mathias Vorreiter Pedersen
962c73da16 C++: Promote 'cpp/unsafe-strncat' to Code Scanning. 2024-07-08 16:02:29 +01:00
Angela P Wen
80bd361607 Merge pull request #16926 from github/post-release-prep/codeql-cli-2.18.0
Post-release preparation for codeql-cli-2.18.0
2024-07-08 16:51:16 +02:00
Owen Mansel-Chan
b83147fa44 Add links on threat models to change note 2024-07-08 15:39:27 +01:00
Owen Mansel-Chan
8241d0b7ef Update QLDoc for ReverseDnsUserInput 2024-07-08 15:33:39 +01:00
Owen Mansel-Chan
07a25a233d Update threat model documentation 2024-07-08 15:32:47 +01:00
Cornelius Riemenschneider
bb78536804 Install script: Windows-compatible cleanup path.
Windows might need some retrying around deleting
the target directory.
2024-07-08 16:21:29 +02:00
Owen Mansel-Chan
64432215a9 Make "reverse-dns" pass validation 2024-07-08 15:16:14 +01:00
Owen Mansel-Chan
8526510783 Add ungrouped threat models to threat-model-grouping.model.yml 2024-07-08 15:15:40 +01:00
Mathias Vorreiter Pedersen
d5d04f2f4c C++: Add a 'cpp/unsafe-strncat' FP. 2024-07-08 15:13:00 +01:00
Geoffrey White
8818f63ca7 C++: Add some practical details to the examples. 2024-07-08 14:32:05 +01:00
Geoffrey White
80af5b7725 C++: Add a third example for cpp/world-writable-file-creation. 2024-07-08 14:32:04 +01:00
Geoffrey White
4f0d725acd C++: Add a 'good' example as well. 2024-07-08 14:32:03 +01:00
Geoffrey White
d52210d565 C++: Improve the example for cpp/return-stack-allocated-memory. 2024-07-08 14:32:01 +01:00
Geoffrey White
3c70583aa2 C++: Add close calls to examples for cpp/toctou-race-condition. 2024-07-08 14:32:00 +01:00
Geoffrey White
0288499801 C++: Rephrase the alert message for cpp/wrong-type-format-argument to be less prescriptive. 2024-07-08 14:31:59 +01:00
github-actions[bot]
ae3aba061b Post-release preparation for codeql-cli-2.18.0 2024-07-08 13:30:13 +00:00
Michael B. Gale
7ca57e114f Go: Add CODEQL_EXTRACTOR_GO_EXTRACT_VENDOR_DIRS env var
If set to `true`, this allows `vendor` directories to be extracted
2024-07-08 14:08:19 +01:00
Michael B. Gale
bc61a58000 Go: Add integration test for extracting vendored dependencies 2024-07-08 14:05:06 +01:00
Tamas Vajk
7387c565e4 C#: Restore Windows dependencies when Windows Forms or WPF usage is detected 2024-07-08 14:44:20 +02:00
Tamas Vajk
7fc1e13672 C#: Add buildless integration test with Windows Forms application 2024-07-08 14:08:15 +02:00
Paolo Tranquilli
0421ceff93 Merge pull request #16922 from github/redsun82/kotlin-wrapper
Kotlin: make wrapper cache downloaded zips
2024-07-08 13:53:35 +02:00
Paolo Tranquilli
a30e7d2cfd Kotlin: add all .kotlin_* in dev to .gitignore 2024-07-08 13:18:56 +02:00
Angela P Wen
dc20b0d19e Merge pull request #16921 from github/release-prep/2.18.0
Release preparation for version 2.18.0
2024-07-08 13:12:57 +02:00
Chris Smowton
d9573596c7 Merge pull request #16810 from smowton/smowton/feature/java-low-db-quality-query
Java: add diagnostic query indicating low database quality
2024-07-08 12:06:42 +01:00
aegilops
5a3328b07a Merge branch 'aegilops/js/insecure-helmet-middleware' of https://github.com/aegilops/codeql into aegilops/js/insecure-helmet-middleware 2024-07-08 11:31:15 +01:00
aegilops
2aff2a7385 Fixed code markup 2024-07-08 11:31:06 +01:00
Paul Hodgkinson
d896fdf9fa Merge branch 'main' into aegilops/js/insecure-helmet-middleware 2024-07-08 11:25:47 +01:00
Rasmus Wriedt Larsen
173cd13ded Python: Add test for impossible isinstance flow 2024-07-08 12:06:53 +02:00
aegilops
c003f265b0 Fixed missing li closing tag 2024-07-08 10:58:06 +01:00
Paolo Tranquilli
002e1eb730 Kotlin: make wrapper cache downloaded zips
Also removed the version check step, as a version not existing will give
a 404 any way later on, and that was adding a delay.

The cache is stored in a `.kotlinc_zips` and will be cleaned up by
`--clear`.
2024-07-08 11:57:07 +02:00
aegilops
1fe14e26b1 Split out "compromised" functionality 2024-07-08 10:56:12 +01:00
Chris Smowton
c4f32ec080 Trivial change to trigger CI 2024-07-08 10:51:24 +01:00
github-actions[bot]
b0d6778652 Release preparation for version 2.18.0 2024-07-08 09:10:51 +00:00
Owen Mansel-Chan
e2a6358048 Update tests so they still work 2024-07-07 00:24:28 +01:00
Owen Mansel-Chan
de5fc4e609 Add change notes 2024-07-07 00:24:27 +01:00
Owen Mansel-Chan
5347770608 Update Android app detection 2024-07-07 00:24:25 +01:00
Mathias Vorreiter Pedersen
0e6b2f0f53 C++: Accept query test changes. 2024-07-06 12:27:42 +01:00
Mathias Vorreiter Pedersen
8ccdc2518f C++: Accept test changes. 2024-07-06 12:27:41 +01:00
Mathias Vorreiter Pedersen
a747ffca07 C++: Address definitions should also handle ssa variables that are calls. 2024-07-06 12:27:35 +01:00
Owen Mansel-Chan
9c82966022 Move detection of Android app to one place 2024-07-05 23:47:56 +01:00
Mathias Vorreiter Pedersen
79919d3c58 C++: Add FP dataflow test. 2024-07-05 17:36:47 +01:00
Mathias Vorreiter Pedersen
31a5a7aebc Merge pull request #16913 from MathiasVP/add-iterator-to-expired-container-fp-3
C++: Add `cpp/iterator-to-expired-container` FP test
2024-07-05 16:26:08 +01:00
Mathias Vorreiter Pedersen
aad233b776 C++: Add FP test. 2024-07-05 15:52:10 +01:00
Koen Vlaswinkel
b7a67b1e51 Merge pull request #16910 from github/koesie10/python-exclude-test-files
Python: Exclude probable test files in model editor
2024-07-05 15:49:07 +02:00
Koen Vlaswinkel
779795b421 Python: Exclude probable test files in model editor 2024-07-05 11:06:22 +02:00
Geoffrey White
5d898727c0 C++: Add the examples to the test. 2024-07-04 17:11:11 +01:00
Geoffrey White
1343e4c9aa C++: Add another 'good' example for cpp/unsigned-difference-expression-compared-zero. 2024-07-04 17:11:10 +01:00
Geoffrey White
7abece46c7 C++: Add a 'good' example for cpp/unsigned-difference-expression-compared-zero. 2024-07-04 17:11:09 +01:00
Geoffrey White
4de43e1bfa C++: Add the examples to the test. 2024-07-04 17:11:08 +01:00
Geoffrey White
f64743e91d C++: Fix mistake in example for cpp/incorrect-allocation-error-handling. 2024-07-04 16:19:32 +01:00
Mathias Vorreiter Pedersen
4893785c68 C++: Accept test changes to GVN. 2024-07-04 15:15:46 +01:00
Mathias Vorreiter Pedersen
5d58cf6208 C++: Accept query test changes. 2024-07-04 15:15:38 +01:00
Mathias Vorreiter Pedersen
b954845318 C++: Ignore the new 'InitializeGroup' instruction in dataflow. 2024-07-04 14:22:06 +01:00
Mathias Vorreiter Pedersen
6ef9dba2fb C++: Accept test changes. 2024-07-04 14:22:04 +01:00
Mathias Vorreiter Pedersen
89f0705585 C++: Sync identical files. 2024-07-04 14:22:03 +01:00
Mathias Vorreiter Pedersen
72b52cc814 C++: Insert Chi instructions after InitializeGroup instructions whose variable group's virtual variable is all aliased memory. 2024-07-04 14:22:02 +01:00
Mathias Vorreiter Pedersen
d1e1037586 C++: Accept test changes. 2024-07-04 14:22:00 +01:00
Mathias Vorreiter Pedersen
92e814b75e C++: Stub 'VariableGroup' and 'GroupedMemoryLocation' in unaliased SSA so that the pyrameterized files compile. 2024-07-04 14:21:59 +01:00
Mathias Vorreiter Pedersen
db525f5cee C++: Sync identical files. 2024-07-04 14:21:58 +01:00
Mathias Vorreiter Pedersen
03ec184ee0 C++: Add 'InitializeGroup' instructions to the successor relation. 2024-07-04 14:21:56 +01:00
Mathias Vorreiter Pedersen
c4d72e5b4f C++: No need to check if the offset is non-negative. It always is because of 'defBlock.getInstruction(oldOffset)' has a result. 2024-07-04 14:21:55 +01:00
Mathias Vorreiter Pedersen
cf8b2d55c5 C++: Hide away the 'multiply by two' hack in a predicate. 2024-07-04 14:21:53 +01:00
Mathias Vorreiter Pedersen
8db7ece8d4 C++: Fill in trivial parts of SSA. 2024-07-04 14:21:51 +01:00
Mathias Vorreiter Pedersen
2c4bf13d05 C++: Sync identical files. 2024-07-04 14:21:50 +01:00
Mathias Vorreiter Pedersen
c54dc49891 C++: Improve 'toString' on the 'InitializeGroup' instruction. 2024-07-04 14:21:49 +01:00
Mathias Vorreiter Pedersen
b185c67d4f C++: Handle overlap with grouped memory locations. 2024-07-04 14:21:47 +01:00
Mathias Vorreiter Pedersen
e7c43b3fcc C++: Return grouped memory locations from 'getOperandMemoryLocation' and 'getResultMemoryLocation'. 2024-07-04 14:21:46 +01:00
Mathias Vorreiter Pedersen
09c03d9a5f C++: The virtual variable of a variable that is contained in a grouped memory location is that grouped memory location (or all aliased memory if it escapes). 2024-07-04 14:21:45 +01:00
Mathias Vorreiter Pedersen
399d47d2cb C++: Cleanup 2024-07-04 14:21:43 +01:00
Mathias Vorreiter Pedersen
5e1c67f5f1 C++: Add a new 'MemoryLocation' that represents a set of allocations. 2024-07-04 14:21:42 +01:00
Paolo Tranquilli
3ae4cb2f9d Merge pull request #16906 from github/redsun82/swift-codespace
Swift: add `git lfs` installation to codespace configuration
2024-07-04 14:55:31 +02:00
Paolo Tranquilli
5c7bbc0287 Swift: add git lfs installation to codespace configuration 2024-07-04 14:28:22 +02:00
Rasmus Wriedt Larsen
0a32f9fed6 Python: Update query metadata 2024-07-04 14:09:37 +02:00
Rasmus Wriedt Larsen
8d1113cdaf Python: Fixup qhelp 2024-07-04 14:01:30 +02:00
Mathias Vorreiter Pedersen
c5c4f08bea C++: Rename from 'getAllocation' to 'getAnAllocation'. 2024-07-04 12:12:00 +01:00
Mathias Vorreiter Pedersen
0b84329e8c C++: Expose the 'AddressOperand' from both 'hasResultMemoryAccess' and 'hasOperandMemoryAccess' and add a boolean column indicating whether they relate to multiple 'Allocation's. 2024-07-04 12:11:59 +01:00
Mathias Vorreiter Pedersen
1c8cf3cd2c C++: Sync identical files. 2024-07-04 12:11:58 +01:00
Mathias Vorreiter Pedersen
ffa55b4bf8 C++: Disable special casing of Phi operands in alias analysis. Instead, we simply add flow through them. 2024-07-04 12:11:57 +01:00
Mathias Vorreiter Pedersen
ef8532982c C++: Sync identical files. 2024-07-04 12:11:56 +01:00
Mathias Vorreiter Pedersen
72679c82a9 C++: Add a new opcode and instruction. 2024-07-04 12:11:54 +01:00
Mathias Vorreiter Pedersen
4953e7e7fa C++: Add tests. 2024-07-04 12:11:50 +01:00
Erik Krogh Kristensen
1c0c51faaf Merge pull request #16904 from igfoo/igfoo/shouldExtract
JS: Remove call to shouldExtract
2024-07-04 12:44:54 +02:00
Tom Hvitved
d675304703 Merge pull request #16875 from hvitved/csharp/ssa-param-def
C#: Move implicit entry definitions inside method bodies in SSA construction
2024-07-04 10:51:06 +02:00
Tamás Vajk
456c649c7d Merge pull request #16895 from tamasvajk/feature/fix-glob-pattern-processing
C#: Fix glob pattern processing: allow `**/` to match empty string
2024-07-04 10:46:36 +02:00
Ian Lynagh
95a418aa14 JS: Remove call to shouldExtract
It always returns true nowadays.
2024-07-04 09:42:07 +01:00
Mathias Vorreiter Pedersen
8e18e7d4e6 Merge pull request #16791 from MathiasVP/collection-content-2
C++: Add support for `Element` content
2024-07-04 08:52:33 +01:00
Tom Hvitved
da0909c080 Merge pull request #16896 from hvitved/ssa/dataflow-integration-prep
SSA: Add `BasicBlock.{getNode/1,length/0}` to the input signature
2024-07-03 19:56:35 +02:00
Mathias Vorreiter Pedersen
356d928544 C++: Accept test changes. 2024-07-03 18:16:20 +01:00
Mathias Vorreiter Pedersen
af28dd8eb4 C++: Add bsl models for 'array::front' and 'array::back'. 2024-07-03 18:14:10 +01:00
Mathias Vorreiter Pedersen
f9d6c63cbb C++: Add more 'Argument[-1]' to 'ReturnValue' flow. 2024-07-03 17:27:22 +01:00
Mathias Vorreiter Pedersen
246f3fd3e2 C++: Fix 'emplace_after' model in bsl. 2024-07-03 17:21:10 +01:00
Ian Lynagh
ea16f72c6f Java: Add changenote for dropping $SEMMLE_DIST support 2024-07-03 17:12:04 +01:00
Ian Lynagh
3260966e3b Kotlin: Remove unused SEMMLE_DIST 2024-07-03 17:10:41 +01:00
Mathias Vorreiter Pedersen
5351c2734f C++: Fix 'assign' models. 2024-07-03 17:01:43 +01:00
Mathias Vorreiter Pedersen
6d05324724 C++: Make sure the 'emplace' functions that return iterators are modeled via Element content. 2024-07-03 16:47:18 +01:00
Mathias Vorreiter Pedersen
e03f8084e6 C++: Fix yml file name. 2024-07-03 16:04:14 +01:00
Mathias Vorreiter Pedersen
c4dabb94d6 C++: Add models for 'array::front' and 'array::back'. 2024-07-03 16:03:25 +01:00
Porcupiney Hairs
808af28618 Python : Arbitrary codde execution due to Js2Py
Js2Py is a Javascript to Python translation library written in Python. It allows users to invoke JavaScript code directly from Python.
The Js2Py interpreter by default exposes the entire standard library to it's users. This can lead to security issues if a malicious input were directly.

This PR includes a CodeQL query along with a qhelp and testcases to detect cases where an untrusted input flows to an Js2Py eval call.

This query successfully detects CVE-2023-0297 in `pyload/pyload`along with it's fix.
The databases can be downloaded from the links bellow.
```
https://file.io/qrMEjSJJoTq1
https://filetransfer.io/data-package/a02eab7V#link
```
2024-07-03 19:06:34 +05:30
Taus
b779341ba6 Merge pull request #16885 from github/tausbn/python-fix-bad-join-in-function-resolution-type-tracker
Python: Fix bad join in function resolution
2024-07-03 13:59:13 +02:00
Tamas Vajk
6a036f4e84 Improve code quality 2024-07-03 12:45:47 +02:00
Mathias Vorreiter Pedersen
d7eac4d567 C++: Add change note. 2024-07-03 11:33:52 +01:00
Mathias Vorreiter Pedersen
b8c01e2901 C++: Accept test changes. 2024-07-03 11:18:21 +01:00
Mathias Vorreiter Pedersen
5be948533c C++: Replace 'Element[*@]' with 'Element[@]'. 2024-07-03 11:18:13 +01:00
Rasmus Wriedt Larsen
f9536e9a66 Merge pull request #16883 from github/tausbn/python-fix-bad-join-in-import-resolution
Python: Fix bad join in `getImmediateModuleReference`
2024-07-03 11:40:01 +02:00
Tom Hvitved
4ae8720930 SSA: Add BasicBlock.{getNode/1,length/0} to the input signature 2024-07-03 11:32:35 +02:00
Owen Mansel-Chan
dfc59a45c2 Merge pull request #16894 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-03 10:17:16 +01:00
Mathias Vorreiter Pedersen
640c842969 Merge pull request #16892 from MathiasVP/fix-qldoc-on-GuardCondition
C++: Update QLDoc on `GuardCondition`
2024-07-03 09:25:13 +01:00
Mathias Vorreiter Pedersen
284007dbff C++: Fix more QLDoc. 2024-07-03 09:14:06 +01:00
Tamas Vajk
b36db5ad11 C#: Fix glob pattern processing: allow **/ to match empty string 2024-07-03 08:09:34 +02:00
github-actions[bot]
13bb93ea20 Add changed framework coverage reports 2024-07-03 00:17:59 +00:00
Mathias Vorreiter Pedersen
4652003688 C++: Update QLDoc on 'GuardCondition' to reflect the fact that switch statements are supported. 2024-07-02 20:21:54 +01:00
Rasmus Wriedt Larsen
ce177c3450 Merge pull request #15655 from yoff/python/support-model-editor
Python: Support model editor
2024-07-02 16:28:58 +02:00
Tom Hvitved
8e8100fd34 Merge pull request #16887 from hvitved/ruby/local-flow-missing-steps
Ruby: Add missing local flow steps
2024-07-02 15:43:52 +02:00
Mathias Vorreiter Pedersen
6b025db824 C++: Add QLDoc to 'getParameterTypeName'. 2024-07-02 14:26:15 +01:00
Mathias Vorreiter Pedersen
c104a0a74c C++: Expand QLDoc on 'signatureMatches'. 2024-07-02 14:23:04 +01:00
Rasmus Wriedt Larsen
dc33f0de1d Python: Additional tests for model-editor
We currently have some problems with these files, that we should fix
later down the line. See PR comment for more details.
2024-07-02 14:28:46 +02:00
Tom Hvitved
19e910e1b5 Merge pull request #16801 from hvitved/ruby/element-reference-block
Ruby: Handle element references with blocks
2024-07-02 13:08:31 +02:00
Owen Mansel-Chan
c7ad0ad406 Merge pull request #16809 from owen-mc/go/mad-sources-beego
Go: Convert Beego sources to MaD
2024-07-02 09:36:48 +01:00
Michael Nebel
e05f835683 C#: Update model generator expected output. 2024-07-02 07:52:30 +01:00
Michael Nebel
5639ada3ed C#: Do not generate source models for Overriable callables that overrides or implements something. 2024-07-02 07:52:26 +01:00
Michael Nebel
70494d339d C#: Re-write some of the existing source model generation tests and introduce a new one for ToString. 2024-07-02 07:52:22 +01:00
Michael Nebel
a108b9c37d C#: Fix some bugs in the python script for the model generator. 2024-07-02 07:52:18 +01:00
Michael Nebel
25b20186af Merge pull request #16861 from michaelnebel/modelgen/sourcesinklift
C#/Java: Do not lift source and sink models.
2024-07-02 08:50:31 +02:00
Tamás Vajk
b4707abf4c Merge pull request #16871 from tamasvajk/fix/quality-issues
C#: Fix quality issues
2024-07-01 22:23:43 +02:00
Tom Hvitved
7fdc09c17f Ruby: Add missing local flow steps 2024-07-01 19:46:40 +02:00
aegilops
e2b37f97b0 Added dot to end of test message 2024-07-01 17:41:26 +01:00
Paul Hodgkinson
d289fb414e Merge branch 'main' into aegilops/polyfill-io-compromised-script 2024-07-01 17:15:07 +01:00
aegilops
73fc6bcdb1 Added some missing QLDoc 2024-07-01 17:10:24 +01:00
aegilops
b4d8c4889a Fixed wrong name for example HTML 2024-07-01 16:58:03 +01:00
aegilops
c985c9adb3 Added change note for polyfill.io query 2024-07-01 16:56:07 +01:00
aegilops
1744a98017 Added full stop to end of message 2024-07-01 16:53:22 +01:00
aegilops
ceda46e317 Fixed ending <p> tags 2024-07-01 16:52:28 +01:00
Rasmus Wriedt Larsen
2b2c381bf0 Merge pull request #16876 from GeekMasher/py-hardcoded-creds-mad
Python: Add Hardcoded Credentials MaD support
2024-07-01 17:25:13 +02:00
aegilops
a1b0703690 Added detection for specific Polyfill.io CDN compromise - edited existing library and added new query and tests 2024-07-01 16:21:34 +01:00
Owen Mansel-Chan
801edda9b2 Accept MaD edge provenance label changes/additions 2024-07-01 16:13:41 +01:00
Owen Mansel-Chan
247abf95ee Convert BeegoContextSource to MaD 2024-07-01 16:13:40 +01:00
Owen Mansel-Chan
84bb8a400b Convert BeegoInputRequestBodySource to MaD 2024-07-01 16:13:39 +01:00
Owen Mansel-Chan
194491f3fb Convert BeegoControllerSource to MaD 2024-07-01 16:13:38 +01:00
Owen Mansel-Chan
6bc0ffe429 Convert BeegoInputSource to MaD 2024-07-01 16:13:37 +01:00
Owen Mansel-Chan
2bbd9ab4eb Change definition of BeegoInputSafeUrlSource 2024-07-01 16:13:36 +01:00
Owen Mansel-Chan
8d8af320bf Add in missing summary models for Beego 2024-07-01 16:13:34 +01:00
Taus
e5a15f34a4 Python: Fix bad join in function resolution
On a certain database, the evaluator was spending 17 seconds on a single
iteration, which is usually a bad sign.

Looking more closely, we find the following culprit:

```
(621s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#fb44303q after 17.8s:
79429084 ~0%     {3} r1 = JOIN `TypeTrackingImpl::TypeTracker.start/0#dispred#f8047cd1` WITH `DataFlowPublic::Node.asExpr/0#dispred#2845197a` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0 't', Rhs.1
59018875 ~7%     {3}    | JOIN WITH LocalSources::LocalSourceNode#2491029a ON FIRST 1 OUTPUT Lhs.2, Lhs.1 't', Lhs.0 'result'
7929     ~1%     {3}    | JOIN WITH `PoorMansFunctionResolution::lastDecoratorCall/1#152a5a8f_10#join_rhs` ON FIRST 1 OUTPUT Lhs.1 't', Rhs.1 'func', Lhs.2 'result'

277654   ~5%     {3} r2 = JOIN `TypeTrackingImpl::TypeTracker.start/0#dispred#f8047cd1` WITH `Function::Function.getDefinition/0#dispred#6279b12c` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0 't', Rhs.1
                 {3}    | AND NOT `project#Function::Function.getADecorator/0#dispred#119184e3`(FIRST 1)
269725   ~0%     {3}    | SCAN OUTPUT In.2, In.1 't', In.0 'func'
270268   ~0%     {3}    | JOIN WITH `DataFlowPublic::Node.asExpr/0#dispred#2845197a_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1 't', Lhs.2 'func'
270268   ~7%     {3}    | JOIN WITH LocalSources::LocalSourceNode#2491029a ON FIRST 1 OUTPUT Lhs.1 't', Lhs.2 'func', Lhs.0 'result'

278197   ~5%     {3} r3 = r1 UNION r2
                 return r3
```

This is clearly silly. We're creating a type tracker start spot for
_every expression_, and only then filtering them down to just final
decorator calls.

To fix this, I simply pushed the `.asExpr` into `lastDecoratorCall` and
made that `pragma[nomagic]`.

This resulted in a much more reasonable iteration:

```
(585s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#62ade299 after 2.1s:
61252093 ~0%     {2} r1 = JOIN `TypeTrackingImpl::TypeTracker.start/0#dispred#f8047cd1` WITH LocalSources::LocalSourceNode#2491029a CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0 't'
7929     ~3%     {3}    | JOIN WITH `PoorMansFunctionResolution::lastDecoratorCall/1#152a5a8f_10#join_rhs` ON FIRST 1 OUTPUT Lhs.1 't', Rhs.1 'func', Lhs.0 'result'

277654   ~5%     {3} r2 = JOIN `TypeTrackingImpl::TypeTracker.start/0#dispred#f8047cd1` WITH `Function::Function.getDefinition/0#dispred#6279b12c` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0 't', Rhs.1
                 {3}    | AND NOT `project#Function::Function.getADecorator/0#dispred#119184e3`(FIRST 1)
269725   ~0%     {3}    | SCAN OUTPUT In.2, In.1 't', In.0 'func'
270268   ~0%     {3}    | JOIN WITH `DataFlowPublic::Node.asExpr/0#dispred#2845197a_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1 't', Lhs.2 'func'
270268   ~5%     {3}    | JOIN WITH LocalSources::LocalSourceNode#2491029a ON FIRST 1 OUTPUT Lhs.1 't', Lhs.2 'func', Lhs.0 'result'

278197   ~5%     {3} r3 = r1 UNION r2
                 return r3
```

That's better, but can we do better still? Ideally, we'll join with
`lastDecoratorCall` _first_, and only then consider `LocalSourceNode`s.

Time to add some pragmas:

```
(6s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#049abau6 after 51ms:
247936 ~0%     {3} r1 = SCAN TypeTrackingImpl::Cached::MkTypeTracker#ff50e2d8 OUTPUT In.1, In.0, In.2 't'
2      ~0%     {3}    | JOIN WITH `num#Option::Option<TypeTrackingImpl::TypeTrackingInput::Content>::TNone#364b4b8a` ON FIRST 1 OUTPUT Lhs.1, Lhs.2 't', _
               {2}    | REWRITE WITH Tmp.2 := false, TEST InOut.0 = Tmp.2 KEEPING 2
1      ~0%     {1}    | SCAN OUTPUT In.1 't'

7929   ~0%     {3} r2 = JOIN r1 WITH `PoorMansFunctionResolution::lastDecoratorCall/1#152a5a8f` CARTESIAN PRODUCT OUTPUT Rhs.1 'result', Lhs.0 't', Rhs.0
7929   ~3%     {3}    | JOIN WITH LocalSources::LocalSourceNode#2491029a ON FIRST 1 OUTPUT Lhs.1 't', Lhs.2 'func', Lhs.0 'result'

277654 ~5%     {3} r3 = JOIN r1 WITH `Function::Function.getDefinition/0#dispred#6279b12c` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0 't', Rhs.1
               {3}    | AND NOT `project#Function::Function.getADecorator/0#dispred#119184e3`(FIRST 1)
269725 ~0%     {3}    | SCAN OUTPUT In.2, In.1 't', In.0 'func'
270268 ~0%     {3}    | JOIN WITH `DataFlowPublic::Node.asExpr/0#dispred#2845197a#fb_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1 't', Lhs.2 'func'
270268 ~5%     {3}    | JOIN WITH LocalSources::LocalSourceNode#2491029a ON FIRST 1 OUTPUT Lhs.1 't', Lhs.2 'func', Lhs.0 'result'

278197 ~5%     {3} r4 = r2 UNION r3
               return r4
```

Perfect! (Here, the optimiser has for some reason decided to inline
`t.start()`, but this is not important.)

Iteration timings before:

```
(621s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#fb44303q after 17.8s:
(623s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i2#fb44303q after 1.9s:
(628s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i3#fb44303q after 5.2s:
(629s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i4#fb44303q after 696ms:
(629s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i5#fb44303q after 238ms:
(630s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i6#fb44303q after 401ms:
(630s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i7#fb44303q after 6ms:
(630s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i8#fb44303q after 3ms:
(630s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i9#fb44303q after 1ms:
(630s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i10#fb44303q after 525ms:
(631s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb/2@6a2459s7 after 518ms:
(631s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb_10#join_rhs/2@eab64fk2 after 42ms:
```

And after:

```
(585s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#62ade299 after 2.1s:
(585s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i2#62ade299 after 331ms:
(590s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i3#62ade299 after 4.8s:
(592s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i4#62ade299 after 1.9s:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i5#62ade299 after 504ms:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i6#62ade299 after 312ms:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i7#62ade299 after 6ms:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i8#62ade299 after 2ms:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i9#62ade299 after 1ms:
(593s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i10#62ade299 after 489ms:
(594s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb/2@7cac46aj after 522ms:
(594s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb_10#join_rhs/2@a15a372e after 41ms:
```

(Curiously, in the "before" run it appeared to run that tracker _twice_,
with the same performance characteristics the second time around. This
is not present in the "after" version.)

And finally with the pragma:

```
(596s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#7ef50eer after 636ms:
(596s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i2#7ef50eer after 180ms:
(598s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i3#7ef50eer after 1.9s:
(604s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i4#7ef50eer after 6.2s:
(606s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i5#7ef50eer after 1.4s:
(607s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i6#7ef50eer after 1.7s:
(607s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i7#7ef50eer after 55ms:
(607s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i8#7ef50eer after 8ms:
(607s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i9#7ef50eer after 2ms:
(608s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i10#7ef50eer after 619ms:
(609s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb/2@4cb536id after 566ms:
(609s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb_10#join_rhs/2@f0664dnr after 56ms:
(714s) Tuple counts for m#PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb/1@fe47420j after 14ms:
(718s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i1#769227t3 after 369ms:
(719s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i2#769227t3 after 623ms:
(724s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i3#769227t3 after 5.3s:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i4#769227t3 after 2.8s:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i5#769227t3 after 289ms:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i6#769227t3 after 285ms:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i7#769227t3 after 7ms:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i8#769227t3 after 3ms:
(727s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i9#769227t3 after 1ms:
(728s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01/3@i10#769227t3 after 672ms:
(731s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/2#75430e01_201#join_rhs/3@cacd816f after 2.5s:
(732s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb/2@14c0cfsk after 80ms:
(732s) Tuple counts for PoorMansFunctionResolution::poorMansFunctionTracker/1#c7f86fe2#fb_10#join_rhs/2@fc0f040d after 0ms:
```

Note the double evaluation again. This will need to be investigated
further.
2024-07-01 14:04:01 +00:00
Mathew Payne
96048f962e Update python/ql/src/Security/CWE-798/HardcodedCredentials.ql
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-07-01 14:29:00 +01:00
aegilops
fc6fba8d06 Fixed CWE tags 2024-07-01 14:25:47 +01:00
aegilops
d1d082982a More external references 2024-07-01 14:25:29 +01:00
Taus
446dbf67cc Python: Fix bad join in getImmediateModuleReference
The "most expensive predicates" report had the following line on a
certain database:

```
1m15s |    11 |   37s @ 4    | ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0@12bb4xdo
```

Investigating further revealed the following bad joins

```
(388s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i4#b2325xoe after 36.5s:
0         ~0%        {2} r1 = JOIN `ImportResolution::ImportResolution::sys_modules_module_with_name/1#134529bf#prev_delta` WITH `ImportResolution::ImportResolution::getReferenceToModuleName/1#bc5da225` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1 'm'

74884348  ~0%        {3} r2 = JOIN `ImportResolution::ImportResolution::getModuleReference/1#28368ea4#prev_delta` WITH `ImportResolution::ImportResolution::potential_module_export/2#19340171` ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.0
5221604   ~0%        {3}    | JOIN WITH `Attributes::AttrRef.accesses/2#dispred#31929f12_120#join_rhs` ON FIRST 2 OUTPUT Rhs.2 'result', Lhs.2, Lhs.1
5219926   ~2%        {3}    | JOIN WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.0 'result'
5300880   ~1%        {2}    | JOIN WITH `ImportResolution::ImportResolution::module_export/3#f2fc6a2a` ON FIRST 2 OUTPUT Rhs.2, Lhs.2 'result'
42211     ~5%        {2}    | JOIN WITH `ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0#prev` ON FIRST 1 OUTPUT Lhs.1 'result', Rhs.1 'm'

957042    ~4%        {3} r3 = JOIN `ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0#prev_delta` WITH `ImportResolution::ImportResolution::module_export/3#f2fc6a2a_201#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Lhs.1 'm'
957035    ~0%        {3}    | JOIN WITH `ImportResolution::ImportResolution::potential_module_export/2#19340171` ON FIRST 2 OUTPUT Lhs.1, Lhs.2 'm', Lhs.0
236753257 ~1%        {4}    | JOIN WITH `Attributes::AttrRef.accesses/2#dispred#31929f12_201#join_rhs` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1 'm', Lhs.2, Rhs.2
199557145 ~2%        {4}    | JOIN WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT Lhs.2, Lhs.3, Lhs.1 'm', Lhs.0 'result'
1         ~0%        {2}    | JOIN WITH `ImportResolution::ImportResolution::getModuleReference/1#28368ea4#prev` ON FIRST 2 OUTPUT Lhs.3 'result', Lhs.2 'm'

15199013  ~1951%     {2} r4 = JOIN `ImportResolution::ImportResolution::getModuleReference/1#28368ea4#prev_delta` WITH `Module::Module.getPackageName/0#dispred#bb0c3872` ON FIRST 1 OUTPUT Lhs.1, Rhs.1
14707604  ~2136%     {3}    | JOIN WITH `Attributes::AttrRef.accesses/2#dispred#31929f12_102#join_rhs` ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1, Rhs.2

14623588  ~2190%     {4} r5 = JOIN r4 WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT _, Lhs.0 'result', Lhs.1, Lhs.2
14623588  ~2058%     {2}    | REWRITE WITH Tmp.0 := ".", Out.0 := (In.2 ++ Tmp.0 ++ In.3) KEEPING 2

14623588  ~2139%     {5} r6 = JOIN r4 WITH Attributes::AttrRead#class#f6c3f431 ON FIRST 1 OUTPUT _, Lhs.0 'result', Lhs.1, Lhs.2, _
14623588  ~2092%     {2}    | REWRITE WITH Tmp.0 := ".", Tmp.0 := (In.2 ++ Tmp.0 ++ In.3), Tmp.4 := ".__init__", Out.0 := (Tmp.0 ++ Tmp.4) KEEPING 2

29247176  ~2099%     {2} r7 = r5 UNION r6
199786001 ~6922%     {2}    | JOIN WITH `Module::isPreferredModuleForName/2#5fb427f9_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'result'
199756923 ~7024%     {2}    | JOIN WITH `Module::Module.getFile/0#dispred#53eb9b1b_10#join_rhs` ON FIRST 1 OUTPUT Lhs.1 'result', Rhs.1 'm'

199799135 ~6954%     {2} r8 = r1 UNION r2 UNION r3 UNION r7
199793992 ~6954%     {2}    | AND NOT `ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0#prev`(FIRST 2)
                     return r8
```

Clearly, waiting to joining with `getModuleReference` last is not
healthy. To fix this, I opted to simply create a helper predicate for
the `accesses` construct.

After this change, here are the iteration timings

```
(327s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i1#74f41yqa after 1.2s:
(327s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i1#8a053ys7 after 1.3s:
(327s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i2#74f41yqa after 20ms:
(327s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i2#8a053ys7 after 20ms:
(337s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i4#74f41yqa after 8.5s:
(341s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i4#8a053ys7 after 3.2s:
(346s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i5#74f41yqa after 7.2s:
(349s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i6#74f41yqa after 3ms:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i5#8a053ys7 after 10s:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i8#74f41yqa after 37ms:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i9#74f41yqa after 0ms:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i10#74f41yqa after 0ms:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i11#74f41yqa after 1ms:
(352s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i12#74f41yqa after 1ms:
(353s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i6#8a053ys7 after 1ms:
(354s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i8#8a053ys7 after 7ms:
(354s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i9#8a053ys7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i10#8a053ys7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i11#8a053ys7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::getImmediateModuleReference/1#3553e6c0#reorder_1_0/2@i12#8a053ys7 after 0ms:
```

And the helper predicate itself is also quick to evaluate:

```
(327s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i1#74f41xqa after 0ms:
(327s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i1#8a053xs7 after 0ms:
(329s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i3#74f41xqa after 99ms:
(337s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i3#8a053xs7 after 98ms:
(338s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i4#74f41xqa after 679ms:
(341s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i4#8a053xs7 after 400ms:
(346s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i5#74f41xqa after 1ms:
(349s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i6#74f41xqa after 22ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i5#8a053xs7 after 1ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i7#74f41xqa after 1.4s:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i8#74f41xqa after 8ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i9#74f41xqa after 0ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i10#74f41xqa after 1ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i11#74f41xqa after 1ms:
(352s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i12#74f41xqa after 1ms:
(353s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i13#74f41xqa after 806ms:
(353s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i6#8a053xs7 after 7ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i7#8a053xs7 after 870ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i8#8a053xs7 after 2ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i9#8a053xs7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i10#8a053xs7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i11#8a053xs7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i12#8a053xs7 after 0ms:
(354s) Tuple counts for ImportResolution::ImportResolution::module_reference_accesses/3#8f45b418#reorder_1_2_0/3@i13#8a053xs7 after 276ms:
```

(I note that we appear to be evaluating this code twice, which is a bit
worrying. I'll leave that investigaton for later.)
2024-07-01 12:53:04 +00:00
Taus
d9b337cb2c Merge pull request #16804 from github/tausbn/python-fix-bad-join-in-dataflow-dispatch
Python: Fix bad join in `DataFlowDispatch`
2024-07-01 13:14:28 +02:00
Joe Farebrother
b81d41ba7b Add django header write models for direct subscript write 2024-07-01 11:26:54 +01:00
Mathias Vorreiter Pedersen
0b4459db75 C++: Add more QLDoc. 2024-07-01 10:13:32 +01:00
Arthur Baars
c6d02e4909 Merge pull request #16878 from github/aibaars/merge-3.14
Merge rc/3.14 into main
2024-07-01 11:04:57 +02:00
Tom Hvitved
c5c97aca50 C#: Move implicit entry definitions inside method bodies in SSA construction 2024-07-01 10:48:13 +02:00
Owen Mansel-Chan
0db4110449 Merge pull request #16879 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-06-30 13:59:16 +01:00
github-actions[bot]
26194eb65f Add changed framework coverage reports 2024-06-30 00:19:16 +00:00
Owen Mansel-Chan
60b9d19d72 Add explicit relation between "reverse-dns" and "all" 2024-06-29 21:29:21 +01:00
Owen Mansel-Chan
390fecbef6 Merge pull request #16866 from owen-mc/go/add-go-jose-to-library-coverage-frameworks
Go: Add Go JOSE to library coverage frameworks
2024-06-29 07:30:36 +01:00
Arthur Baars
b12b33c8f9 Merge remote-tracking branch 'upstream/main' into 'rc/3.14' 2024-06-28 19:50:35 +02:00
Jeroen Ketema
a85f73972c Merge pull request #16870 from jketema/preproc-more
C++: Update test expectations
2024-06-28 19:01:12 +02:00
Mathew Payne
ed314b1799 docs: Add Change Notes 2024-06-28 14:42:35 +01:00
Mathew Payne
1cf9714272 feat(python): Add Hardcoded Credentials MaD support 2024-06-28 14:30:36 +01:00
Tom Hvitved
075a249f3b C#: Add SSA test for multi-bodied method 2024-06-28 14:27:51 +02:00
Jami
42925b56e3 Merge pull request #15921 from jcogs33/jcogs33/unsafe-url-forward-promotion-resource-and-file-methods
Java: add models for some resource-related methods
2024-06-28 08:05:50 -04:00
Erik Krogh Kristensen
60811116ab Merge pull request #16332 from erik-krogh/ts55
JS: upgrade TypeScript to 5.5
2024-06-28 13:59:52 +02:00
Tamas Vajk
199a9688af C#: Fix quality issues 2024-06-28 13:58:08 +02:00
Tamás Vajk
1cf5e89b96 Merge pull request #16747 from tamasvajk/buildless/binary-log-extractor-2
C#: Add binlog support to buildless with source generator support
2024-06-28 12:39:54 +02:00
Erik Krogh Kristensen
fd3089ee5a Merge pull request #14342 from maikypedia/maikypedia/javascript-cors
JS: Add Permissive CORS query (CWE-942)
2024-06-28 11:27:37 +02:00
Mathias Vorreiter Pedersen
72caadb7db Merge pull request #16869 from hvitved/shared/cfg/mermaid-output
Shared: Generate mermaid output in `View CFG` query
2024-06-28 10:21:02 +01:00
Tom Hvitved
e1c1314824 Shared: Generate mermaid output in View CFG query 2024-06-28 09:45:22 +02:00
Tamas Vajk
4db586f17d Add TSP diagnostic for binlog usage 2024-06-28 09:40:41 +02:00
Tamas Vajk
c8927447f5 Record diagnostics in binlog extraction test 2024-06-28 09:40:13 +02:00
Jami Cogswell
85a1e1a972 Java: update change note date 2024-06-27 22:11:01 -04:00
Jami Cogswell
be565288f2 Java: update more test cases due to shifted alert provenance line numbers 2024-06-27 22:08:38 -04:00
Jami Cogswell
c73af7f789 Java: update some test cases due to shifted alert provenance line numbers 2024-06-27 21:07:35 -04:00
Mathias Vorreiter Pedersen
4535043e90 C++: Accept test changes. 2024-06-27 20:15:58 +01:00
Mathias Vorreiter Pedersen
2ad8704325 C++: Add bsl models. 2024-06-27 19:48:27 +01:00
Maiky
d0cf2a978c Merge branch 'main' into maikypedia/javascript-cors 2024-06-27 20:24:42 +02:00
Jeroen Ketema
8defd27b49 C++: Update test expectations 2024-06-27 17:45:33 +02:00
yoff
40b7534210 Merge pull request #16860 from yoff/python/MaD-doc-fixup
Python: fix typo pointed out in review but missed by me
2024-06-27 17:02:39 +02:00
Rasmus Lerchedahl Petersen
6bc830dca4 Python: add qldoc 2024-06-27 16:55:29 +02:00
Rasmus Lerchedahl Petersen
9cca1b294c Python: Add test cases 2024-06-27 16:33:23 +02:00
Rasmus Lerchedahl Petersen
27301edc28 Python: address more review comments 2024-06-27 16:05:21 +02:00
Owen Mansel-Chan
98b2d1f2d7 Add Go JOSE to library coverage frameworks 2024-06-27 14:52:08 +01:00
Owen Mansel-Chan
5d7a6e3836 Merge pull request #16851 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-06-27 13:57:30 +01:00
yoff
c2141b62e0 Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2024-06-27 14:53:03 +02:00
Tamas Vajk
1e2d1ef715 Use dedicated API to get generated syntax trees 2024-06-27 14:49:29 +02:00
Tamas Vajk
0b41d5121a Compute unique identifier (folder path) for each compilation 2024-06-27 14:49:24 +02:00
Tamas Vajk
1ae40c95b1 Change binlog test to have colliding generated file locations 2024-06-27 14:49:20 +02:00
Tamas Vajk
b22f5f557a Fix failed extraction handling 2024-06-27 14:49:16 +02:00
Tamas Vajk
fb0520c74a C#: Adjust trap location, database ID and archiving of generated sources 2024-06-27 14:49:10 +02:00
Tamas Vajk
dcd84f47a4 Improve source archiving to handle non-existent files 2024-06-27 14:49:06 +02:00
Tamas Vajk
31ad195dc3 C#: Add binlog support to buildless with source generator support 2024-06-27 14:48:54 +02:00
Tamás Vajk
b2d2f2d0d8 Merge pull request #16858 from tamasvajk/fix/solution
C#: Fix solution file
2024-06-27 14:31:15 +02:00
Owen Mansel-Chan
50cc720117 Merge branch 'main' into workflow/coverage/update 2024-06-27 10:51:23 +01:00
Michael Nebel
9cb7018215 Java: Update the model generator expected test output. 2024-06-27 11:35:07 +02:00
Michael Nebel
e23ff3e499 Java: Sync files and make language specific implementation. 2024-06-27 11:27:08 +02:00
Rasmus Lerchedahl Petersen
da03237b32 Python: fix typo pointed out in review but missed by me 2024-06-27 11:21:28 +02:00
Michael Nebel
22e9ae2793 Java: Add some source/sink examples where lifting is applied. 2024-06-27 11:15:06 +02:00
Chris Smowton
5cee3927f0 Suspend compile checking of new query until a compatible CLI is released 2024-06-27 09:57:45 +01:00
Chris Smowton
27e2b00cd7 Add test for database quality diagnostic 2024-06-27 09:57:40 +01:00
Chris Smowton
80cb908289 Amend message 2024-06-27 09:57:35 +01:00
Chris Smowton
567ba9f9c3 Change note 2024-06-27 09:57:30 +01:00
Chris Smowton
df860d4128 autoformat 2024-06-27 09:57:25 +01:00
Chris Smowton
16a90aa180 autoformat 2024-06-27 09:57:19 +01:00
Chris Smowton
6292cacd74 Add link to build modes docs 2024-06-27 09:57:13 +01:00
Chris Smowton
d43762cae3 Apply suggestions from code review
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
Co-authored-by: Chad Bentz <1760475+felickz@users.noreply.github.com>
2024-06-27 09:57:07 +01:00
Chris Smowton
f397ab2d72 Java: add diagnostic query indicating low database quality 2024-06-27 09:57:02 +01:00
Tamás Vajk
6c727b1e7d Merge pull request #16857 from tamasvajk/feature/stringformat
C#: Change `string.Format` calls to interpolated strings
2024-06-27 10:55:21 +02:00
Tamas Vajk
3e20d908c4 C#: Fix solution file 2024-06-27 10:53:39 +02:00
Chris Smowton
c5678ad156 Merge pull request #16847 from smowton/smowton/admin/java-diagnostic-test-expectations
Java: Adjust test expectations for Java diagnostic severity changes
2024-06-27 09:53:25 +01:00
Michael Nebel
f7ce4f39ea C#: Update expected source/sink model generator expected test output. 2024-06-27 10:42:37 +02:00
Michael Nebel
3180d8f752 C#: Add some source/sink examples where lifting is applied. 2024-06-27 10:27:50 +02:00
Michael Nebel
64ac52e918 C#: Only lift summary models in the model generator. 2024-06-27 09:54:00 +02:00
Tamas Vajk
0c34b4535a C#: Change string.Format calls to interpolated strings 2024-06-27 09:20:50 +02:00
Tamás Vajk
4a98436884 Merge pull request #16855 from tamasvajk/fix/integration-test
C#: Fix integration test expected file
2024-06-27 08:52:05 +02:00
Tamas Vajk
6b6d705b4f C#: Fix integration test expected file 2024-06-27 08:14:37 +02:00
Jami
901245ae3d Merge branch 'main' into jcogs33/unsafe-url-forward-promotion-resource-and-file-methods 2024-06-26 21:57:07 -04:00
github-actions[bot]
0a8c9da0ac Add changed framework coverage reports 2024-06-27 00:17:25 +00:00
Chris Smowton
f2cbf08d15 Adjust test expectations 2024-06-26 17:37:48 +01:00
Mathias Vorreiter Pedersen
e845204ec9 C++: Add tests of internal MaD predicates and accept test changes. 2024-06-26 14:10:31 +01:00
Mathias Vorreiter Pedersen
d38ce61e03 C++: Mention in the QLDoc that you cannot instantiate templates in the signature string. 2024-06-26 13:54:28 +01:00
Owen Mansel-Chan
272132a09a Merge pull request #16799 from owen-mc/go/mad/match-all-package-versions
Go: Make models-as-data package column match any version without "$ANYVERSION"
2024-06-26 13:46:49 +01:00
Anders Schack-Mulligen
9d8ee99c1c Merge pull request #16806 from aschackmull/dataflow/debug-stages
Dataflow: Add path-problem view of intermediate stages for debug purposes.
2024-06-26 12:53:12 +02:00
Michael Nebel
e1f65d1f8b Merge pull request #16836 from michaelnebel/csharp/bestlocation
C#: Be more consistent when picking between locations.
2024-06-26 12:46:50 +02:00
aegilops
f22778960b Fixed expected test results for Helmet query 2024-06-26 11:31:57 +01:00
Cornelius Riemenschneider
c4cc30fb7a Merge pull request #16839 from github/criemen/bazel-721
Bump to bazel 7.2.1.
2024-06-26 11:26:19 +02:00
Paolo Tranquilli
53a7d823ec Merge pull request #16841 from github/redsun82/kotlin
Kotlin: exclude `KotlinExtractorDbScheme.kt` generated by hand
2024-06-26 11:18:44 +02:00
Tamás Vajk
81f4786643 Merge pull request #16832 from tamasvajk/feature/update-dependencies
C#: Update (some) nuget dependencies
2024-06-26 11:12:26 +02:00
Michael Nebel
e258d9fa74 C#: Use the first best location from the list of locations. 2024-06-26 11:04:38 +02:00
Joe Farebrother
6538d22d3f Fix tornado model of httheaders.add. 2024-06-26 09:21:53 +01:00
Paolo Tranquilli
a52a412c24 Kotlin: exclude KotlinExtractorDbScheme.kt generated by hand 2024-06-26 09:05:09 +02:00
Owen Mansel-Chan
a30b34c4bd Used "fixed-version:" prefix in a test 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
418a56d385 Replace "$THISVERSION" suffix with "fixed-version:" prefix 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
081f32141c Accept review suggestion fixing a comment
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
d4e8e4c943 Add QLDoc for majorVersionSuffixRegex 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
46d0c6ff9c Use lookahead in regex to not match e.g. "/v2foo" 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
c8a3bedf44 Move major version suffix regex into one place 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
cb2ccef5fa Refactor suffix check 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
c045e77d61 Fix QLDoc for interpretPackage 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
7d11fc2c7d Fix bug in regex
I accidentally included a `$` at the end, so it only matched a major
version suffix at the end of the package path.
2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
a9afbfa993 Document version matching and "$THISVERSION" 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
3e2bbd38d4 Remove "$ANYVERSION" from models 2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
47d946fb1c Make MaD package match any version without $ANYVERSION
Note that if the package column contains major version suffix (like
"/v2") or if it ends with "$THISVERSION" (which is removed) then we
don't do any version matching.
2024-06-26 05:01:09 +01:00
Owen Mansel-Chan
ea0db4d55e Add predicate for package path without "/v2" etc 2024-06-26 05:01:09 +01:00
Ian Lynagh
f9ae44ca5c Merge pull request #16736 from igfoo/igfoo/debugLoC
Java/Kotlin: Tag the LoC queries 'debug'
2024-06-25 22:57:36 +01:00
Cornelius Riemenschneider
37da3e1bb3 Bump to bazel 7.2.1. 2024-06-25 21:21:39 +02:00
Chris Smowton
2413332553 Merge pull request #16802 from github/smowton/admin/note-java-system-requirements
Java: document extraction system requirements
2024-06-25 15:53:09 +01:00
Ian Lynagh
c12adbeeaa Java/Kotlin: Tag the LoC queries 'debug'
This brings them into line with LinesOfCode.ql
2024-06-25 15:46:10 +01:00
Michael Nebel
d18915a1e4 C#: Update expected test output. 2024-06-25 16:02:58 +02:00
Michael Nebel
e15a47d58c C#: Update the extractor to use the BestOrDefault extension method to choose between multiple locations. 2024-06-25 16:02:54 +02:00
Michael Nebel
dd65d960be C#: Introduce a Location extension method to help pick a unique location. 2024-06-25 16:02:49 +02:00
Michael Nebel
8dc95ce9b0 Merge pull request #16722 from michaelnebel/csharp/modelgensourcesink
C#/Java: Respect manual neutrals, sources and sinks in model generation.
2024-06-25 15:55:06 +02:00
yoff
58b6b3f601 Merge pull request #16789 from yoff/python/document-models-as-data
python: Document MaD format
2024-06-25 15:46:28 +02:00
Arthur Baars
306e481c5d Merge pull request #16830 from github/post-release-prep/codeql-cli-2.17.6
Post-release preparation for codeql-cli-2.17.6
2024-06-25 15:26:05 +02:00
Tamas Vajk
5058727980 C#: Update (some) nuget dependencies 2024-06-25 15:24:08 +02:00
Anders Schack-Mulligen
1cc49af454 Dataflow: Address review comments. 2024-06-25 15:19:55 +02:00
Asger F
6a3bb4dd28 Merge pull request #16834 from asgerf/shared/capture-this-location
Shared: add location for 'this' CaptureContainer
2024-06-25 13:18:41 +02:00
Mathias Vorreiter Pedersen
17edfdf801 Merge pull request #16833 from MathiasVP/simplify-incorrect-allocation-error-handling
C++: Simplify `cpp/incorrect-allocation-error-handling`
2024-06-25 12:16:21 +01:00
Rasmus Lerchedahl Petersen
6524b8e25d Python: consistent double quotes in examples 2024-06-25 12:11:52 +02:00
Rasmus Lerchedahl Petersen
09905ee228 Python: double back-tics 2024-06-25 12:05:38 +02:00
Rasmus Lerchedahl Petersen
6d4e993dea Python: remove named parameter filename 2024-06-25 12:00:53 +02:00
Rasmus Lerchedahl Petersen
aa4fd1992e Python: compact types in type models 2024-06-25 11:59:55 +02:00
Rasmus Lerchedahl Petersen
b902dd5680 Python: add change note 2024-06-25 11:54:30 +02:00
Arthur Baars
046a5f0881 Merge branch 'rc/3.14' into post-release-prep/codeql-cli-2.17.6 2024-06-25 11:43:38 +02:00
Arthur Baars
624c574559 Merge pull request #16831 from smowton/smowton/admin/backport-maven-regex-fix
Backport Maven regex fix to rc/3.14
2024-06-25 11:42:54 +02:00
Jeroen Ketema
e0e5bdec8a Merge pull request #16818 from jketema/predef
C++: Update expected test results
2024-06-25 11:06:53 +02:00
Mathias Vorreiter Pedersen
921afb71e2 Update cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2024-06-25 10:03:53 +01:00
Owen Mansel-Chan
890da5377e Merge pull request #16819 from owen-mc/go/remove-dataflowtype-optimizer-bug-workaround
Go: Make DataFlowType a singleton (remove workaround)
2024-06-25 10:03:08 +01:00
Asger F
551743e000 Shared: add location for 'this' CaptureContainer
Only has an effect for debugging purposes
2024-06-25 10:34:28 +02:00
Mathias Vorreiter Pedersen
982f845be7 C++: Accept test changes. 2024-06-25 09:31:00 +01:00
Mathias Vorreiter Pedersen
bb8b0d0bf5 C++: Use the unary version of 'comparesEq' to handle both disjuncts. 2024-06-25 09:30:53 +01:00
Chris Smowton
5608e0141c Adjust and tolerate variability in test expectations 2024-06-25 09:02:58 +01:00
Tom Hvitved
25daaf9d47 Ruby: Add change note 2024-06-25 10:00:01 +02:00
Jeroen Ketema
285ed3630b C++: Update expected test results 2024-06-25 09:16:05 +02:00
github-actions[bot]
fd385736e6 Post-release preparation for codeql-cli-2.17.6 2024-06-25 06:39:45 +00:00
Joe Farebrother
0901b3d0a6 Add change note 2024-06-24 21:43:09 +01:00
Owen Mansel-Chan
8458bde51e Add comment that "reverse-dns" is an ungrouped threat model 2024-06-24 21:23:52 +01:00
Owen Mansel-Chan
9e25279cb8 Change category in change note to "majorAnalysis" 2024-06-24 21:23:51 +01:00
Owen Mansel-Chan
162245fb9a Fix unrelated test using reverse DNS as source 2024-06-24 21:23:50 +01:00
Owen Mansel-Chan
059ef42f41 Add change note 2024-06-24 21:23:49 +01:00
Owen Mansel-Chan
878867205e Fix taintsources test 2024-06-24 21:23:47 +01:00
Owen Mansel-Chan
91db2b6c9c Make new threat model kind "reverse-dns" 2024-06-24 21:23:46 +01:00
Joe Farebrother
d0f735ac28 Update tests for restframework 2024-06-24 20:52:09 +01:00
Arthur Baars
0508d4fa33 Merge pull request #16821 from github/release-prep/2.17.6
Release preparation for version 2.17.6
2024-06-24 21:17:34 +02:00
Dave Bartolomeo
1e46e431e8 Merge pull request #16823 from smowton/smowton/admin/maven-transfer-failure-test-expectations
Java: Adjust and tolerate variability in test expectations
2024-06-24 13:54:25 -04:00
Joe Farebrother
c404f00a9b Add additional header write models for aiohttp and tornado + added qldoc 2024-06-24 17:27:25 +01:00
Joe Farebrother
79c0ed6074 Add additional fastapi mheader write models 2024-06-24 17:27:21 +01:00
Joe Farebrother
5ced5c010c Add django header writes 2024-06-24 17:27:15 +01:00
Joe Farebrother
7704801e47 Change fastapi raw cookie header models to header write models 2024-06-24 17:27:12 +01:00
Joe Farebrother
a0201e9c4f Update tests for new cookie write from headers 2024-06-24 17:27:06 +01:00
Joe Farebrother
6b8080a5b3 Update concept tests for header writes 2024-06-24 17:27:02 +01:00
Joe Farebrother
d11f58f768 Add cookie header write concept from experimental. 2024-06-24 17:26:56 +01:00
Joe Farebrother
b71ba7c30f Move Header Write derrived concepts to Concepts 2024-06-24 17:26:51 +01:00
Paolo Tranquilli
d2a00fa773 Merge pull request #16822 from github/redsun82/nodejs-mirror
Bazel: add `nodejs` mirror
2024-06-24 17:59:08 +02:00
Chris Smowton
351b908f62 Adjust and tolerate variability in test expectations 2024-06-24 16:38:18 +01:00
Paolo Tranquilli
0669186713 Bazel: remove unneeded upstream rules_nodejs patch 2024-06-24 17:09:40 +02:00
Paolo Tranquilli
a02cf07833 Bazel: add nodejs mirror
This patches `rules_nodejs` with the contents of
https://github.com/bazelbuild/rules_nodejs/pull/3763
in order to allow specifying a mirror for nodejs, as nodejs.org has
hit us with intermittent downtimes.
2024-06-24 16:59:25 +02:00
Mathias Vorreiter Pedersen
5b1b60cc92 Merge pull request #16797 from MathiasVP/yml-for-allocation-and-deallocation
C++: Add extensible predicates to `Allocation` and `Deallocation`
2024-06-24 15:34:27 +01:00
github-actions[bot]
e32a587078 Release preparation for version 2.17.6 2024-06-24 14:33:10 +00:00
Anders Schack-Mulligen
25d520a7f1 Merge pull request #16785 from aschackmull/dataflow/stage3-notypes
Dataflow: Replace stage 3 type pruning with flow-insensitive type pruning.
2024-06-24 15:21:37 +02:00
Mathias Vorreiter Pedersen
36d59cef7e C++: Add 'bsl::free' as a deallocation function model. 2024-06-24 13:56:44 +01:00
Mathias Vorreiter Pedersen
82ed1ee671 Update cpp/ql/lib/change-notes/2024-06-20-extensible-allocation-deallocation.md
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2024-06-24 13:50:24 +01:00
Owen Mansel-Chan
d8df38c683 Make DataFlowType a singleton (remove workaround) 2024-06-24 13:43:10 +01:00
Mathias Vorreiter Pedersen
19b6d24bc2 Merge pull request #16816 from MathiasVP/fix-valuenumber-imports
C++: Fix value numbering imports
2024-06-24 13:37:38 +01:00
Anders Schack-Mulligen
fdf6e30888 Dataflow: Handle non-trivial type systems with stores into a top type. 2024-06-24 13:35:50 +02:00
Anders Schack-Mulligen
a26132e818 Dataflow: Replace stage 3 type pruning with flow-insensitive type pruning. 2024-06-24 13:35:50 +02:00
Anders Schack-Mulligen
3ede3af6f2 C#: Fix join-order. 2024-06-24 13:35:49 +02:00
Anders Schack-Mulligen
8c23e21073 Dataflow: Cache compatibleTypes. 2024-06-24 13:35:48 +02:00
Anders Schack-Mulligen
06a7e3f3ee Dataflow: Cache typeStrongerThan. 2024-06-24 13:35:48 +02:00
Anders Schack-Mulligen
bd99f32a4b Dataflow: Check types on ParamReturnNode. 2024-06-24 13:35:47 +02:00
Michael Nebel
24685a07c0 Java: Update model generator test expected output. 2024-06-24 13:07:42 +02:00
Michael Nebel
c687dcb094 Java: Sync files and make language specific implementation. 2024-06-24 13:07:39 +02:00
Michael Nebel
30249e4f2b Java: Add some spurious source and sink examples. 2024-06-24 13:07:34 +02:00
Michael Nebel
854674a71c C#: Update expected test output. 2024-06-24 13:07:30 +02:00
Michael Nebel
b27a9d948a C#: Exclude APIs with a manual source neutral from source model generation and allow source generation for all source kinds. 2024-06-24 13:07:14 +02:00
Michael Nebel
2657e7f56d C#: Add some source and sink modelling examples where a neutral exist. 2024-06-24 13:05:35 +02:00
Mathias Vorreiter Pedersen
00d772f980 C++: Fix value numbering imports. 2024-06-24 11:53:24 +01:00
Michael Nebel
abc7cc39d4 Merge pull request #16775 from michaelnebel/modelgen/refactorprinting
C#/Java: Parameterized module for model printing.
2024-06-24 12:51:07 +02:00
Michael Nebel
9cd16fd9d6 Java: Base the model printing on the shared implementation. 2024-06-24 11:52:50 +02:00
Michael Nebel
8630583856 C#/Java: Exclude the model printing implementation form sync files. 2024-06-24 11:50:57 +02:00
Michael Nebel
b7bc540325 C#: Adjust implementation to use the shared model printer. 2024-06-24 11:50:46 +02:00
Michael Nebel
65e150b416 Add parameterized module for MaD model printing. 2024-06-24 11:48:33 +02:00
Owen Mansel-Chan
f04a85e121 Merge pull request #16753 from owen-mc/go/misc-clean-up
Go: a few small clean ups
2024-06-24 10:47:21 +01:00
Michael Nebel
94d12edfdb Merge pull request #16759 from michaelnebel/modelgen/sourcesinkmodelgen
C#/Java: Introduce source and sink model generation sanitisers.
2024-06-24 11:47:11 +02:00
Rasmus Lerchedahl Petersen
4626e134fa Python: update doc to use operations module 2024-06-24 10:56:34 +02:00
Rasmus Lerchedahl Petersen
00fbada41d Python: recognize fabric.operations 2024-06-24 10:54:59 +02:00
Rasmus Lerchedahl Petersen
21a0f8af07 Python: address reviewer comments
- fix wording on `builtins`
- add named argument/parameter access path components
2024-06-24 10:48:53 +02:00
yoff
d603b48884 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2024-06-24 10:29:33 +02:00
Mathias Vorreiter Pedersen
a1743aa12e Merge pull request #16805 from MathiasVP/tc-in-temp-materialization
C++: Fix missing `asExpr` for temporary materializations with conversions
2024-06-23 13:38:01 +01:00
Owen Mansel-Chan
513ec16691 Merge pull request #16796 from owen-mc/go/fix/package-vendor
Go: Fix bug removing "vendor/" from package paths
2024-06-22 07:54:18 +01:00
Mathias Vorreiter Pedersen
9a2c7d34af C++: Simplify 'parseParens'. 2024-06-21 15:45:43 +01:00
Mathias Vorreiter Pedersen
2e74ae448c C++: Accept more test changes. 2024-06-21 14:04:08 +01:00
Mathias Vorreiter Pedersen
40fb59dc0b C++: Add gnu iterator models to regain TP. 2024-06-21 14:04:07 +01:00
Mathias Vorreiter Pedersen
c8f3c1a798 C++: Accept test changes. Nothing exciting to see here. 2024-06-21 14:04:06 +01:00
Mathias Vorreiter Pedersen
f507b51170 C++: Fix Code Scanning errors. 2024-06-21 14:04:05 +01:00
Mathias Vorreiter Pedersen
3e9862391b C++: No need for 'decodeUnknownContent' if we specify the MaD summary rows correctly. This avoids a bad join in a compiler-generated predicate. 2024-06-21 14:04:03 +01:00
Mathias Vorreiter Pedersen
6513c33d26 C++: Accept test changes. 2024-06-21 14:04:02 +01:00
Mathias Vorreiter Pedersen
1bb762bea9 C++: Accept test changes. 2024-06-21 13:35:10 +01:00
Mathias Vorreiter Pedersen
7d41e8ef73 C++: Perform a TC to skip conversions when special-casing materialization of temporaries. 2024-06-21 13:35:09 +01:00
Mathias Vorreiter Pedersen
3b585b4196 C++: Add test with missing flow. 2024-06-21 13:35:08 +01:00
Taus
4a448f445e Merge pull request #15715 from am0o0/am0o0-python-codeExec
Python: New command execution sinks
2024-06-21 14:26:33 +02:00
Anders Schack-Mulligen
accc73d1d0 Dataflow: Add debug graph for pruning stages. 2024-06-21 14:25:32 +02:00
Erik Krogh Kristensen
49f74bacf2 Merge pull request #16729 from mbaluda/main
JS: Extract SAP XSJS file types as Javascript
2024-06-21 14:23:55 +02:00
Taus
6db7e72fb8 Python: Fix bad join in DataFlowDispatch
A case of bad magic. Rather than evaluating separately whether a class
has a method of some name, the compiler opted to magick in the fact
that this was done as part of the `findFunctionAccordingToMro`
predicate. Hilarity ensued.

However, _we_ know that magic really isn't needed in this case (the
number of results is bounded by `Class.getAMethod` since methods have
only a single name), so by factoring it out into a helper predicate, we
can help the join-orderer along.

Before
```
(377s) Starting to evaluate predicate _DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev_DataFlowDispatch::getNextClassInMro/1#__#shared/3@i6#L3#f893bw2h (iteration 6)
(377s) Tuple counts for _DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev_DataFlowDispatch::getNextClassInMro/1#__#shared/3@i6#L3#f893bw2h after 16ms:
33363  ~0%     {2} r1 = SCAN `DataFlowDispatch::getNextClassInMro/1#e1ee596a#prev_delta` OUTPUT In.1, In.0 'arg1'
159696 ~4%     {3}    | JOIN WITH `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev` ON FIRST 1 OUTPUT Rhs.1 'arg0', Lhs.1 'arg1', Rhs.2 'arg2'
               return r1
(377s) Starting to evaluate predicate _Class::Class.getAMethod/0#dispred#66416e47_Function::Function.getName/0#dispred#033700ef_10#join_rh__#antijoin_rhs/3@i6#L4#f893bw2h (iteration 6)
(382s) Tuple counts for _Class::Class.getAMethod/0#dispred#66416e47_Function::Function.getName/0#dispred#033700ef_10#join_rh__#antijoin_rhs/3@i6#L4#f893bw2h after 4.4s:
1770825904 ~4%     {4} r1 = JOIN `_DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev_DataFlowDispatch::getNextClassInMro/1#__#shared` WITH `Function::Function.getName/0#dispred#033700ef_10#join_rhs` ON FIRST 1 OUTPUT Lhs.1 'arg0', Rhs.1, Lhs.0 'arg1', Lhs.2 'arg2'
34558      ~3%     {3}    | JOIN WITH `Class::Class.getAMethod/0#dispred#66416e47` ON FIRST 2 OUTPUT Lhs.0 'arg0', Lhs.2 'arg1', Lhs.3 'arg2'
                   return r1
...
(382s) Starting to evaluate predicate DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3/3@i6#f893b1xh (iteration 6)
(382s)                     - DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3_delta has 125138 rows (order for disjuncts: delta=<standard>).
(382s) Tuple counts for DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3/3@i6#f893b1xh after 12ms:
33363  ~0%     {2} r1 = SCAN `DataFlowDispatch::getNextClassInMro/1#e1ee596a#prev_delta` OUTPUT In.1, In.0 'cls'
159696 ~0%     {3}    | JOIN WITH `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev` ON FIRST 1 OUTPUT Lhs.1 'cls', Rhs.1 'name', Rhs.2 'result'
125138 ~1%     {3}    | AND NOT `_Class::Class.getAMethod/0#dispred#66416e47_Function::Function.getName/0#dispred#033700ef_10#join_rh__#antijoin_rhs`(FIRST 3)

0      ~0%     {3} r2 = JOIN `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev_delta` WITH `DataFlowDispatch::getNextClassInMro/1#e1ee596a#reorder_1_0#prev` ON FIRST 1 OUTPUT Lhs.1 'name', Lhs.2 'result', Rhs.1 'cls'
               {3}    | AND NOT `_Class::Class.getAMethod/0#dispred#66416e47_DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#__#antijoin_rhs`(FIRST 3)
0      ~0%     {3}    | SCAN OUTPUT In.2 'cls', In.0 'name', In.1 'result'

125138 ~1%     {3} r3 = r1 UNION r2
125138 ~1%     {3}    | AND NOT `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev`(FIRST 3)
               return r3
```

And now
```
(18s) Tuple counts for DataFlowDispatch::class_has_method/2#0d2ae9c0/2@ff66c1lr after 18ms:
202279 ~1%     {2} r1 = JOIN `Class::Class.getAMethod/0#dispred#66416e47_10#join_rhs` WITH `Function::Function.getName/0#dispred#033700ef` ON FIRST 1 OUTPUT Lhs.1 'cls', Rhs.1 'name'
               return r1
...
(490s) Tuple counts for DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3/3@i6#48b6c1xi after 54ms:
0      ~0%     {3} r1 = JOIN `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev_delta` WITH `DataFlowDispatch::getNextClassInMro/1#e1ee596a#reorder_1_0#prev` ON FIRST 1 OUTPUT Rhs.1 'cls', Lhs.1 'name', Lhs.2 'result'
0      ~0%     {3}    | AND NOT `DataFlowDispatch::class_has_method/2#0d2ae9c0`(FIRST 2)

33363  ~0%     {2} r2 = SCAN `DataFlowDispatch::getNextClassInMro/1#e1ee596a#prev_delta` OUTPUT In.1, In.0 'cls'
159696 ~0%     {3}    | JOIN WITH `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev` ON FIRST 1 OUTPUT Lhs.1 'cls', Rhs.1 'name', Rhs.2 'result'
125138 ~1%     {3}    | AND NOT `DataFlowDispatch::class_has_method/2#0d2ae9c0`(FIRST 2)

125138 ~1%     {3} r3 = r1 UNION r2
125138 ~1%     {3}    | AND NOT `DataFlowDispatch::findFunctionAccordingToMro/2#a610c0a3#prev`(FIRST 3)
               return r3
```
2024-06-21 12:16:27 +00:00
Anders Schack-Mulligen
bbdae5188d Dataflow: Add ArgNodeEx column to fwdFlowIsEntered. 2024-06-21 14:10:37 +02:00
Anders Schack-Mulligen
fa13861e53 Dataflow: Add Debug module with stage references. 2024-06-21 14:02:07 +02:00
Mathias Vorreiter Pedersen
47309df2a9 C++: Fix 'toString' on parameter and argument positions. 2024-06-21 12:47:46 +01:00
Mathias Vorreiter Pedersen
85da3d2f13 C++: Update MaD models. 2024-06-21 12:47:43 +01:00
Mathias Vorreiter Pedersen
b0bd7a983f C++: Add MaD syntax for an arbitrary number of dereferences. 2024-06-21 12:47:42 +01:00
Mathias Vorreiter Pedersen
4dc13e850e C++: Add summaries for std dequence containers. 2024-06-21 12:47:40 +01:00
Mathias Vorreiter Pedersen
716df0c7ce C++: Support a richer language in MaD summaries for selecting member functions. 2024-06-21 12:47:39 +01:00
Mauro Baluda
b75514c990 Merge branch 'github:main' into main 2024-06-21 13:36:38 +02:00
Chris Smowton
cfb48ace73 Java: document extraction system requirements
Note that a `java` binary is at least highly recommended for Java extraction, and in many circumstances a hard requirement. The same goes for `mvn` and `gradle`.
2024-06-21 11:53:36 +01:00
Kasper Svendsen
988d0671bb Merge pull request #16734 from kaspersv/kaspersv/doc-intern-sets-builtin
Document builtin InternSets module
2024-06-21 12:06:40 +02:00
Tom Hvitved
a8758c0160 Ruby: Handle element references with blocks 2024-06-21 12:04:55 +02:00
Tom Hvitved
d7ce2be040 Ruby: Up/downgrade scripts 2024-06-21 12:04:53 +02:00
Rasmus Lerchedahl Petersen
280a9b4408 Python: Support Model Editor 2024-06-21 11:47:51 +02:00
Tom Hvitved
dff3ce2a9f Merge pull request #16794 from hvitved/ruby/sinatra-flow
Ruby: Rework `Sinatra.FilterJumpStep`
2024-06-21 11:38:10 +02:00
Tom Hvitved
21c9f33419 Ruby: Bump tree-sitter-ruby 2024-06-21 10:17:59 +02:00
Mathias Vorreiter Pedersen
c357cc9f08 C++: Add change note. 2024-06-21 08:54:12 +01:00
Mathias Vorreiter Pedersen
69490c62cd C++: Add qlpack dependency. 2024-06-21 08:54:10 +01:00
Mathias Vorreiter Pedersen
6bf22bda58 C++: Replace allocation models with models from extensible predicates. 2024-06-21 08:54:09 +01:00
Tom Hvitved
8ea4f85de3 Ruby: Rework Sinatra.FilterJumpStep 2024-06-21 08:57:59 +02:00
Tom Hvitved
95c764eff6 Fix Sinatra test to properly output pathgraph 2024-06-21 08:57:19 +02:00
Erik Krogh Kristensen
db768960f4 Merge pull request #15060 from am0o0/amammad-js-envinjection
JS: Env Injection query
2024-06-20 21:27:21 +02:00
Erik Krogh Kristensen
555d7e5958 Merge pull request #14293 from am0o0/amammad-js-CodeInjection_dynamic_import
JS: Dynamic import as code injection sink
2024-06-20 21:19:57 +02:00
erik-krogh
0de4fd8430 add test for the better type-narrowing in TS 5.5 2024-06-20 20:55:44 +02:00
erik-krogh
9966be6975 update to the stable release of TypeScript 5.5 2024-06-20 20:47:43 +02:00
erik-krogh
b936f725b5 update to 5.5.1-rc 2024-06-20 20:43:01 +02:00
erik-krogh
a691ec01b3 add test for the inferred type predicates in TS5.5 2024-06-20 20:42:59 +02:00
erik-krogh
5336a1a251 upgrade TypeScript to 5.5-beta 2024-06-20 20:42:57 +02:00
Erik Krogh Kristensen
60ed51781e Merge pull request #16790 from github/max-schaefer-patch-1
JavaScript: Fix CodeQL alert in extractor
2024-06-20 20:20:00 +02:00
Erik Krogh Kristensen
e84028d01e Merge pull request #14088 from am0o0/amammad-js-JWT
JS: decoding JWT without signature verification
2024-06-20 20:13:40 +02:00
Mathias Vorreiter Pedersen
d308178781 C++: Add extensible predicate for allocation. 2024-06-20 16:26:52 +01:00
Mathias Vorreiter Pedersen
ce5ab4c4b7 C++: Add qlpack dependency. 2024-06-20 16:26:50 +01:00
Mathias Vorreiter Pedersen
3457551264 C++: Replace deallocation models with models from extensible predicates. 2024-06-20 16:26:49 +01:00
Jeroen Ketema
0e04a59c08 Merge pull request #16795 from jketema/test-cleanup
C++: Remove unneeded options from tests
2024-06-20 16:24:07 +02:00
Mathias Vorreiter Pedersen
e5c20b13cf C++: Add extensible predicate for deallocation. 2024-06-20 14:51:09 +01:00
Jeroen Ketema
4c4c15b425 C++: Remove unneeded options from tests 2024-06-20 14:21:34 +02:00
Owen Mansel-Chan
aa35bd771b Fix bug removing "vendor/" from package paths 2024-06-20 13:18:21 +01:00
Asger F
a36e39359f Merge pull request #16739 from RasmusWL/js-array-steps
JS: Allow many Array steps to be used in type-tracking
2024-06-20 11:39:46 +02:00
Rasmus Lerchedahl Petersen
a7386b6670 Python: include new documentation 2024-06-20 11:25:25 +02:00
Rasmus Lerchedahl Petersen
f0e68887d4 Python: autoformat 2024-06-20 10:59:39 +02:00
yoff
b4fdf3c342 Apply suggestions from code review
Co-authored-by: Ben Ahmady <32935794+subatoi@users.noreply.github.com>
2024-06-20 10:57:54 +02:00
Rasmus Wriedt Larsen
596102d3fb Update javascript/ql/lib/change-notes/2024-06-14-type-tracking-array-steps.md
Co-authored-by: Asger F <asgerf@github.com>
2024-06-20 10:07:49 +02:00
Owen Mansel-Chan
754fd8e84c Drop leading . from getQualifiedName for built-in functions
So it will be "panic" instead of ".panic".
2024-06-19 22:04:21 +01:00
Owen Mansel-Chan
68a661f3c7 Write out whole function names 2024-06-19 21:58:31 +01:00
Owen Mansel-Chan
b79711b17e Move deprecated notice to top of comment 2024-06-19 21:58:28 +01:00
aegilops
1ecd72727d Renamed README to CUSTOMIZING, removed details from qhelp and referenced md doc instead 2024-06-19 17:59:43 +01:00
aegilops
a07639f4f6 Set severity to 7.0, in line with other configuration queries 2024-06-19 17:43:41 +01:00
aegilops
26f1b36736 Fixed formatting 2024-06-19 17:41:58 +01:00
aegilops
252c9e9416 Added data extension to set defaults, updated help, added README to explain customization 2024-06-19 17:27:17 +01:00
Max Schaefer
2be171746b JavaScript: Fix CodeQL alert in extractor
This doesn't make a difference in practice because we only run the method on arrays of even length, but we might as well fix it.
2024-06-19 17:13:01 +01:00
Rasmus Lerchedahl Petersen
5cb37f5c4c python: Document MaD format
- add a few tests reflecting the documentation
- make the mentioned sink-kinds have an effect on relevant queries
2024-06-19 17:00:15 +02:00
Mathias Vorreiter Pedersen
901fac4282 C++: Support 'Element' content in flow summaries. 2024-06-19 13:40:06 +01:00
Mathias Vorreiter Pedersen
013ee9c15e C++: Add support for 'Element' content in dataflow. 2024-06-19 13:39:39 +01:00
Mathias Vorreiter Pedersen
c158f8054e C++: Get rid of all the 'StdContainer' taint models. 2024-06-19 13:36:19 +01:00
Michael Nebel
aa962f9b03 Java: Update expected output of model generation. 2024-06-19 14:10:59 +02:00
Michael Nebel
1185e28ea2 Java: Add some spurious source and sink model generation examples. 2024-06-19 14:10:56 +02:00
Michael Nebel
ed3f1e40db Java: Sync changes and make dummy language specific implementation. 2024-06-19 14:10:54 +02:00
Michael Nebel
99907471b2 C#: Update model generator expected output. 2024-06-19 14:10:52 +02:00
Michael Nebel
40204911bc C#: Only allow source propgatation upwards in the call stack if the call path consists of unique call targets (to avoid unwanted virtual dispatch). This severely tightens the generation of extrapolated sources. 2024-06-19 14:10:49 +02:00
Paul Hodgkinson
3a98edb60b Merge branch 'main' into aegilops/js/insecure-helmet-middleware 2024-06-19 12:53:32 +01:00
Tom Hvitved
6dbdc9e17f Merge pull request #16784 from github/redsun82/fix-warnings-in-ql-tests
C++/Java: Accept new warning format in ql tests
2024-06-19 13:05:50 +02:00
aegilops
d142f830da Change note and changed name of query in .ql file 2024-06-19 12:04:32 +01:00
aegilops
8a3cec4977 Fix formatting for check 2024-06-19 11:38:20 +01:00
Paolo Tranquilli
b7a2ea8981 CI: accept other diagnostic format related test changes 2024-06-19 11:33:50 +02:00
Paolo Tranquilli
59f8f8a394 Merge branch 'main' into redsun82/fix-warnings-in-ql-tests 2024-06-19 11:21:36 +02:00
aegilops
de96d3951d Renamed to helmetProperty everywhere 2024-06-19 10:15:06 +01:00
aegilops
f4691b1919 Changed to more-modern Dataflow libraries 2024-06-19 10:11:06 +01:00
aegilops
81ef255a87 Change to helmetProperty from helmetSetting variable name 2024-06-19 10:09:50 +01:00
Tamás Vajk
45ece48b6f Merge pull request #16776 from tamasvajk/fix/source-generator-folder
C#: Make sure no file is added twice to the compilation
2024-06-19 10:09:50 +02:00
Paolo Tranquilli
919ddccfdb C++/Java: Accept new warning format in ql tests 2024-06-19 09:13:18 +02:00
aegilops
da9e1e61a4 Moved examples into separate files 2024-06-18 19:50:06 +01:00
Edward Minnix III
7adfa6bbed Merge pull request #16709 from egregius313/egregius313/go/df/threat-models/refactor-queries
Go: Refactor queries to use `ThreatModelFlowSource` instead of `RemoteFlowSource`
2024-06-18 13:56:00 -04:00
Alex Ford
51f3f15e42 Ruby: remove outdated test comment 2024-06-18 17:51:49 +01:00
Alex Ford
d79a253c20 Ruby: remove unused import 2024-06-18 17:49:14 +01:00
Alex Ford
7380e29774 Ruby: changenote for rb/weak-sensitive-data-hashing 2024-06-18 17:48:51 +01:00
Alex Ford
d994959720 Ruby: add tests for rb/weak-sensitive-data-hashing 2024-06-18 17:47:32 +01:00
Alex Ford
81ec6861f9 Ruby: fix some SensitiveDataSource definitions 2024-06-18 17:46:52 +01:00
am0o0
eb1999f8b3 revert .vscode/settings.json :(( 2024-06-18 18:43:20 +02:00
am0o0
ccb923a436 fix formatting 2024-06-18 18:31:29 +02:00
Ed Minnix
5bbd003dfc Reword change note 2024-06-18 12:27:21 -04:00
Ed Minnix
b53712cae0 Change note 2024-06-18 12:27:19 -04:00
Ed Minnix
6a0be6ad09 ExternalAPIs 2024-06-18 12:27:18 -04:00
Ed Minnix
46e16b88bb Refactor experimental queries to use ThreadModelFlowSource 2024-06-18 12:27:17 -04:00
Ed Minnix
cfd5f53eb0 Refactor Customizations libraries to use ThreatModelFlowSource 2024-06-18 12:27:15 -04:00
Edward Minnix III
8997f2cdf2 Merge pull request #16697 from egregius313/egregius313/go/dataflow/threat-modeling
Go: Introduce Threat Modeling
2024-06-18 12:25:33 -04:00
Alex Ford
f217de9623 Ruby: Move SensitiveDataSource logic into a private module 2024-06-18 16:58:30 +01:00
am0o0
1f99559e9f Revert "update id of the query file"
This reverts commit 1f112467ce.
2024-06-18 17:33:07 +02:00
am0o0
cb39ae7dd3 revert .vscode/settings.json 2024-06-18 17:27:15 +02:00
am0o0
8a7fdfa6fe fix conflict 2024-06-18 17:18:59 +02:00
Taus
59a77a873c Merge pull request #16754 from github/tausbn/python-disregard-unused-imports-in-pytest-tests
Python: Disregard unused imports in `pytest` tests
2024-06-18 15:10:31 +02:00
Florin Coada
b7b35e5913 Merge pull request #16778 from github/coadaflorin/2.17.4-changedocs-patch
2.17.4 Changelog patch
2024-06-18 13:49:17 +01:00
Owen Mansel-Chan
9403bf25d8 Merge pull request #16667 from smowton/smowton/fix/global-variable-side-effect
Add support for flow through content of global variables
2024-06-18 13:41:57 +01:00
Florin Coada
34f5b676f1 2.17.4 Changelogs patch 2024-06-18 13:34:03 +01:00
Tamas Vajk
6c8e391a63 C#: Make sure no file is added twice to the compilation 2024-06-18 13:45:09 +02:00
Tamas Vajk
5170585515 C#: Add integration test with file added multiple times in the same compilation 2024-06-18 13:45:06 +02:00
Alex Ford
6a46fb54c5 Ruby: Add SensitiveDataSource abstract class 2024-06-18 12:11:28 +01:00
Michael Nebel
1c3ceacf04 C#: Some renaming and re-factoring. 2024-06-18 13:05:21 +02:00
Michael Nebel
dfaa40a1d2 C#: Update expected test output from model generation. 2024-06-18 13:05:17 +02:00
Michael Nebel
b5d6a6db7e C#: Use the same types as sanitizers for source and sink model as we use for summary model generation. 2024-06-18 13:05:12 +02:00
Michael Nebel
031e44b157 C#: Add some source/sink model generator test examples. 2024-06-18 13:05:07 +02:00
Max Schaefer
2c4a95bb5e Merge pull request #16777 from github/max-schaefer-patch-1
Swift: Add missing bracket in example
2024-06-18 11:39:42 +01:00
Alex Ford
6c3d90e8a0 Merge pull request #16650 from alexrford/rb/routing-improvements
Ruby: ActionDispatch - support `path => target` route format
2024-06-18 11:17:05 +01:00
Max Schaefer
9ca74de3e9 Swift: Add missing bracket in example 2024-06-18 11:00:59 +01:00
Joe Farebrother
33704779ea Merge pull request #16503 from joefarebrother/ruby-sensitive-sources
Ruby: Use additional sensitive data heuristics for CleartextSources
2024-06-18 10:57:55 +01:00
Michael Nebel
cd9d58fdc8 Merge pull request #16772 from michaelnebel/java/taintedpermissionthreatmodel
Java: Opt-in `java/tainted-permissions-check` to threat models.
2024-06-18 10:54:28 +02:00
Joe Farebrother
eee7f5a896 Use a combined regex for performance 2024-06-17 22:21:33 +01:00
Cornelius Riemenschneider
0f98d9e815 Merge pull request #16774 from github/criemen/cleanup
Remove unused bzl files.
2024-06-17 20:04:25 +02:00
Chris Smowton
4da5d6660a Add change note 2024-06-17 16:49:09 +01:00
Chris Smowton
38ee085782 Adjust test expectation 2024-06-17 16:46:49 +01:00
Chris Smowton
822f6eebfb Add support for flow through content of global variables 2024-06-17 16:42:23 +01:00
Ed Minnix
b4ecc81145 Fix provenance numbers in tests 2024-06-17 11:33:19 -04:00
Florin Coada
004451ee4b Merge pull request #16773 from github/changedocs/2.17.5
add 2.17.5 unified changelog
2024-06-17 16:09:37 +01:00
Ed Minnix
fa2c50616b Remove getSourceType definitions 2024-06-17 10:57:11 -04:00
Ed Minnix
b6adff6377 Fix jsoniter test 2024-06-17 10:51:13 -04:00
Ed Minnix
53dd269f9f Go: Threat model tests 2024-06-17 10:51:11 -04:00
Ed Minnix
7f19f449eb Change note 2024-06-17 10:51:10 -04:00
Ed Minnix
49fb372eb9 Add getSourceType declarations to existing remote flow sources 2024-06-17 10:51:09 -04:00
Ed Minnix
df6449cfc7 Go: Add the SourceNode and ThreatModelFlowSource classes 2024-06-17 10:51:07 -04:00
Ed Minnix
b697068e9a Go: Add threat modeling shared library 2024-06-17 10:51:06 -04:00
Michael Nebel
5686efd25c Update java/ql/src/change-notes/2024-06-17-tainted-permissions-check.md
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-06-17 16:47:22 +02:00
Alex Ford
f017821062 Ruby: rb/weak-sensitive-data-hashing qhelp 2024-06-17 15:29:53 +01:00
Alex Ford
d4203d9286 Ruby: minimal port of py/weak-sensitive-data-hashing 2024-06-17 15:27:00 +01:00
Cornelius Riemenschneider
f41bd41bd0 Remove unused bzl files. 2024-06-17 15:15:08 +02:00
Michael Nebel
197cdab43d Merge pull request #16752 from michaelnebel/shared/sourcesinkcallables
C#/Java: Add some (shared) helper classes for Neutrals, Sources and Sink
2024-06-17 14:58:27 +02:00
Anders Schack-Mulligen
0e8af39b77 Merge pull request #16719 from aschackmull/shared/fix-qldoc
Shared: Fix file-module qldoc.
2024-06-17 13:26:57 +02:00
Florin Coada
32202acc2d quick fix to remove multiple mentions of CodeQL pack upgrade 2024-06-17 12:19:01 +01:00
Anders Schack-Mulligen
96b6ddefe0 Merge pull request #16751 from aschackmull/java/sndlevelscope-fix
Java: Calculate 2nd level scopes for implicit instance accesses.
2024-06-17 13:10:46 +02:00
Michael Nebel
57925373c6 Address review comment. 2024-06-17 13:02:25 +02:00
Florin Coada
44cca056de add 2.17.5 unified changelog 2024-06-17 12:00:50 +01:00
Michael Nebel
833b4f90bf Java: Make source and sink callable adapters. 2024-06-17 12:53:08 +02:00
Michael Nebel
0fabca94db C#: Use the new shared classes for Source and Sink callables. 2024-06-17 12:53:06 +02:00
Michael Nebel
3d53ddf919 DataFlow: Add some shared classes for Neutrals, Source and Sink callables. 2024-06-17 12:53:03 +02:00
Michael Nebel
e1317ddcb6 Merge pull request #16768 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-06-17 11:51:35 +02:00
Anders Schack-Mulligen
b8b95fd81d Java: Add change note. 2024-06-17 11:46:54 +02:00
Michael Nebel
c3862660e4 Java: Add change note. 2024-06-17 11:07:29 +02:00
Michael Nebel
327dab69d0 Java: Opt-in the tainted permissions check query to threat models. 2024-06-17 11:02:08 +02:00
Jeroen Ketema
1d1a84962b Merge pull request #16765 from jketema/attrib-dup
C++: Add more tests that show we do not properly deduplicate attributes
2024-06-17 07:07:55 +02:00
github-actions[bot]
abe2deb6a6 Add changed framework coverage reports 2024-06-17 00:18:39 +00:00
Andrew Eisenberg
3d3a315456 Merge pull request #16766 from github/aeisenberg/requirements
Add powershell to list of requirements on windows
2024-06-14 15:15:28 -07:00
Andrew Eisenberg
d238b9198d Clarify that this applies to both autobuild and regular builds 2024-06-14 14:41:29 -07:00
Owen Mansel-Chan
b0afba49a2 Merge pull request #16761 from owen-mc/java/reverse-dns-get-loopback-address
Java: Exclude loopback address from reverse DNS source
2024-06-14 22:39:55 +01:00
Andrew Eisenberg
39a8af6519 Add powershell to list of requirements on windows 2024-06-14 14:30:47 -07:00
Jeroen Ketema
14b5114aa6 C++: Add more tests that show we do not properly deduplicate attributes 2024-06-14 17:44:05 +02:00
Jeroen Ketema
c0df22950b Merge pull request #16763 from jketema/attrib-dup
C++: Add test that show that routine attributes are not fully de-duplicated
2024-06-14 17:15:27 +02:00
Taus
b7b0f84e8b Python: Handle @pytest.fixture decorations with arguments as well
Not the prettiest of solutions, but it seems to work well enough.
2024-06-14 15:11:25 +00:00
Taus
c75e66c433 Merge pull request #16762 from github/redsun82/python-disregard-unused-imports-in-pytest-tests
Python: failing unused import test case
2024-06-14 16:57:53 +02:00
Owen Mansel-Chan
9aa0c9f1f3 Fix test expectations 2024-06-14 15:55:30 +01:00
Paolo Tranquilli
1046d03486 Python: update unused import test case for pytest 2024-06-14 16:55:05 +02:00
Jeroen Ketema
7d97463e4d C++: Add test that show that routine attributes are not fully de-duplicated 2024-06-14 16:43:29 +02:00
Ian Lynagh
079717bbc0 Merge pull request #16694 from igfoo/igfoo/PopulationSpecFile
Kotlin: Remove unused PopulationSpecFile
2024-06-14 15:06:39 +01:00
Rasmus Wriedt Larsen
3fc8401370 JS: Add change-note 2024-06-14 15:37:25 +02:00
Rasmus Wriedt Larsen
3f2befc3e5 JS: Support spread arguments in array.splice 2024-06-14 15:33:17 +02:00
Rasmus Wriedt Larsen
269f8ca2cd JS: Add splice(...arr) test 2024-06-14 15:19:56 +02:00
Rasmus Wriedt Larsen
68ccec3d43 JS: Prepare for new test 2024-06-14 15:18:47 +02:00
Taus
2f00a0d323 Python: Also test pytest fixture factories 2024-06-14 13:11:00 +00:00
Owen Mansel-Chan
6cfd9458b0 Add change note 2024-06-14 14:05:25 +01:00
Owen Mansel-Chan
7a13c31021 Exclude loopback address from reverse DNS source 2024-06-14 14:05:01 +01:00
Owen Mansel-Chan
5973f3fadc Add test for reverse DNS from loopback address 2024-06-14 14:04:47 +01:00
Owen Mansel-Chan
098b732937 Fix formatting of inline expectation test comment 2024-06-14 14:04:42 +01:00
Rasmus Wriedt Larsen
194ef607f7 JS: Updated .expected 2024-06-14 14:49:34 +02:00
Taus
78729180ad Python: Fix pytest fixture unused import FPs 2024-06-14 12:05:55 +00:00
Taus
f3a9c9a9dc Python: Add tests for pytest fixture unused import FPs 2024-06-14 12:03:43 +00:00
am0o0
4e1f7a930d fix invalid js file sample in qlhelp 2024-06-14 13:47:01 +02:00
Paolo Tranquilli
e2a47e7c18 Merge pull request #16720 from github/redsun82/kotlin
Kotlin: cleanup after internal changes
2024-06-14 13:28:22 +02:00
Cornelius Riemenschneider
c808953b1d Merge pull request #16723 from github/criemen/codeql-pack-group
`pkg.bzl`: Significantly restructure `codeql_pack` rule.
2024-06-14 13:19:00 +02:00
Michael Nebel
3525967143 Merge pull request #16701 from michaelnebel/csharp/modelgentaintmembers
C#/Java: Improve Sink and Summary model generation.
2024-06-14 12:30:50 +02:00
Tom Hvitved
c7b4f51077 Merge pull request #16758 from hvitved/ruby/shared-ci-trigger
Ruby: Trigger `ruby-build.yml` on changes to shared extractor
2024-06-14 12:00:18 +02:00
Michael B. Gale
039537f7ba Merge pull request #16727 from github/mbg/go/fix/too-many-go-mod-files-initialised 2024-06-14 10:14:57 +01:00
Tom Hvitved
be66ea2178 Ruby: Trigger ruby-build.yml on changes to shared extractor 2024-06-14 11:09:03 +02:00
Michael Nebel
a29446a566 C#/Java: Address review comments. 2024-06-14 10:46:19 +02:00
Cornelius Riemenschneider
58f69c9385 Make CodeQLPackInfo provider public. 2024-06-13 21:57:46 +02:00
Cornelius Riemenschneider
02100e58d9 Address review. 2024-06-13 21:55:56 +02:00
Cornelius Riemenschneider
ede0b5bdf4 Merge remote-tracking branch 'origin/main' into criemen/codeql-pack-group 2024-06-13 21:53:31 +02:00
Paolo Tranquilli
f9db7864e1 Change note: reword 2024-06-13 18:04:23 +02:00
Paolo Tranquilli
0198806658 Merge branch 'main' into redsun82/kotlin 2024-06-13 16:29:13 +02:00
am0o0
bb03a9faba format the query file 2024-06-13 14:54:29 +02:00
am0o0
f0a467e80b update tests 2024-06-13 14:52:22 +02:00
am0o0
84b9d4d1ac fix qlhelp errors 2024-06-13 14:32:41 +02:00
Mathias Vorreiter Pedersen
3d037e73f0 Merge pull request #16749 from MathiasVP/fix-fps-on-double-free
C++: Fix `ArrayExpr` FPs in `cpp/double-free`
2024-06-13 12:58:41 +01:00
Paolo Tranquilli
b8de2ea03b Merge pull request #16731 from github/redsun82/kotlin-fix-version-picker
Kotlin: expose kotlin version picker for internal packaging
2024-06-13 13:57:38 +02:00
Anders Schack-Mulligen
b47831af14 Java: Calculate 2nd level scopes for implicit instance accesses. 2024-06-13 13:57:18 +02:00
Michael B. Gale
1834a399d2 Merge pull request #16738 from github/mbg/go/remove-go-work
Go: Remove `go.work` file
2024-06-13 12:20:12 +01:00
Mathias Vorreiter Pedersen
4bbeda08d6 C++: Fix change note naming. 2024-06-13 11:10:00 +01:00
Mathias Vorreiter Pedersen
83108e3e25 C++: Add change note. 2024-06-13 11:03:52 +01:00
Mathias Vorreiter Pedersen
bcabc88649 C++: Accept test changes. 2024-06-13 10:59:46 +01:00
Mathias Vorreiter Pedersen
4079de125f C++: Fix FP by also excluding indirections of array expressions. 2024-06-13 10:59:39 +01:00
Mathias Vorreiter Pedersen
eec259279a C++: Add another FP test. We already have tests for this, but it doesn't hurt to have another one, I guess. 2024-06-13 10:57:49 +01:00
Mathias Vorreiter Pedersen
e244eef3b5 Merge pull request #16748 from MathiasVP/rc-3.14-mergeback-2
Mergeback from `rc/3.14`
2024-06-13 10:44:46 +01:00
Michael Nebel
7f7c5d7c94 Java: Update model generator expected test output. 2024-06-13 10:57:15 +02:00
Michael Nebel
e247d5b316 Java: Sync files and make dummy language specific implementation. 2024-06-13 10:55:17 +02:00
Michael Nebel
e56c185f32 Java: Add some model generator sink examples. 2024-06-13 10:49:57 +02:00
Mathias Vorreiter Pedersen
0150269503 Merge branch 'rc/3.14' into rc-3.14-mergeback-2 2024-06-13 09:14:40 +01:00
Mathias Vorreiter Pedersen
9384f6189e Merge pull request #16740 from MathiasVP/fix-join-in-ssa
SSA: Fix bad join in `lastRefRedefExt`
2024-06-13 09:06:20 +01:00
Paolo Tranquilli
11c37734c3 Kotlin: add change note for having fixed kotlin QL tests in release 2024-06-13 09:49:39 +02:00
Michael Nebel
854c6fa813 C#: Update expected test output after .NET 8 models update. 2024-06-13 09:24:13 +02:00
Michael Nebel
9ea2b463f0 C#: Update .NET 8 Runtime models. 2024-06-13 08:36:23 +02:00
Michael Nebel
78d23ee044 C#/Java: Allow the model generator to use 32GB of ram. 2024-06-13 08:35:52 +02:00
Maiky
8ba7ac678d Update javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2024-06-12 19:38:13 +02:00
Maiky
4be5cf4e78 Update javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfigurationCustomizations.qll
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2024-06-12 19:38:02 +02:00
Rasmus Wriedt Larsen
ec18786488 JS: Provide better model for Array.splice 2024-06-12 16:29:21 +02:00
Mathias Vorreiter Pedersen
5b3403c4b1 C++: Fix bad join in 'lastRefRedefExt'. 2024-06-12 15:24:58 +01:00
Michael B. Gale
e10e2899bd Go: Update comment in gen.py 2024-06-12 15:24:33 +01:00
Rasmus Wriedt Larsen
54a0e6dc45 JS: Add new test for Array.splice 2024-06-12 16:24:33 +02:00
Michael B. Gale
8629e00686 Go: Remove workspace from vendor/modules.txt 2024-06-12 15:22:56 +01:00
Rasmus Wriedt Larsen
9ed6da1072 JS: prepare to extend Array tests
Oh how I have enjoyed working with InlineExpectationTests for these sort
of things, not worrying about all the .expected files changing because
you add a few lines in the middle of your tests :D
2024-06-12 16:22:55 +02:00
Michael B. Gale
a90968d277 Go: Replace go work vendor with go mod vendor 2024-06-12 15:19:14 +01:00
Rasmus Wriedt Larsen
1027ca266d JS: Allow many Array steps to be used in type-tracking 2024-06-12 16:14:13 +02:00
Joe Farebrother
90d6f2ece3 Factor out nameIndicatesRelevantSensitiveData 2024-06-12 15:11:47 +01:00
Tom Hvitved
605fe54a06 Ruby: Remove two Cartesian products 2024-06-12 15:11:43 +01:00
Joe Farebrother
5f08371f19 Add change note 2024-06-12 15:11:39 +01:00
Joe Farebrother
07f03be8cc Add unit tests 2024-06-12 15:11:35 +01:00
Joe Farebrother
b0c03f6d68 Allow implicit read steps on sinks 2024-06-12 15:11:32 +01:00
Joe Farebrother
8b51ee8fe8 Use additional sensitive data heuristics in CleartextSources 2024-06-12 15:11:27 +01:00
Michael B. Gale
a04f08f026 Go: Remove go.work file 2024-06-12 15:10:28 +01:00
Tamás Vajk
a756f86847 Merge pull request #16732 from tamasvajk/refactor/extraction-states
C#: Refactor extractor state classes and simplify extraction code
2024-06-12 15:20:11 +02:00
Tamas Vajk
0df6a1c4b1 Fix quality issues 2024-06-12 14:48:16 +02:00
Michael Nebel
48739da565 C#: Update expected test output. 2024-06-12 14:16:31 +02:00
Michael Nebel
91ebeee429 C#: Perceive field and property reads as additional flow steps in sink extrapolation. 2024-06-12 14:16:26 +02:00
Michael Nebel
5aee35256d C#: Add member flow example. 2024-06-12 14:16:22 +02:00
Michael Nebel
4b62cb64ed C#: Update expected test output. 2024-06-12 14:16:17 +02:00
Michael Nebel
0bbf131fdb C#: Add some compound sink examples. 2024-06-12 14:16:12 +02:00
Kasper Svendsen
7c2ee80bc3 Document builtin InternSets module 2024-06-12 13:56:48 +02:00
Tamas Vajk
e3cbf1479a Fix quality issue 2024-06-12 13:25:34 +02:00
Arthur Baars
4ee80653e2 Merge pull request #16471 from Sim4n6/ruby-UBV
Ruby: Add some method calls as a Source
2024-06-12 12:42:08 +02:00
Tamas Vajk
3551386a1a Simplify standalone extractor 2024-06-12 12:30:08 +02:00
Owen Mansel-Chan
6af1ed9d75 Merge pull request #16730 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-06-12 11:22:29 +01:00
Tamas Vajk
cdca607828 Rename Extractor to ExtractionContext 2024-06-12 11:43:19 +02:00
Tamas Vajk
af2a78ea4d Reduce references to Extract class 2024-06-12 11:13:05 +02:00
Paolo Tranquilli
183a825841 Kotlin: expose kotlin version picker for internal packaging 2024-06-12 09:29:57 +02:00
github-actions[bot]
bbeebfae73 Add changed framework coverage reports 2024-06-12 00:17:31 +00:00
Joe Farebrother
f441c68f7e Merge pull request #16657 from joefarebrother/python-partial-ssrf-fp
Python: Add additional sanitizers to SSRF
2024-06-11 23:20:50 +01:00
Mauro Baluda
1db5e32e86 Extract SAP XSJS file types as Javascript 2024-06-11 23:53:41 +02:00
Mauro Baluda
45a48f360f Extract SAP XSJS file types as Javascript 2024-06-11 23:51:44 +02:00
Michael B. Gale
e9bd85e0ba Merge pull request #16704 from github/mbg/go/fix/build-scripts-running-more-than-once 2024-06-11 22:23:15 +01:00
Michael B. Gale
202d77d94f Merge pull request #16726 from github/mbg/go/log-one-line-for-stray-sources
Go: Only log one line for stray .go files
2024-06-11 22:16:21 +01:00
Owen Mansel-Chan
24c9062b35 Merge pull request #16671 from owen-mc/go/mad-builtin-taint-models-try-2
Go: Convert old-style models for built-ins to MaD
2024-06-11 19:45:34 +01:00
Michael B. Gale
d8d1ae632c Merge branch 'mbg/go/fix/build-scripts-running-more-than-once' into mbg/go/fix/too-many-go-mod-files-initialised 2024-06-11 18:31:03 +01:00
Michael B. Gale
0f56e408f8 Merge branch 'main' into mbg/go/fix/build-scripts-running-more-than-once 2024-06-11 18:29:41 +01:00
Michael B. Gale
864d629a13 Go: Prevent go.mod files from being added to every directory with stray source files 2024-06-11 18:24:11 +01:00
Michael B. Gale
20b7def543 Go: Only log one line for stray .go files 2024-06-11 18:06:08 +01:00
Geoffrey White
cf4736c8f6 Merge pull request #16545 from geoffw0/salvage
Swift: Salvage
2024-06-11 17:51:17 +01:00
Mathias Vorreiter Pedersen
67b327a0f7 Merge pull request #16725 from MathiasVP/rc-3.14-mergeback
Mergeback from `rc/3.14`
2024-06-11 17:37:40 +01:00
Tony Torralba
a299afaf51 Merge pull request #16712 from mbaluda/main
Java: Add `FileUtils` sinks to path injection
2024-06-11 17:50:08 +02:00
Paolo Tranquilli
3d3652c63f Merge branch 'main' into redsun82/kotlin 2024-06-11 17:25:10 +02:00
Cornelius Riemenschneider
92957a63ad Add prefix feature to codeql_pack_group.
Turns out we need this for our production targets.
2024-06-11 17:22:35 +02:00
Mathias Vorreiter Pedersen
3351b9547d Merge branch 'rc/3.14' into rc-3.14-mergeback 2024-06-11 16:21:08 +01:00
Owen Mansel-Chan
2ae7fa4897 Tests: accept expected changes 2024-06-11 16:20:06 +01:00
Owen Mansel-Chan
6fd2ab7cef Tests: Accept model renumbering in edge provenance 2024-06-11 16:18:18 +01:00
Mathias Vorreiter Pedersen
b88a1b2d1e Merge pull request #16724 from MathiasVP/cache-asexpr
C++: Cache `asExpr` (and `asIndirectExpr`) implementation predicates
2024-06-11 16:17:29 +01:00
Owen Mansel-Chan
700604a1c2 Convert old-style models for built-ins to MaD
These models are to cover the special cases where `append` can be used
with a second argument which is a string followed by `...`, and `copy`
can be used with a second argument which is a string. In this case the
taint is carried by the whole string, rather than in array elements.
2024-06-11 16:16:45 +01:00
Joe Farebrother
93f10fcf14 Add sanitizers for compiled regexes 2024-06-11 15:44:16 +01:00
Mathias Vorreiter Pedersen
6a6978398a C++: Add file QLDoc. 2024-06-11 15:39:45 +01:00
Mathias Vorreiter Pedersen
333df03f64 C++: Cache more things. 2024-06-11 15:39:43 +01:00
Mauro Baluda
a464a8e48e @mbaluda
Update provenance in test expectations
2024-06-11 15:15:50 +02:00
Tamas Vajk
11faf08ed0 Remove specific standalone/tracing extractor state classes 2024-06-11 14:16:35 +02:00
Geoffrey White
214db5c20d Swift: Make CI more happy. 2024-06-11 12:49:58 +01:00
Cornelius Riemenschneider
3cf719cb39 pkg.bzl: Significantly restructure codeql_pack rule.
This PR introduces a `codeql_pack_rule` that does the heavy lifting
of extracting arch- and common zip files for production dist building.
It also factors out the installer targets for individual packs,
as well as pack groups.

This changes the contract between the internal build system and the pack
definition significantly, which is why an accompanying internal PR is required.
No backwards compatibility layer is provided, as the PR as complex enough as-is.

The individual `codeql_pack` rules are now much simpler,
as they mostly stuff their inputs into a new `_CodeQLPackInfo` provider,
and let the installer and `codeql_pack_group` rules do the heavy lifting.
For working in the external repo with self-contained packs,
the per-pack installer targets are still available.
Internally, we'll only use the new `codeql_pack_group` targets
going forward, both for defining intree-dists and for building
the production zip files.
2024-06-11 13:15:05 +02:00
Cornelius Riemenschneider
3574b9fd4f Merge pull request #16716 from github/criemen/rust-bzlmod-new
Rust: Move to bzlmod.
2024-06-11 13:13:16 +02:00
Mauro Baluda
29e3816412 Apply suggestions from code review
Address reviewiew comments

Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2024-06-11 12:05:14 +02:00
Paolo Tranquilli
01416838a1 Merge branch 'main' into redsun82/kotlin 2024-06-11 11:57:19 +02:00
Cornelius Riemenschneider
4226270ef9 Merge branch 'main' into criemen/rust-bzlmod-new 2024-06-11 11:40:40 +02:00
Anders Schack-Mulligen
73caa48302 Merge pull request #16721 from aschackmull/dataflow/remove-unused-import
Dataflow: Remove unused import.
2024-06-11 09:54:05 +02:00
Chris Smowton
3172054073 Merge pull request #16717 from github/post-release-prep/codeql-cli-2.17.5
Post-release preparation for codeql-cli-2.17.5
2024-06-11 07:56:55 +01:00
Anders Schack-Mulligen
939ae4a561 Dataflow: Remove unused import. 2024-06-11 08:55:44 +02:00
Paolo Tranquilli
90db894d01 Kotlin: remove obsolete scripts and reword comments 2024-06-11 08:52:26 +02:00
Anders Schack-Mulligen
87316784ad Shared: Fix file-module qldoc. 2024-06-11 08:49:15 +02:00
Mauro Baluda
bb5ef3ccd9 Update provenance in test expectations 2024-06-10 19:57:37 +02:00
Mauro Baluda
e9dba59f11 Merge branch 'main' into main 2024-06-10 19:57:00 +02:00
Geoffrey White
ae0bf037ac Swift: Make CI happy. 2024-06-10 18:54:16 +01:00
Geoffrey White
2f33b9422b Merge branch 'main' into salvage 2024-06-10 18:31:46 +01:00
Geoffrey White
83860acdde Swift: Test BuiltinLiteralExpr. 2024-06-10 18:20:25 +01:00
Geoffrey White
f2b1e09650 Swift: Add some conversion test cases. 2024-06-10 17:25:25 +01:00
Michael B. Gale
317790eac3 Merge pull request #16703 from github/mbg/go/improve-version-selection-v2
Go: Use toolchain directives for version selection if available, and add tests (v2)
2024-06-10 16:03:00 +00:00
Mathias Vorreiter Pedersen
ec34007a88 Merge pull request #16714 from MathiasVP/handle-unlikely-in-guards-2
C++: Support `__builtin_expect` in `IRGuards`
2024-06-10 16:54:01 +01:00
github-actions[bot]
8a25081a0e Post-release preparation for codeql-cli-2.17.5 2024-06-10 15:33:08 +00:00
Tony Torralba
7336dd1ae5 Merge pull request #16482 from grakshith/rakshith/tune-java-crypto
Java: Add RSA/ECB/OEAP ciphers to the list of secure algorithms
2024-06-10 17:27:35 +02:00
Cornelius Riemenschneider
496fff4273 C#: Remove empty glob pattern. 2024-06-10 17:04:00 +02:00
Cornelius Riemenschneider
00319c5010 Upgrade bazel to 7.2.0.
This also bumps a bunch of external dependencies.
2024-06-10 17:03:59 +02:00
Cornelius Riemenschneider
092bc6445d Rust/bazel: Port to bzlmod.
This gets rid of our last workspace dependency.
In particular, this change also gets rid of the checked-in extra
lock files that took forever to generate.
2024-06-10 17:03:58 +02:00
Michael B. Gale
d4adc373c6 Replace if with else if in RequiredGoVersion 2024-06-10 15:48:29 +01:00
Chris Smowton
a160b891c8 Merge pull request #16715 from github/release-prep/2.17.5
Release preparation for version 2.17.5
2024-06-10 14:46:30 +01:00
github-actions[bot]
877bfa2468 Release preparation for version 2.17.5 2024-06-10 13:40:39 +00:00
Mathias Vorreiter Pedersen
c3bba38950 C++: Fix QLDoc. 2024-06-10 13:39:34 +01:00
Cornelius Riemenschneider
7ecf1f9010 Merge pull request #16713 from github/criemen/csharp-version-fallback
C#: Add fallback for branch detection.
2024-06-10 14:24:37 +02:00
Mathias Vorreiter Pedersen
1aea120e89 C++: Add change note. 2024-06-10 13:01:01 +01:00
Mathias Vorreiter Pedersen
b0c4fcec57 C++: Cleanup. 2024-06-10 12:53:07 +01:00
Mathias Vorreiter Pedersen
9e088f3e4a C++: Accept test changes. 2024-06-10 12:53:06 +01:00
Mathias Vorreiter Pedersen
84c1341b62 C++: Support builtin expect in IRGuards. 2024-06-10 12:53:04 +01:00
Mathias Vorreiter Pedersen
d76700497b C++: Add testcases using the builtin expect operation. 2024-06-10 12:47:45 +01:00
Mathias Vorreiter Pedersen
9c98652116 C++: Handle 'unlikely' in IRGuards. 2024-06-10 12:47:44 +01:00
Jeroen Ketema
000a81fd29 Merge pull request #16690 from MathiasVP/better-guards
C++: Fix missing results for `comparesEq` in `IRGuardCondition`
2024-06-10 13:32:10 +02:00
Sim4n6
7c0ce6486b Rerun the test learn 2024-06-10 12:21:10 +01:00
Cornelius Riemenschneider
027c7d0d43 C#: Add fallback for branch detection.
Apparently, when building a release build, we're getting `no-git`
as first part o the version string for the submodule.
If we do, fall back to the internal repo's branch name.
For releases, that's the same anyways.
Luckily, the commit SHA is correct.
2024-06-10 12:14:03 +02:00
Mauro Baluda
1d44f45be2 Update org.apache.commons.io.model.yml 2024-06-10 12:03:57 +02:00
Mathias Vorreiter Pedersen
7819cc1c36 C++: Add more QLDoc. 2024-06-10 10:58:52 +01:00
Mauro Baluda
71505f4003 Added more org.apache.commons.io.FileUtils-related sinks to the path injection query. 2024-06-10 11:29:51 +02:00
Tamás Vajk
06aa2664bf Merge pull request #16705 from tamasvajk/build/fix-attributes
C#: Add assembly attributes to assemblies built with Bazel
2024-06-10 09:26:31 +02:00
am0o0
9db334d02f update select statement, update test cases 2024-06-07 21:26:20 +02:00
am0o0
2c9340331d update test cases expected results 2024-06-07 21:16:31 +02:00
am0o0
5e0a78c4c7 make predicate for env key and value nodes, use propertyRead/Write instead of API nodes to find env key and value assignments, fix a bug thanks to @erik-krogh 2024-06-07 21:15:30 +02:00
Michael B. Gale
e7a60b72f1 Go: Check dependencies per workspace 2024-06-07 16:22:41 +00:00
Michael B. Gale
b9586a81ef Go: Add functions for constructing go list commands 2024-06-07 16:22:40 +00:00
Michael B. Gale
6c0c3365cf Go: Fix vendor issues and go.sum files in separate loop 2024-06-07 16:22:39 +00:00
Michael B. Gale
d344f720aa Go: Add methods to GoModule for the tidy and vendor commands
These ensure that the module path is used automatically
2024-06-07 16:22:37 +00:00
aegilops
7ee5655f31 Merge branch 'aegilops/js/insecure-helmet-middleware' of https://github.com/aegilops/codeql into aegilops/js/insecure-helmet-middleware 2024-06-07 15:50:15 +01:00
aegilops
975811ae59 Change layout of qhelp example code 2024-06-07 15:50:06 +01:00
Paul Hodgkinson
43a140e62c Merge branch 'main' into aegilops/js/insecure-helmet-middleware 2024-06-07 15:46:18 +01:00
aegilops
7136763c37 Formatting 2024-06-07 15:36:39 +01:00
aegilops
465d64a810 Removed br tags 2024-06-07 15:34:45 +01:00
aegilops
29322f5ff0 Merge branch 'aegilops/js/insecure-helmet-middleware' of https://github.com/aegilops/codeql into aegilops/js/insecure-helmet-middleware 2024-06-07 15:32:23 +01:00
aegilops
f5d465f08a Added data extension to allow setting extra required Helmet features 2024-06-07 15:32:11 +01:00
Tamas Vajk
5f98f2aec9 Add assembly attributes to bazel build script 2024-06-07 15:42:12 +02:00
Cornelius Riemenschneider
6731bccc92 C#: Provide skeleton to generate an assemblyInfo file.
Each unit gets a unique assemblyInfo file, on top
of the ones for entrypoints that also gets the git info embedded.
2024-06-07 15:24:53 +02:00
Tamas Vajk
16f8be4ba4 C#: Add product name to assemblies 2024-06-07 15:24:21 +02:00
Tamas Vajk
beffc2a49d C#: Remove unneeded source folder from Bazel build scripts 2024-06-07 15:23:45 +02:00
Anders Schack-Mulligen
32260e2823 Merge pull request #16210 from aschackmull/dataflow/provenance-for-tests
Dataflow: Add support for pretty-printed alert provenance in tests
2024-06-07 14:53:56 +02:00
Michael B. Gale
881b2586e1 Go: Add tests for RequiredGoVersion 2024-06-07 12:20:44 +00:00
Michael B. Gale
504a233299 Go: Use Toolchain directives in go.mod files, if available 2024-06-07 12:20:43 +00:00
Michael B. Gale
1d6f09c750 Go: Refactor go.mod version retrieval into its own method 2024-06-07 12:20:42 +00:00
Michael B. Gale
44a16cef6c Go: Use Toolchain directives in go.work files, if available 2024-06-07 12:20:41 +00:00
Michael B. Gale
ea3a3db847 Merge pull request #16460 from github/mbg/go/semver-type
Go: Use new type for all semantic versions
2024-06-07 12:19:12 +00:00
Michael B. Gale
9d1c2c6ba1 Merge branch 'main' into mbg/go/semver-type 2024-06-07 12:09:10 +00:00
Anders Schack-Mulligen
9b1e4d7895 Go: Fix test failure. 2024-06-07 13:16:20 +02:00
Anders Schack-Mulligen
7e980d9524 Add a bit more qldoc. 2024-06-07 11:47:50 +02:00
Anders Schack-Mulligen
0c47203580 Javascript: Add support for pretty-printed provenace in tests. 2024-06-07 11:47:49 +02:00
Anders Schack-Mulligen
68ddae2918 Python: Add support for pretty-printed provenace in tests. 2024-06-07 11:47:48 +02:00
Anders Schack-Mulligen
5d51b5b97b Ruby: Add support for pretty-printed provenace in tests. Convert one test. 2024-06-07 11:47:48 +02:00
Anders Schack-Mulligen
a26c01d7c7 Go: Add support for pretty-printed provenace in tests. Convert one test. 2024-06-07 11:47:45 +02:00
Anders Schack-Mulligen
0e8d72c126 C#: Add support for pretty-printed provenace in tests. Convert one test. 2024-06-07 11:45:16 +02:00
Anders Schack-Mulligen
4ec4da4c8c Dataflow/Java: Add support for pretty-printed provenace in tests. Convert one test. 2024-06-07 11:45:13 +02:00
Mathias Vorreiter Pedersen
7f62085be5 C++: Delete unused predicate. 2024-06-07 09:13:29 +01:00
am0o0
1033bf9c4c remove unused imports from javascript test cases 2024-06-07 06:04:12 +02:00
am0o0
b9e3b3310e update the remote flow based query thanks to @erik-krogh, update tests and separate the local and remote query tests 2024-06-07 06:01:49 +02:00
Ian Lynagh
97cb0c89c8 Kotlin: Remove unused PopulationSpecFile 2024-06-06 21:14:28 +01:00
Mathias Vorreiter Pedersen
ed525fce70 C++: Accept test changes. 2024-06-06 20:38:31 +01:00
Mathias Vorreiter Pedersen
b5a3575130 C++: Make proper use of barrier guards in test. 2024-06-06 20:38:17 +01:00
Mathias Vorreiter Pedersen
7b92554cf2 Merge branch 'main' into better-guards 2024-06-06 19:22:10 +01:00
Michael B. Gale
2662808629 Go: Output setup-go compatible pre-release identifiers 2024-06-06 17:14:45 +00:00
Mathias Vorreiter Pedersen
9564ae1ca4 C++: Accept more test changes. 2024-06-06 17:04:48 +01:00
Mathias Vorreiter Pedersen
528afba919 C++: Accept test changes. 2024-06-06 16:32:29 +01:00
Mathias Vorreiter Pedersen
36aac3ffd8 C++: Get rid of 'relevantUnaryComparison' since it was excluding too much. The performance is most likely fine with that restriction. 2024-06-06 16:32:16 +01:00
Mathias Vorreiter Pedersen
703832f5a1 C++: Remove a column from a few predicates. 2024-06-06 16:30:32 +01:00
Mathias Vorreiter Pedersen
0298755975 C++: Add a test. 2024-06-06 16:22:23 +01:00
am0o0
12df7dee17 Merge branch 'amammad-js-JWT' of https://github.com/amammad/codeql into amammad-js-JWT 2024-06-06 14:04:46 +02:00
Am
af016f9416 Merge branch 'github:main' into amammad-js-JWT 2024-06-06 15:33:26 +03:30
am0o0
8258e377dd use PascalCase for URLConstructorLabel 2024-06-06 14:00:56 +02:00
am0o0
d27a378008 change query-id to avoid duplicate ids 2024-06-06 13:59:58 +02:00
Sim4n6
dabc33bf66 simplify UnicodeBypassValidationQuery code 2024-06-05 22:45:49 +01:00
Michael B. Gale
c0142c1a91 Go: Add comment explaining why NewSemVer does not Canonicalise the result 2024-06-05 14:08:45 +00:00
Michael B. Gale
f830dc6852 Merge branch 'main' into mbg/go/semver-type 2024-06-05 13:59:20 +00:00
Michael B. Gale
5dd7e136e5 Merge branch 'main' into mbg/go/semver-type 2024-06-05 12:22:16 +00:00
Sim4n6
7dcbbbac91 Refactor UnicodeBypassValidationQuery to remove unnecessary code 2024-06-05 13:05:34 +01:00
Rakshith Gopalakrishna
798a736d16 fix: update changelog
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2024-06-04 11:20:05 -07:00
Rakshith Gopalakrishna
65af2556ed fix: remove rsa/ecb/* from getASecureAlgorithmName
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2024-06-04 11:20:05 -07:00
Rakshith Gopala krishna
97f9a882c6 fix: address PR comments 2024-06-04 11:20:05 -07:00
Rakshith Gopala krishna
0f63f0dda2 docs: add changenote 2024-06-04 11:20:05 -07:00
Rakshith Gopala krishna
80bf7cdb52 fix: remove the pkcs1 scheme 2024-06-04 11:20:05 -07:00
Rakshith Gopala krishna
dd223ed704 feat: add rsa/ecb/... variants to the list of secure algorithms 2024-06-04 11:20:05 -07:00
Am
e3e59e02e5 Merge branch 'github:main' into amammad-js-CodeInjection_dynamic_import 2024-06-04 16:22:06 +04:00
Joe Farebrother
6ff7fb2a70 Add change note 2024-06-04 09:52:57 +01:00
Joe Farebrother
9331c2c33a Add tests 2024-06-04 09:39:37 +01:00
Joe Farebrother
6ac46b8436 Add additional sanitizers to SSRF for methods that restrict the contents of a string. 2024-06-03 23:23:25 +01:00
Alex Ford
1100b75a3c Ruby: handle routes with path/action pairs 2024-05-31 15:54:57 +01:00
Alex Ford
0473655752 Ruby: actiondispatch add hash arg testcase 2024-05-31 15:08:35 +01:00
Alex Ford
22858249f9 Ruby: actiondispatch test whitespace changes 2024-05-31 15:07:39 +01:00
Alex Ford
4644f08195 Ruby: Routing.qll - rename call as methodCall 2024-05-31 14:45:32 +01:00
Alex Ford
25f9449f53 Ruby: Routing.qll - rename method as httpMethod 2024-05-31 14:45:26 +01:00
Alex Ford
af9ed21c36 Ruby: Routing.qll - rename method as methodCall 2024-05-31 14:45:20 +01:00
am0o0
1f112467ce update id of the query file 2024-05-29 16:48:35 +02:00
am0o0
b9edcb7943 rename secondary to remote :), complete the previous commit changes 2024-05-29 16:47:37 +02:00
am0o0
52a809145e SecondaryCommandInjection to RemoteCommandExecution, change RemoteCommandExecution to module like SystemCommandExecution module 2024-05-29 16:18:55 +02:00
am0o0
fd9e6f48d7 fix the docs of secondary server cmd injection 2024-05-29 16:01:43 +02:00
am0o0
171486641e Ssh2.qll: fix a typo 2024-05-29 16:00:52 +02:00
am0o0
5299c4a845 fix the qhelp of secondary server cmd injectino 2024-05-29 16:00:06 +02:00
am0o0
66cba89fdb Torch.qll: use better alternative instead of exists 2024-05-29 15:43:41 +02:00
am0o0
8c3994bc9c Paramiko.qll: improve docs 2024-05-29 15:42:29 +02:00
am0o0
b1242e464e Pandas.qll: remove unnecessary exists, fix class naming 2024-05-29 15:41:45 +02:00
am0o0
fcd2bd6776 fabic.qll: remove test predicate and apply review changes 2024-05-29 15:37:11 +02:00
maikypedia
e96c3a36ad Move Apollo to experimental 2024-05-27 12:24:48 +02:00
maikypedia
cfd7c7a47c move change-note to javascript/ql/src/change-notes 2024-05-27 11:57:05 +02:00
am0o0
2b929c4d2d remove old expected test file 2024-05-25 20:45:34 +02:00
am0o0
1fc481ce81 v2: it is basically the first stable version :)) 2024-05-25 20:43:36 +02:00
am0o0
ea05b297a3 update expected test files 2024-05-25 19:40:37 +02:00
am0o0
14daf58767 update tests, add test cases for query with local sources 2024-05-25 18:17:56 +02:00
am0o0
8fde8c2db4 change test dir name 2024-05-25 13:54:31 +02:00
am0o0
b397f57357 change queries id according to new naming 2024-05-25 13:53:33 +02:00
am0o0
300c82a8ff use Verification instead of validation in files name 2024-05-25 13:52:32 +02:00
am0o0
76beffb04a change dir name 2024-05-25 13:49:34 +02:00
am0o0
f1533f40b6 change query files name 2024-05-25 13:49:01 +02:00
am0o0
d2d945c66d merge all JWT pkgs into one 2024-05-25 13:47:43 +02:00
am0o0
4af4040bd6 change duplicate query IDs 2024-05-25 13:29:16 +02:00
am0o0
f905ac10c4 add jsonWebToken library file to remove duplicate predicate declrations 2024-05-25 13:28:13 +02:00
Geoffrey White
1f13e462b1 Swift: Change note. 2024-05-23 10:14:59 +01:00
Geoffrey White
06dea2d27f Swift: Use sensitive private info regex from the shared library, now that it has that. 2024-05-23 10:07:42 +01:00
Geoffrey White
0d4cd3e103 Swift: Add more sensitive data test cases. 2024-05-23 10:03:27 +01:00
am0o0
0895f7d971 update qlref files 2024-05-21 22:48:17 +02:00
am0o0
c470c078dc move to experimental 2024-05-21 22:42:16 +02:00
Geoffrey White
8dad622de2 Swift: Fix some inconsistencies. 2024-05-21 16:32:00 +01:00
Paul Hodgkinson
65dfd4c860 Merge branch 'main' into aegilops/js/insecure-helmet-middleware 2024-05-21 14:46:49 +01:00
aegilops
68e21a594a Fixed query help formatting issues 2024-05-21 14:35:18 +01:00
aegilops
bda794fde7 Fixed wrong filenames in the InsecureHelmet tests 2024-05-21 14:34:58 +01:00
aegilops
83037b1195 Adjust structure to avoid warnings about message 2024-05-21 13:51:13 +01:00
aegilops
8300aeb0a0 Tests for InsecureHelmet 2024-05-20 12:05:42 +01:00
aegilops
3a885eaf9f Insecure Helmet middle configuration - frameguard or CSP to 'false' 2024-05-20 11:58:55 +01:00
Mathias Vorreiter Pedersen
533c5218dd Swift: Remove more beta references. 2024-05-15 22:56:50 +01:00
Mathias Vorreiter Pedersen
8f15b0b6c1 Swift: Remove beta label on documentation. 2024-05-15 22:54:34 +01:00
Michael B. Gale
81297aad8c Go: Use standard semver format in outputEnvironmentJson 2024-05-15 12:21:23 +01:00
Michael B. Gale
fabd7a9c51 Go: Better preserve original versions 2024-05-15 12:01:03 +01:00
Michael B. Gale
e0543d1d59 Go: Support all permutations of version prefixes and suffixes 2024-05-15 10:43:02 +01:00
Michael B. Gale
6652685f5a Go: Restore toolchain.IsInstalled check 2024-05-15 10:07:44 +01:00
Michael B. Gale
898383ccff Go: Fix comment in NewSemVer for empty string 2024-05-15 10:07:44 +01:00
Michael B. Gale
054efa648c Go: Move version constants to shared location 2024-05-15 10:03:35 +01:00
Michael B. Gale
9e618b6961 Go: Use SemVer type in autobuilder package 2024-05-15 10:03:35 +01:00
Michael B. Gale
a6d2aa3913 Go: Use SemVer type in project package 2024-05-15 10:03:32 +01:00
Michael B. Gale
010df54657 Go: Use SemVer type in toolchain package 2024-05-15 10:03:01 +01:00
Michael B. Gale
d171750678 Go: Add SemVer type to track valid semantic versions 2024-05-15 10:02:10 +01:00
am0o0
c7adb32bc4 simply replace duplicate class references with classRef() in Fabric.qll 2024-05-14 09:51:47 +02:00
am0o0
37d33186e5 revert classRef deletion, fix secondaryserverCmdInjection expected test results 2024-05-13 15:02:04 +02:00
am0o0
fb3d34ce11 format Torch.qll 2024-05-13 14:43:43 +02:00
Sim4n6
7f153ed07b Add some method calls as a Source 2024-05-12 09:46:36 +01:00
am0o0
90da07159e fix tests, chore on Find.ql 2024-05-10 08:51:23 +02:00
am0o0
a87d27b53e revert vscode settings.json file 2024-05-10 08:35:50 +02:00
am0o0
9435a62a86 revert vscode settings.json file 2024-05-10 08:34:08 +02:00
am0o0
0e80e867af fix actions reviews 2024-05-10 08:32:45 +02:00
am0o0
f93d4a0dd5 fix Fabric query library 2024-05-10 01:27:31 +02:00
am0o0
3a52cd186e Merge branch 'am0o0-python-codeExec' of https://github.com/amammad/codeql into am0o0-python-codeExec 2024-05-09 23:16:11 +02:00
Am
0043d93fc1 Merge branch 'github:main' into am0o0-python-codeExec 2024-05-09 23:15:56 +02:00
am0o0
9b4ea8877b Merge branch 'am0o0-python-codeExec' of https://github.com/amammad/codeql into am0o0-python-codeExec 2024-05-09 23:14:11 +02:00
am0o0
4a2ab49efb better structure for pandas DataFrame, it is now much better readable and also we can find much more DataFrame objects 2024-05-06 14:36:10 +02:00
am0o0
8b93e815b9 minor test cases change: remove unused dict 2024-05-06 14:36:10 +02:00
amammad
6b9cc1a278 update Twisted document link 2024-05-06 14:36:10 +02:00
amammad
c4a38d0a2f add twisted SSH client as secondary server command injection sinks, add proper test cases 2024-05-06 14:36:10 +02:00
amammad
0a765cc94a add jsonpickle and pexpect libs in case of unsafe decoding and secondary command execution, add proper test cases 2024-05-06 14:36:10 +02:00
amammad
7e93102097 finalize Secondary server command injection queries and tests. 2024-05-06 14:36:10 +02:00
amammad
ead247469d add ssh client libraries, add SecondaryServerCmdInjectionCustomizations 2024-05-06 14:36:10 +02:00
amammad
4df73f9975 continue to convert paramiko query to a more general query,
the proxy command is not a secondary command execution
so we can add proxy command to SystemCommandExecution::Range, update QLDocs,
add a proper Paramiko test case
fix a typo
2024-05-06 14:36:10 +02:00
amammad
5fea71e5d6 convert paramiko query to SecondaryServerCmdInjection query, Add inline tests 2024-05-06 14:36:10 +02:00
amammad
6520e2fdfb update Fabric models, add new sink to Fabric, add proper test cases 2024-05-06 14:36:10 +02:00
amammad
2708e57e4b add pyTorch :) code execution sinks, add proper tests 2024-05-06 14:36:10 +02:00
amammad
cffdc5b452 add panas code execution sinks, add proper tests 2024-05-06 14:36:10 +02:00
Geoffrey White
fc7fef3dd8 Swift: Add dataflow tests for dictionaries. 2024-04-15 18:50:41 +01:00
Geoffrey White
0c88d05a65 Swift: QLDoc BuiltinLiteralExpr subclasses and add BuiltinLiteral.getValueString. 2024-04-15 18:23:32 +01:00
Jami
5792f7b770 Merge branch 'main' into jcogs33/unsafe-url-forward-promotion-resource-and-file-methods 2024-04-08 10:26:42 -04:00
Jami Cogswell
e90f55a05f Java: move change note to lib 2024-03-27 20:56:19 -04:00
Jami Cogswell
e58e5fb825 Java: add change note 2024-03-27 20:51:13 -04:00
Jami Cogswell
b35f318910 Java: update models 2024-03-27 20:39:34 -04:00
Jami Cogswell
e285cf232c Java: add resource-related methods as path-injection sinks and as summaries 2024-03-13 22:48:57 -04:00
erik-krogh
f2d6640003 fix ambiguous import. It could refer both to a module or a file 2024-03-12 15:15:50 +01:00
erik-krogh
c1fd7a6190 autoformat 2024-03-12 15:09:45 +01:00
maikypedia
699d8d4719 x 2024-03-07 18:15:22 +01:00
am0o0
b20b733172 better structure for pandas DataFrame, it is now much better readable and also we can find much more DataFrame objects 2024-02-27 09:38:43 +04:00
am0o0
a636c47c84 minor test cases change: remove unused dict 2024-02-25 23:57:58 +04:00
amammad
4321c5c2da update Twisted document link 2024-02-25 17:53:19 +04:00
amammad
7dd1389b9e add twisted SSH client as secondary server command injection sinks, add proper test cases 2024-02-25 17:52:24 +04:00
amammad
ab219902a9 add jsonpickle and pexpect libs in case of unsafe decoding and secondary command execution, add proper test cases 2024-02-25 17:15:35 +04:00
amammad
3e6b4a161b finalize Secondary server command injection queries and tests. 2024-02-25 14:24:42 +04:00
amammad
95c9a3fc9a add ssh client libraries, add SecondaryServerCmdInjectionCustomizations 2024-02-25 12:50:12 +04:00
amammad
385c3ba7ff continue to convert paramiko query to a more general query,
the proxy command is not a secondary command execution
so we can add proxy command to SystemCommandExecution::Range, update QLDocs,
add a proper Paramiko test case
fix a typo
2024-02-25 01:18:34 +04:00
amammad
70282f9ebe convert paramiko query to SecondaryServerCmdInjection query, Add inline tests 2024-02-24 18:10:13 +04:00
amammad
d234a53c50 update Fabric models, add new sink to Fabric, add proper test cases 2024-02-24 17:43:51 +04:00
amammad
076faa3a4e add pyTorch :) code execution sinks, add proper tests 2024-02-24 15:55:33 +04:00
amammad
3d7db0e46b add panas code execution sinks, add proper tests 2024-02-24 14:44:06 +04:00
maikypedia
78e7793e01 Move to experimental 2024-01-09 01:11:58 +01:00
maikypedia
7662b2bd24 format 2023-12-19 13:23:05 +01:00
Maiky
191766a47b Use config.getCorsConfiguration().getOrigin())
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2023-12-18 12:38:39 +01:00
Maiky
4f68f60db2 Apply review
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2023-12-18 12:37:05 +01:00
amammad
102f09aa23 extend tests 2023-12-10 20:33:00 +01:00
amammad
18d0b28024 v1 2023-12-10 20:27:21 +01:00
maikypedia
87cac2a4e3 Express Argument has to be Cors 2023-12-07 23:01:41 +01:00
Maiky
83cbbd7043 Apply docstring changes
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2023-12-05 09:05:29 +01:00
Maiky
e6c7fc0ead Fixes CI 2023-11-29 19:45:08 +02:00
Maiky
6a3cdc90e2 Add change-node 2023-11-27 20:58:47 +02:00
Maiky
3bcb411d1a Using Express::RouteSetup 2023-11-27 20:31:19 +02:00
Maiky
f623db461a Change qldoc 2023-11-27 19:51:13 +02:00
Maiky
bb6ef72e67 getArgument returns Cors::Cors 2023-11-27 19:36:49 +02:00
Maiky
aa24ce5532 Apply suggestions from code review
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2023-11-27 17:48:21 +02:00
amammad
48a9b107b9 add query to detect strapi CVe too 2023-11-24 10:47:17 +01:00
Maiky
4ef4c92e2c Move Customizations and Query 2023-11-23 21:29:09 +01:00
Maiky
abd53e98a9 Fix minor issues 2023-11-23 13:17:54 +01:00
Maiky
413c11171e Move to /experimental 2023-11-23 11:00:47 +01:00
Maiky
d661f7f482 Add Flow Labels 2023-11-22 19:50:16 +01:00
amammad
5cc4206e00 add a temporary Query file to demonstrate unsuccessful usage of two DataFlow configs 2023-11-22 08:30:59 +01:00
amammad
0652afced3 update tests, updated qldoc and examples, upgrade all libraries to path-problem, update jsonwebtoken source and sinks 2023-11-07 08:25:25 +01:00
amammad
a9c8bc082f delete CWE-321 2023-11-02 16:27:31 +01:00
amammad
faa483a282 move to CWE-347, update comments of tests 2023-11-02 16:24:58 +01:00
amammad
9da815a5c0 move to new CWE-321 directory, make saparate query files for each JWT pkg, create a path query for jsonwebtoken package which is not work correctly 2023-11-02 14:13:52 +01:00
amammad
ee4d87bd96 remove hardcoded JWT secret-key query 2023-10-19 11:57:53 +02:00
amammad
7891e64d3e add sanitizers to hardcoded query 2023-10-17 10:37:27 +02:00
Maiky
acac534ed0 Forgot .js 2023-10-16 19:29:57 +02:00
Maiky
07ad596f77 Add coverage for express 2023-10-16 16:48:32 +02:00
Maiky
c0e6d7c049 Merge branch 'github:main' into maikypedia/javascript-cors 2023-10-11 12:20:42 +02:00
amammad
3f41a42c38 remove unused classes 2023-10-08 11:08:05 +02:00
amammad
15671682c5 remove unused flowLable, update path query alert message 2023-10-08 11:06:13 +02:00
amammad
00b6e1f0b0 fix tests 2023-10-08 11:03:19 +02:00
amammad
41e7b91d78 fix flowLabels 2023-10-08 11:00:07 +02:00
Maiky
ed066281b9 Add documentation string for CorsPermissiveConfiguration 2023-10-06 18:22:31 +02:00
Maiky
816eebbb51 Add .qhelp and apply some review changes 2023-10-02 18:05:39 +02:00
Maiky
142ab01b48 Remove comment line 2023-09-29 18:32:12 +02:00
Maiky
e171123589 Add initial query for CWE-942 2023-09-29 18:25:58 +02:00
amammad
f41bc1f631 revert nodeJSLib 2023-09-28 20:37:21 +10:00
amammad
75f0fc4a98 fix a mistake 2023-09-28 20:34:58 +10:00
amammad
921198ed30 add separate query for sinks that accepts data: URL 2023-09-28 20:33:38 +10:00
amammad
f6737b3d90 fix FP 2023-09-25 21:09:19 +10:00
amammad
344869f0d7 change commandExecution sink to CodeInjection sink 2023-09-22 19:37:17 +10:00
amammad
06114d91d8 V1 2023-09-22 19:19:52 +10:00
amammad
7a577ddd98 change Source to ConstantString, it seems that we have some duplicate results now, ConstantString is suggested as a better alternative for finding constant sources 2023-08-30 20:47:43 +10:00
amammad
3f64cc82eb fix qhelps 2023-08-29 22:42:21 +10:00
amammad
4f04dc8f6e add test cases 2023-08-29 21:34:02 +10:00
amammad
65b97745c2 V1 2023-08-29 21:23:02 +10:00
1737 changed files with 138702 additions and 46087 deletions

View File

@@ -1 +1 @@
7.1.2
7.2.1

14
.devcontainer/swift/root.sh Normal file → Executable file
View File

@@ -3,6 +3,16 @@ set -xe
BAZELISK_VERSION=v1.12.0
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
# install git lfs apt source
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
# install gh apt source
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
apt-get update
export DEBIAN_FRONTEND=noninteractive
apt-get -y install --no-install-recommends \
@@ -10,7 +20,9 @@ apt-get -y install --no-install-recommends \
uuid-dev \
python3-distutils \
python3-pip \
bash-completion
bash-completion \
git-lfs \
gh
# Install Bazel
curl -fSsL -o /usr/local/bin/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-linux-amd64

View File

@@ -1,5 +1,7 @@
set -xe
git lfs install
# add the workspace to the codeql search path
mkdir -p /home/vscode/.config/codeql
echo "--search-path /workspaces/codeql" > /home/vscode/.config/codeql/config

View File

@@ -7,6 +7,7 @@ on:
- .github/workflows/ruby-build.yml
- .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml
- "shared/tree-sitter-extractor/**"
branches:
- main
- "rc/*"
@@ -16,6 +17,7 @@ on:
- .github/workflows/ruby-build.yml
- .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml
- "shared/tree-sitter-extractor/**"
branches:
- main
- "rc/*"

View File

@@ -13,22 +13,45 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.9")
bazel_dep(name = "rules_go", version = "0.47.0")
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_go", version = "0.48.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
bazel_dep(name = "rules_python", version = "0.32.2")
bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
bazel_dep(name = "gazelle", version = "0.36.0")
bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.46.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
crate = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
)
crate.from_cargo(
name = "py_deps",
cargo_lockfile = "//python/extractor/tsg-python:Cargo.lock",
manifests = [
"//python/extractor/tsg-python:Cargo.toml",
"//python/extractor/tsg-python/tsp:Cargo.toml",
],
)
crate.from_cargo(
name = "ruby_deps",
cargo_lockfile = "//ruby/extractor:Cargo.lock",
manifests = [
"//ruby/extractor:Cargo.toml",
"//ruby/extractor/codeql-extractor-fake-crate:Cargo.toml",
],
)
use_repo(crate, "py_deps", "ruby_deps")
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "8.0.101")
use_repo(dotnet, "dotnet_toolchains")
@@ -62,6 +85,10 @@ use_repo(
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(
name = "nodejs",
node_urls = [
"https://nodejs.org/dist/v{version}/{filename}",
"https://mirrors.dotsrc.org/nodejs/release/v{version}/{filename}",
],
node_version = "18.15.0",
)
use_repo(node, "nodejs", "nodejs_toolchains")
@@ -85,6 +112,7 @@ use_repo(
"kotlin-compiler-1.9.0-Beta",
"kotlin-compiler-1.9.20-Beta",
"kotlin-compiler-2.0.0-RC1",
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
@@ -97,6 +125,7 @@ use_repo(
"kotlin-compiler-embeddable-1.9.0-Beta",
"kotlin-compiler-embeddable-1.9.20-Beta",
"kotlin-compiler-embeddable-2.0.0-RC1",
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
@@ -109,11 +138,16 @@ use_repo(
"kotlin-stdlib-1.9.0-Beta",
"kotlin-stdlib-1.9.20-Beta",
"kotlin-stdlib-2.0.0-RC1",
"kotlin-stdlib-2.0.20-Beta2",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.22.2")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
lfs_files(

View File

@@ -61,10 +61,6 @@
"java/ql/src/utils/modelgenerator/internal/CaptureModels.qll",
"csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll"
],
"Model as Data Generation Java/C# - CaptureModelsPrinting": [
"java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll",
"csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll"
],
"Sign Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
@@ -185,11 +181,6 @@
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysisImports.qll"
],
"C++ IR ValueNumberingImports": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll"
],
"IR SSA SSAConstruction": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Revert support for using-enum declarations.
compatibility: partial
usings.rel: run usings.qlo
using_container.rel: run using_container.qlo

View File

@@ -0,0 +1,14 @@
class UsingEntry extends @using {
string toString() { none() }
}
class Element extends @element {
string toString() { none() }
}
from UsingEntry u, Element parent, int kind
where
usings(u, _, _, kind) and
using_container(parent, u) and
kind != 3
select parent, u

View File

@@ -0,0 +1,17 @@
class UsingEntry extends @using {
string toString() { none() }
}
class Element extends @element {
string toString() { none() }
}
class Location extends @location_default {
string toString() { none() }
}
from UsingEntry u, Element target, Location loc, int kind
where
usings(u, target, loc, kind) and
kind != 3
select u, target, loc

View File

@@ -0,0 +1,17 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 364 <= kind and kind <= 384)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add new builtin operations
compatibility: partial
exprs.rel: run exprs.qlo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Support destroying deletes
compatibility: full

View File

@@ -1,3 +1,37 @@
## 1.3.0
### New Features
* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
## 1.2.0
### New Features
* The syntax for models-as-data rows has been extended to make it easier to select sources, sinks, and summaries that involve templated functions and classes. Additionally, the syntax has also been extended to make it easier to specify models with arbitrary levels of indirection. See `dataflow/ExternalFlow.qll` for the updated documentation and specification for the model format.
* It is now possible to extend the classes `AllocationFunction` and `DeallocationFunction` via data extensions. Extensions of these classes should be added to the `lib/ext/allocation` and `lib/ext/deallocation` directories respectively.
### Minor Analysis Improvements
* The queries "Potential double free" (`cpp/double-free`) and "Potential use after free" (`cpp/use-after-free`) now produce fewer false positives.
* The "Guards" library (`semmle.code.cpp.controlflow.Guards`) now also infers guards from calls to the builtin operation `__builtin_expect`. As a result, some queries may produce fewer false positives.
## 1.1.1
No user-facing changes.
## 1.1.0
### New Features
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
### Minor Analysis Improvements
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
## 1.0.0
### Breaking Changes

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.

View File

@@ -0,0 +1,9 @@
## 1.1.0
### New Features
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
### Minor Analysis Improvements
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.

View File

@@ -0,0 +1,3 @@
## 1.1.1
No user-facing changes.

View File

@@ -0,0 +1,11 @@
## 1.2.0
### New Features
* The syntax for models-as-data rows has been extended to make it easier to select sources, sinks, and summaries that involve templated functions and classes. Additionally, the syntax has also been extended to make it easier to specify models with arbitrary levels of indirection. See `dataflow/ExternalFlow.qll` for the updated documentation and specification for the model format.
* It is now possible to extend the classes `AllocationFunction` and `DeallocationFunction` via data extensions. Extensions of these classes should be added to the `lib/ext/allocation` and `lib/ext/deallocation` directories respectively.
### Minor Analysis Improvements
* The queries "Potential double free" (`cpp/double-free`) and "Potential use after free" (`cpp/use-after-free`) now produce fewer false positives.
* The "Guards" library (`semmle.code.cpp.controlflow.Guards`) now also infers guards from calls to the builtin operation `__builtin_expect`. As a result, some queries may produce fewer false positives.

View File

@@ -0,0 +1,7 @@
## 1.3.0
### New Features
* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.0
lastReleaseVersion: 1.3.0

View File

@@ -1,4 +1,3 @@
extensions:
# partial model of the Boost::Asio network library
extensions:
- addsTo:

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "kmem_alloc", "0", "", "", True]
- ["", "", False, "kmem_zalloc", "0", "", "", True]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "g_malloc", "0", "", "", True]
- ["", "", False, "g_try_malloc", "0", "", "", True]

View File

@@ -0,0 +1,10 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "CRYPTO_malloc", "0", "", "", True]
- ["", "", False, "CRYPTO_zalloc", "0", "", "", True]
- ["", "", False, "CRYPTO_secure_malloc", "0", "", "", True]
- ["", "", False, "CRYPTO_secure_zalloc", "0", "", "", True]

View File

@@ -0,0 +1,15 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "malloc", "0", "", "", True]
- ["std", "", False, "malloc", "0", "", "", True]
- ["bsl", "", False, "malloc", "0", "", "", True]
- ["", "", False, "alloca", "0", "", "", False]
- ["", "", False, "__builtin_alloca", "0", "", "", False]
- ["", "", False, "_alloca", "0", "", "", False]
- ["", "", False, "_malloca", "0", "", "", False]
- ["", "", False, "calloc", "1", "0", "", True]
- ["std", "", False, "calloc", "1", "0", "", True]
- ["bsl", "", False, "calloc", "1", "0", "", True]

View File

@@ -0,0 +1,29 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "MmAllocateContiguousMemory", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousNodeMemory", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousMemorySpecifyCache", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousMemorySpecifyCacheNode", "0", "", "", True]
- ["", "", False, "MmAllocateNonCachedMemory", "0", "", "", True]
- ["", "", False, "MmAllocateMappingAddress", "0", "", "", True]
- ["", "", False, "CoTaskMemAlloc", "0", "", "", True]
- ["", "", False, "ExAllocatePool", "1", "", "", True]
- ["", "", False, "ExAllocatePool2", "1", "", "", True]
- ["", "", False, "ExAllocatePool3", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithTag", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithTagPriority", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithQuota", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithQuotaTag", "1", "", "", True]
- ["", "", False, "ExAllocatePoolZero", "1", "", "", True]
- ["", "", False, "IoAllocateMdl", "1", "", "", True]
- ["", "", False, "IoAllocateErrorLogEntry", "1", "", "", True]
- ["", "", False, "LocalAlloc", "1", "", "", True]
- ["", "", False, "GlobalAlloc", "1", "", "", True]
- ["", "", False, "VirtualAlloc", "1", "", "", True]
- ["", "", False, "HeapAlloc", "2", "", "", True]
- ["", "", False, "MmAllocatePagesForMdl", "3", "", "", True]
- ["", "", False, "MmAllocatePagesForMdlEx", "3", "", "", True]
- ["", "", False, "MmAllocateNodePagesForMdlEx", "3", "", "", True]

View File

@@ -0,0 +1,5 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data: []

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["bsl", "array", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "array", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "array", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "array", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "array", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "array", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "array", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "array", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "array", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]

View File

@@ -0,0 +1,73 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["bsl", "deque<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "deque", "(const deque &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "deque", "(deque &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "deque", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T,Allocator>", True, "deque", "(const deque &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T,Allocator>", True, "deque", "(deque &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T,Allocator>", True, "deque", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T,Allocator>", True, "deque<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,56 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "forward_list", "(const forward_list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "forward_list", "(forward_list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(const forward_list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(forward_list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,71 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["bsl", "list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list", True, "list", "(const list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "list", "(list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T,Allocator>", True, "list", "(const list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T,Allocator>", True, "list", "(list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T,Allocator>", True, "list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T,Allocator>", True, "list<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,60 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["bsl", "vector<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["bsl", "vector", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector", True, "vector", "(const vector &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector", True, "vector", "(vector &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T,Allocator>", True, "vector", "(const vector &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T,Allocator>", True, "vector", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T,Allocator>", True, "vector", "(vector &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T,Allocator>", True, "vector<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,8 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "pool_put", "1"]
- ["", "", False, "pool_cache_put", "1"]
- ["", "", False, "kmem_free", "0"]

View File

@@ -0,0 +1,42 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "free", "0"]
- ["std", "", False, "free", "0"]
- ["bsl", "", False, "free", "0"]
- ["", "", False, "realloc", "0"]
- ["std", "", False, "realloc", "0"]
- ["bsl", "", False, "realloc", "0"]
- ["", "", False, "CRYPTO_free", "0"]
- ["", "", False, "CRYPTO_secure_free", "0"]
- ["", "", False, "g_free", "0"]
- ["", "", False, "ExFreePool", "0"]
- ["", "", False, "ExFreePoolWithTag", "0"]
- ["", "", False, "ExDeleteTimer", "0"]
- ["", "", False, "IoFreeIrp", "0"]
- ["", "", False, "IoFreeMdl", "0"]
- ["", "", False, "IoFreeErrorLogEntry", "0"]
- ["", "", False, "IoFreeWorkItem", "0"]
- ["", "", False, "MmFreeContiguousMemory", "0"]
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
- ["", "", False, "MmFreeNonCachedMemory", "0"]
- ["", "", False, "MmFreeMappingAddress", "0"]
- ["", "", False, "MmFreePagesFromMdl", "0"]
- ["", "", False, "MmUnmapReservedMapping", "0"]
- ["", "", False, "MmUnmapLockedPages", "0"]
- ["", "", False, "NdisFreeGenericObject", "0"]
- ["", "", False, "NdisFreeMemory", "0"]
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
- ["", "", False, "NdisFreeMdl", "0"]
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
- ["", "", False, "NdisFreeNetBufferPool", "0"]
- ["", "", False, "LocalFree", "0"]
- ["", "", False, "GlobalFree", "0"]
- ["", "", False, "LocalReAlloc", "0"]
- ["", "", False, "GlobalReAlloc", "0"]
- ["", "", False, "VirtualFree", "0"]
- ["", "", False, "CoTaskMemFree", "0"]
- ["", "", False, "CoTaskMemRealloc", "0"]
- ["", "", False, "SysFreeString", "0"]

View File

@@ -0,0 +1,41 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "ExFreePool", "0"]
- ["", "", False, "ExFreePoolWithTag", "0"]
- ["", "", False, "ExDeleteTimer", "0"]
- ["", "", False, "IoFreeIrp", "0"]
- ["", "", False, "IoFreeMdl", "0"]
- ["", "", False, "IoFreeErrorLogEntry", "0"]
- ["", "", False, "IoFreeWorkItem", "0"]
- ["", "", False, "MmFreeContiguousMemory", "0"]
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
- ["", "", False, "MmFreeNonCachedMemory", "0"]
- ["", "", False, "MmFreeMappingAddress", "0"]
- ["", "", False, "MmFreePagesFromMdl", "0"]
- ["", "", False, "MmUnmapReservedMapping", "0"]
- ["", "", False, "MmUnmapLockedPages", "0"]
- ["", "", False, "NdisFreeGenericObject", "0"]
- ["", "", False, "NdisFreeMemory", "0"]
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
- ["", "", False, "NdisFreeMdl", "0"]
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
- ["", "", False, "NdisFreeNetBufferPool", "0"]
- ["", "", False, "LocalFree", "0"]
- ["", "", False, "GlobalFree", "0"]
- ["", "", False, "LocalReAlloc", "0"]
- ["", "", False, "GlobalReAlloc", "0"]
- ["", "", False, "VirtualFree", "0"]
- ["", "", False, "CoTaskMemFree", "0"]
- ["", "", False, "CoTaskMemRealloc", "0"]
- ["", "", False, "SysFreeString", "0"]
- ["", "", False, "ExFreeToLookasideListEx", "1"]
- ["", "", False, "ExFreeToPagedLookasideList", "1"]
- ["", "", False, "ExFreeToNPagedLookasideList", "1"]
- ["", "", False, "NdisFreeMemoryWithTagPriority", "1"]
- ["", "", False, "StorPortFreeMdl", "1"]
- ["", "", False, "StorPortFreePool", "1"]
- ["", "", False, "HeapFree", "2"]
- ["", "", False, "HeapReAlloc", "2"]

View File

@@ -0,0 +1,5 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data: []

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "array", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "array", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "array", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "array", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "array", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "array", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "array", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "array", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "array", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]

View File

@@ -0,0 +1,73 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "deque<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "deque", "(const deque &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "deque", "(deque &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "deque", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T,Allocator>", True, "deque", "(const deque &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T,Allocator>", True, "deque", "(deque &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T,Allocator>", True, "deque", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T,Allocator>", True, "deque<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,56 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "forward_list", "(const forward_list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "forward_list", "(forward_list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(const forward_list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(forward_list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,11 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "iterator", True, "operator*", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "iterator", True, "operator->", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "iterator", True, "iterator", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["__gnu_cxx", "__normal_iterator", True, "operator*", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["__gnu_cxx", "__normal_iterator", True, "operator->", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["__gnu_cxx", "__normal_iterator", True, "__normal_iterator", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]

View File

@@ -0,0 +1,71 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "list", "(const list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "list", "(list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T,Allocator>", True, "list", "(const list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T,Allocator>", True, "list", "(list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T,Allocator>", True, "list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T,Allocator>", True, "list<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -0,0 +1,60 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "vector<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
- ["std", "vector", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector", True, "vector", "(const vector &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector", True, "vector", "(vector &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T,Allocator>", True, "vector", "(const vector &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T,Allocator>", True, "vector", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T,Allocator>", True, "vector", "(vector &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T,Allocator>", True, "vector<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 1.0.1-dev
version: 1.3.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
@@ -16,4 +16,6 @@ dependencies:
codeql/xml: ${workspace}
dataExtensions:
- ext/*.model.yml
- ext/deallocation/*.model.yml
- ext/allocation/*.model.yml
warnOnImplicitThis: true

View File

@@ -156,7 +156,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
* A C++ `using` directive or `using` declaration.
*/
class UsingEntry extends Locatable, @using {
override Location getLocation() { usings(underlyingElement(this), _, result) }
override Location getLocation() { usings(underlyingElement(this), _, result, _) }
}
/**
@@ -166,15 +166,13 @@ class UsingEntry extends Locatable, @using {
* ```
*/
class UsingDeclarationEntry extends UsingEntry {
UsingDeclarationEntry() {
not exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
}
UsingDeclarationEntry() { usings(underlyingElement(this), _, _, 1) }
/**
* Gets the declaration that is referenced by this using declaration. For
* example, `std::string` in `using std::string`.
*/
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) }
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _, _) }
override string toString() { result = "using " + this.getDeclaration().getDescription() }
}
@@ -186,19 +184,36 @@ class UsingDeclarationEntry extends UsingEntry {
* ```
*/
class UsingDirectiveEntry extends UsingEntry {
UsingDirectiveEntry() {
exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
}
UsingDirectiveEntry() { usings(underlyingElement(this), _, _, 2) }
/**
* Gets the namespace that is referenced by this using directive. For
* example, `std` in `using namespace std`.
*/
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) }
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _, _) }
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
}
/**
* A C++ `using enum` declaration. For example:
* ```
* enum class Foo { a, b };
* using enum Foo;
* ```
*/
class UsingEnumDeclarationEntry extends UsingEntry {
UsingEnumDeclarationEntry() { usings(underlyingElement(this), _, _, 3) }
/**
* Gets the enumeration that is referenced by this using directive. For
* example, `Foo` in `using enum Foo`.
*/
Enum getEnum() { usings(underlyingElement(this), unresolveElement(result), _, _) }
override string toString() { result = "using enum " + this.getEnum().getQualifiedName() }
}
/**
* Holds if `g` is an instance of `GlobalNamespace`. This predicate
* is used suppress a warning in `GlobalNamespace.getADeclaration()`

View File

@@ -59,8 +59,7 @@ class MatchValue extends AbstractValue, TMatchValue {
}
/**
* A Boolean condition in the AST that guards one or more basic blocks. This includes
* operands of logical operators but not switch statements.
* A Boolean condition in the AST that guards one or more basic blocks.
*/
cached
class GuardCondition extends Expr {
@@ -366,15 +365,42 @@ private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled)
}
/**
* A Boolean condition in the IR that guards one or more basic blocks. This includes
* operands of logical operators but not switch statements. Note that `&&` and `||`
* don't have an explicit representation in the IR, and therefore will not appear as
* IRGuardConditions.
* A Boolean condition in the IR that guards one or more basic blocks.
*
* Note that `&&` and `||` don't have an explicit representation in the IR,
* and therefore will not appear as IRGuardConditions.
*/
cached
class IRGuardCondition extends Instruction {
Instruction branch;
/*
* An `IRGuardCondition` supports reasoning about four different kinds of
* relations:
* 1. A unary equality relation of the form `e == k`
* 2. A binary equality relation of the form `e1 == e2 + k`
* 3. A unary inequality relation of the form `e < k`
* 4. A binary inequality relation of the form `e1 < e2 + k`
*
* where `k` is a constant.
*
* Furthermore, the unary relations (i.e., case 1 and case 3) are also
* inferred from `switch` statement guards: equality relations are inferred
* from the unique `case` statement, if any, and inequality relations are
* inferred from the [case range](https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html)
* gcc extension.
*
* The implementation of all four follows the same structure: Each relation
* has a cached user-facing predicate that. For example,
* `GuardCondition::comparesEq` calls `compares_eq`. This predicate has
* several cases that recursively decompose the relation to bring it to a
* canonical form (i.e., a relation of the form `e1 == e2 + k`). The base
* case for this relation (i.e., `simple_comparison_eq`) handles
* `CompareEQInstruction`s and `CompareNEInstruction`, and recursive
* predicates (e.g., `complex_eq`) rewrites larger expressions such as
* `e1 + k1 == e2 + k2` into canonical the form `e1 == e2 + (k2 - k1)`.
*/
cached
IRGuardCondition() { branch = getBranchForCondition(this) }
@@ -735,6 +761,8 @@ private predicate compares_eq(
exists(AbstractValue dual | value = dual.getDualValue() |
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
)
or
compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), left, right, k, areEqual, value)
}
/**
@@ -776,7 +804,9 @@ private predicate unary_compares_eq(
Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
exists(AbstractValue v |
unary_simple_comparison_eq(test, k, inNonZeroCase, v) and op.getDef() = test
|
areEqual = true and value = v
or
areEqual = false and value = v.getDualValue()
@@ -802,6 +832,9 @@ private predicate unary_compares_eq(
int_value(const) = k1 and
k = k1 + k2
)
or
unary_compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), op, k, areEqual,
inNonZeroCase, value)
}
/** Rearrange various simple comparisons into `left == right + k` form. */
@@ -821,45 +854,55 @@ private predicate simple_comparison_eq(
value.(BooleanValue).getValue() = false
}
/**
* Holds if `test` is an instruction that is part of test that eventually is
* used in a conditional branch.
*/
private predicate relevantUnaryComparison(Instruction test) {
not test instanceof CompareInstruction and
exists(IRType type, ConditionalBranchInstruction branch |
type instanceof IRAddressType or type instanceof IRIntegerType
|
type = test.getResultIRType() and
branch.getCondition() = test
)
or
exists(LogicalNotInstruction logicalNot |
relevantUnaryComparison(logicalNot) and
test = logicalNot.getUnary()
)
}
/**
* Rearrange various simple comparisons into `op == k` form.
*/
private predicate unary_simple_comparison_eq(
Instruction test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
Instruction test, int k, boolean inNonZeroCase, AbstractValue value
) {
exists(SwitchInstruction switch, CaseEdge case |
test = switch.getExpression() and
op.getDef() = test and
case = value.(MatchValue).getCase() and
exists(switch.getSuccessor(case)) and
case.getValue().toInt() = k and
inNonZeroCase = false
)
or
// There's no implicit CompareInstruction in files compiled as C since C
// doesn't have implicit boolean conversions. So instead we check whether
// there's a branch on a value of pointer or integer type.
relevantUnaryComparison(test) and
op.getDef() = test and
// Any instruction with an integral type could potentially be part of a
// check for nullness when used in a guard. So we include all integral
// typed instructions here. However, since some of these instructions are
// already included as guards in other cases, we exclude those here.
// These are instructions that compute a binary equality or inequality
// relation. For example, the following:
// ```cpp
// if(a == b + 42) { ... }
// ```
// generates the following IR:
// ```
// r1(glval<int>) = VariableAddress[a] :
// r2(int) = Load[a] : &:r1, m1
// r3(glval<int>) = VariableAddress[b] :
// r4(int) = Load[b] : &:r3, m2
// r5(int) = Constant[42] :
// r6(int) = Add : r4, r5
// r7(bool) = CompareEQ : r2, r6
// v1(void) = ConditionalBranch : r7
// ```
// and since `r7` is an integral typed instruction this predicate could
// include a case for when `r7` evaluates to true (in which case we would
// infer that `r6` was non-zero, and a case for when `r7` evaluates to false
// (in which case we would infer that `r6` was zero).
// However, since `a == b + 42` is already supported when reasoning about
// binary equalities we exclude those cases here.
not test.isGLValue() and
not simple_comparison_eq(test, _, _, _, _) and
not simple_comparison_lt(test, _, _, _) and
not test = any(SwitchInstruction switch).getExpression() and
(
test.getResultIRType() instanceof IRAddressType or
test.getResultIRType() instanceof IRIntegerType or
test.getResultIRType() instanceof IRBooleanType
) and
(
k = 1 and
value.(BooleanValue).getValue() = true and
@@ -871,12 +914,68 @@ private predicate unary_simple_comparison_eq(
)
}
/** A call to the builtin operation `__builtin_expect`. */
private class BuiltinExpectCallInstruction extends CallInstruction {
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
/** Gets the condition of this call. */
Instruction getCondition() {
// The first parameter of `__builtin_expect` has type `long`. So we skip
// the conversion when inferring guards.
result = this.getArgument(0).(ConvertInstruction).getUnary()
}
}
/**
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
* and `cmp` is an instruction that compares the value of
* `__builtin_expect(left == right + k, _)` to `0`.
*/
private predicate builtin_expect_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
compares_eq(call.getCondition(), left, right, k, areEqual, innerValue)
|
cmp instanceof CompareNEInstruction and
value = innerValue
or
cmp instanceof CompareEQInstruction and
value.getDualValue() = innerValue
)
}
private predicate complex_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
sub_eq(cmp, left, right, k, areEqual, value)
or
add_eq(cmp, left, right, k, areEqual, value)
or
builtin_expect_eq(cmp, left, right, k, areEqual, value)
}
/**
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and `cmp` is
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
*/
private predicate unary_builtin_expect_eq(
CompareInstruction cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
AbstractValue value
) {
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
|
cmp instanceof CompareNEInstruction and
value = innerValue
or
cmp instanceof CompareEQInstruction and
value.getDualValue() = innerValue
)
}
private predicate unary_complex_eq(
@@ -885,6 +984,8 @@ private predicate unary_complex_eq(
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
or
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
or
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
}
/*
@@ -913,7 +1014,8 @@ private predicate compares_lt(
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
simple_comparison_lt(test, op, k, isLt, value)
unary_simple_comparison_lt(test, k, isLt, value) and
op.getDef() = test
or
complex_lt(test, op, k, isLt, value)
or
@@ -960,12 +1062,11 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
}
/** Rearrange various simple comparisons into `op < k` form. */
private predicate simple_comparison_lt(
Instruction test, Operand op, int k, boolean isLt, AbstractValue value
private predicate unary_simple_comparison_lt(
Instruction test, int k, boolean isLt, AbstractValue value
) {
exists(SwitchInstruction switch, CaseEdge case |
test = switch.getExpression() and
op.getDef() = test and
case = value.(MatchValue).getCase() and
exists(switch.getSuccessor(case)) and
case.getMaxValue() > case.getMinValue()

View File

@@ -14,16 +14,22 @@
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
* 1. The `namespace` column selects a namespace.
* 2. The `type` column selects a type within that namespace.
* 2. The `type` column selects a type within that namespace. This column can
* introduce template names that can be mentioned in the `signature` column.
* For example, `vector<T,Allocator>` introduces the template names `T` and
* `Allocator`.
* 3. The `subtypes` is a boolean that indicates whether to jump to an
* arbitrary subtype of that type. Set this to `false` if leaving the `type`
* blank (for example, a free function).
* 4. The `name` column optionally selects a specific named member of the type.
* Like the `type` column, this column can introduce template names that can
* be mentioned in the `signature` column. For example, `insert<InputIt>`
* introduces the template name `InputIt`.
* 5. The `signature` column optionally restricts the named member. If
* `signature` is blank then no such filtering is done. The format of the
* signature is a comma-separated list of types enclosed in parentheses. The
* types can be short names or fully qualified names (mixing these two options
* is not allowed within a single signature).
* types must be stripped of template names. That is, write `const vector &`
* instead of `const vector<T> &`.
* 6. The `ext` column specifies additional API-graph-like edges. Currently
* there is only one valid value: "".
* 7. The `input` column specifies how data enters the element selected by the
@@ -44,6 +50,9 @@
* One or more "*" can be added as an argument to indicate indirection, for
* example, "ReturnValue[*]" indicates the first indirection of the return
* value.
* The special symbol `@` can be used to specify an arbitrary (but fixed)
* number of indirections. For example, the `input` column `Argument[*@0]`
* indicates one or more indirections of the 0th argument.
*
* An `output` can be either:
* - "": Selects a read of a selected field.
@@ -65,6 +74,17 @@
* One or more "*" can be added as an argument to indicate indirection, for
* example, "ReturnValue[*]" indicates the first indirection of the return
* value.
* The special symbol `@` can be used to specify an arbitrary (but fixed)
* number of indirections. For example, the `output` column
* `ReturnValue[*@0]` indicates one or more indirections of the return
* value.
* Note: The symbol `@` only ever takes a single value across a row. Thus,
* the (`input`, `output`) pair `("Argument[*@0]", "ReturnValue[@]")`
* represents:
* - flow from the _first_ indirection of the 0th argument to the return
* value, and
* - flow from the _second_ indirection of the 0th argument to the first
* indirection of the return value, etc.
* 8. The `kind` column is a tag that can be referenced from QL to determine to
* which classes the interpreted elements should be added. For example, for
* sources "remote" indicates a default remote flow source, and for summaries
@@ -74,6 +94,8 @@
import cpp
private import new.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import internal.FlowSummaryImpl
private import internal.FlowSummaryImpl::Public
private import internal.FlowSummaryImpl::Private
@@ -124,7 +146,7 @@ predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
@@ -138,16 +160,20 @@ predicate sourceModel(
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance,
_)
exists(QlBuiltins::ExtensionId madId |
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
@@ -161,15 +187,24 @@ predicate sinkModel(
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, _)
exists(QlBuiltins::ExtensionId madId |
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a summary model exists for the given parameters. */
predicate summaryModel(
/**
* Holds if a summary model exists for the given parameters.
*
* This predicate does not expand `@` to `*`s.
*/
private predicate summaryModel0(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
@@ -184,16 +219,48 @@ predicate summaryModel(
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, _)
exists(QlBuiltins::ExtensionId madId |
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/**
* Holds if `input` is `input0`, but with all occurrences of `@` replaced
* by `n` repetitions of `*` (and similarly for `output` and `output0`).
*/
bindingset[input0, output0, n]
pragma[inline_late]
private predicate expandInputAndOutput(
string input0, string input, string output0, string output, int n
) {
input = input0.replaceAll("@", repeatStars(n)) and
output = output0.replaceAll("@", repeatStars(n))
}
/**
* Holds if a summary model exists for the given parameters.
*/
predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, string model
) {
exists(string input0, string output0 |
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
provenance, model) and
expandInputAndOutput(input0, input, output0, output,
[0 .. Private::getMaxElementContentIndirectionIndex() - 1])
)
}
private predicate relevantNamespace(string namespace) {
sourceModel(namespace, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _)
sourceModel(namespace, _, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _, _)
}
private predicate namespaceLink(string shortns, string longns) {
@@ -223,17 +290,17 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
part = "source" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string output, string provenance |
string ext, string output, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance)
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, model)
)
or
part = "sink" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string provenance |
string ext, string input, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance)
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, model)
)
or
part = "summary" and
@@ -241,7 +308,7 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance)
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _)
)
)
}
@@ -250,9 +317,9 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
module CsvValidation {
private string getInvalidModelInput() {
exists(string pred, AccessPath input, string part |
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
or
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
(
invalidSpecComponent(input, part) and
@@ -269,9 +336,9 @@ module CsvValidation {
private string getInvalidModelOutput() {
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
or
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
invalidSpecComponent(output, part) and
not part = "" and
@@ -281,11 +348,11 @@ module CsvValidation {
}
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
}
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
@@ -326,11 +393,11 @@ module CsvValidation {
private string getInvalidModelSignature() {
exists(string pred, string namespace, string type, string name, string signature, string ext |
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
sourceModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
sinkModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -362,21 +429,160 @@ module CsvValidation {
private predicate elementSpec(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedMemberFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and
exists(Class c, Class templateClass, int i |
c.isConstructedFrom(templateClass) and
f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
}
/**
* Gets the type name of the `n`'th parameter of `f` without any template
* arguments.
*/
bindingset[f]
pragma[inline_late]
string getParameterTypeWithoutTemplateArguments(Function f, int n) {
exists(string s, string base, string specifiers |
s = f.getParameter(n).getType().getName() and
parseAngles(s, base, _, specifiers) and
result = base + specifiers
)
}
/**
* Normalize the `n`'th parameter of `f` by replacing template names
* with `func:N` (where `N` is the index of the template).
*/
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction |
templateFunction = getFullyTemplatedMemberFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
)
or
exists(string mid, TemplateParameter tp, Function templateFunction |
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
templateFunction = getFullyTemplatedMemberFunction(f) and
tp = templateFunction.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
)
}
/**
* Normalize the `n`'th parameter of `f` by replacing template names
* with `class:N` (where `N` is the index of the template).
*/
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
exists(Class template |
f.getDeclaringType().isConstructedFrom(template) and
remaining = template.getNumberOfTemplateArguments() and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
)
or
exists(string mid, TemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
f.getDeclaringType().isConstructedFrom(template) and
tp = template.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
)
}
/** Gets the string representation of the `i`'th parameter of `c`. */
private string getParameterTypeName(Function c, int i) {
result = getTypeNameWithoutClassTemplates(c, i, 0)
}
/** Splits `s` by `,` and gets the `i`'th element. */
bindingset[s]
pragma[inline_late]
private string getAtIndex(string s, int i) {
result = s.splitAt(",", i) and
// when `s` is `""` and `i` is `0` we get `result = ""` which we don't want.
not (s = "" and i = 0)
}
/**
* Normalizes `partiallyNormalizedSignature` by replacing the `remaining`
* number of template arguments in `partiallyNormalizedSignature` with their
* index in `typeArgs`.
*/
private string getSignatureWithoutClassTemplateNames(
string partiallyNormalizedSignature, string typeArgs, string nameArgs, int remaining
) {
elementSpecWithArguments0(_, _, _, partiallyNormalizedSignature, typeArgs, nameArgs) and
remaining = count(partiallyNormalizedSignature.indexOf(",")) + 1 and
result = partiallyNormalizedSignature
or
exists(string mid |
mid =
getSignatureWithoutClassTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs,
remaining + 1)
|
exists(string typeArg |
typeArg = getAtIndex(typeArgs, remaining) and
result = mid.replaceAll(typeArg, "class:" + remaining.toString())
)
or
// Make sure `remaining` is properly bound
remaining = [0 .. count(partiallyNormalizedSignature.indexOf(",")) + 1] and
not exists(getAtIndex(typeArgs, remaining)) and
result = mid
)
}
/**
* Normalizes `partiallyNormalizedSignature` by replacing:
* - _All_ the template arguments in `partiallyNormalizedSignature` that refer to
* template parameters in `typeArgs` with their index in `typeArgs`, and
* - The `remaining` number of template arguments in `partiallyNormalizedSignature`
* with their index in `nameArgs`.
*/
private string getSignatureWithoutFunctionTemplateNames(
string partiallyNormalizedSignature, string typeArgs, string nameArgs, int remaining
) {
remaining = count(partiallyNormalizedSignature.indexOf(",")) + 1 and
result =
getSignatureWithoutClassTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs, 0)
or
exists(string mid |
mid =
getSignatureWithoutFunctionTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs,
remaining + 1)
|
exists(string nameArg |
nameArg = getAtIndex(nameArgs, remaining) and
result = mid.replaceAll(nameArg, "func:" + remaining.toString())
)
or
// Make sure `remaining` is properly bound
remaining = [0 .. count(partiallyNormalizedSignature.indexOf(",")) + 1] and
not exists(getAtIndex(nameArgs, remaining)) and
result = mid
)
}
private string paramsStringPart(Function c, int i) {
i = -1 and result = "(" and exists(c)
or
exists(int n, string p | c.getParameter(n).getType().toString() = p |
i = 2 * n and result = p
not c.isFromUninstantiatedTemplate(_) and
(
i = -1 and result = "(" and exists(c)
or
i = 2 * n - 1 and result = "," and n != 0
exists(int n, string p | getParameterTypeName(c, n) = p |
i = 2 * n and result = p
or
i = 2 * n - 1 and result = "," and n != 0
)
or
i = 2 * c.getNumberOfParameters() and result = ")"
)
or
i = 2 * c.getNumberOfParameters() and result = ")"
}
/**
@@ -396,6 +602,193 @@ private predicate matchesSignature(Function func, string signature) {
paramsString(func) = signature
}
/**
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
* - `typeArgs` represents the named template parameters supplied to `type`, and
* - `nameArgs` represents the named template parameters supplied to `name`, and
* - `normalizedSignature` is `signature`, except with
* - template parameter names replaced by `func:i` if the template name is
* the `i`'th entry in `nameArgs`, and
* - template parameter names replaced by `class:i` if the template name is
* the `i`'th entry in `typeArgs`.
*
* In other words, the string `normalizedSignature` represents a "normalized"
* signature with no mention of any free template parameters.
*
* For example, consider a summary row such as:
* ```
* elementSpec(_, "MyClass<B, C>", _, myFunc<A>, "(const A &,int,C,B *)", _)
* ```
* In this case, `normalizedSignature` will be `"(const func:0 &,int,class:1,class:0 *)"`.
*/
private predicate elementSpecWithArguments(
string signature, string type, string name, string normalizedSignature, string typeArgs,
string nameArgs
) {
exists(string signatureWithoutParens |
elementSpecWithArguments0(signature, type, name, signatureWithoutParens, typeArgs, nameArgs) and
normalizedSignature =
getSignatureWithoutFunctionTemplateNames(signatureWithoutParens, typeArgs, nameArgs, 0)
)
}
/** Gets the `n`'th normalized signature parameter for the function `name` in class `type`. */
private string getSignatureParameterName(string signature, string type, string name, int n) {
exists(string normalizedSignature |
elementSpecWithArguments(signature, type, name, normalizedSignature, _, _) and
result = getAtIndex(normalizedSignature, n)
)
}
/**
* Holds if the suffix containing the entries in `signature` starting at entry
* `i` matches the suffix containing the parameters of `func` starting at entry `i`.
*
* For example, consider the signature `(int,bool,char)` and a function:
* ```
* void f(int a, bool b, char c);
* ```
* 1. The predicate holds for `i = 2` because the suffix containing all the entries
* in `signature` starting at `2` is `char`, and suffix containing all the parameters
* of `func` starting at `2` is `char`.
* 2. The predicate holds for `i = 1` because the suffix containing all the entries
* in `signature` starting at `1` is `bool,char`, and the suffix containing all the
* parameters of `func` starting at `1` is `bool, char`.
* 3. The predicate holds for `i = 0` because the suffix containing all the entries
* in `signature` starting at `0` is `int,bool,char` and the suffix containing all
* the parameters of `func` starting at `0` is `int, bool, char`.
*
* When `paramsString(func)[i]` is `class:n` then the signature name is
* compared with the `n`'th name in `type`, and when `paramsString(func)[i]`
* is `func:n` then the signature name is compared with the `n`'th name
* in `name`.
*/
private predicate signatureMatches(Function func, string signature, string type, string name, int i) {
exists(string s |
s = getSignatureParameterName(signature, type, name, i) and
s = getParameterTypeName(func, i)
) and
if exists(getParameterTypeName(func, i + 1))
then signatureMatches(func, signature, type, name, i + 1)
else i = count(signature.indexOf(","))
}
/**
* Internal: Do not use.
*
* This module only exists to expose internal predicates for testing purposes.
*/
module ExternalFlowDebug {
/**
* INTERNAL: Do not use.
*
* Exposed for testing purposes.
*/
predicate signatureMatches_debug = signatureMatches/5;
/**
* INTERNAL: Do not use.
*
* Exposed for testing purposes.
*/
predicate getSignatureParameterName_debug = getSignatureParameterName/4;
/**
* INTERNAL: Do not use.
*
* Exposed for testing purposes.
*/
predicate getParameterTypeName_debug = getParameterTypeName/2;
}
/**
* Holds if `s` can be broken into a string of the form
* `beforeAngles<betweenAngles>`,
* or `s = beforeAngles` where `beforeAngles` does not have any brackets.
*/
bindingset[s]
pragma[inline_late]
private predicate parseAngles(
string s, string beforeAngles, string betweenAngles, string afterAngles
) {
beforeAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 1) and
(
betweenAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 2) and
afterAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 3)
or
not exists(s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 2)) and
betweenAngles = "" and
afterAngles = ""
)
}
/** Holds if `s` can be broken into a string of the form `(betweenParens)`. */
bindingset[s]
pragma[inline_late]
private predicate parseParens(string s, string betweenParens) { s = "(" + betweenParens + ")" }
/**
* Holds if `elementSpec(_, type, _, name, signature, _)` and:
* - `type` introduces template parameters `typeArgs`, and
* - `name` introduces template parameters `nameArgs`, and
* - `signatureWithoutParens` equals `signature`, but with the surrounding
* parentheses removed.
*/
private predicate elementSpecWithArguments0(
string signature, string type, string name, string signatureWithoutParens, string typeArgs,
string nameArgs
) {
elementSpec(_, type, _, name, signature, _) and
parseAngles(name, _, nameArgs, "") and
(
type = "" and typeArgs = ""
or
parseAngles(type, _, typeArgs, "")
) and
parseParens(signature, signatureWithoutParens)
}
/**
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
* `method`'s signature matches `signature`.
*
* `signature` may contain template parameter names that are bound by `type` and `name`.
*/
pragma[nomagic]
private predicate elementSpecMatchesSignature(
Function method, string namespace, string type, boolean subtypes, string name, string signature
) {
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
pragma[only_bind_into](signature), _) and
signatureMatches(method, signature, type, name, 0)
}
/**
* Holds if `classWithMethod` has `method` named `name` (excluding any
* template parameters).
*/
bindingset[name]
pragma[inline_late]
private predicate hasClassAndName(Class classWithMethod, Function method, string name) {
exists(string nameWithoutArgs |
parseAngles(name, nameWithoutArgs, _, "") and
classWithMethod = method.getClassAndName(nameWithoutArgs)
)
}
/**
* Holds if `namedClass` is in namespace `namespace` and has
* name `type` (excluding any template parameters).
*/
bindingset[type, namespace]
pragma[inline_late]
private predicate hasQualifiedName(Class namedClass, string namespace, string type) {
exists(string typeWithoutArgs |
parseAngles(type, typeWithoutArgs, _, "") and
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
)
}
/**
* Gets the element in module `namespace` that satisfies the following properties:
* 1. If the element is a member of a class-like type, then the class-like type has name `type`
@@ -410,8 +803,8 @@ pragma[nomagic]
private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature
) {
elementSpec(namespace, type, subtypes, name, signature, _) and
(
elementSpec(namespace, type, subtypes, name, signature, _) and
// Non-member functions
exists(Function func |
func.hasQualifiedName(namespace, name) and
@@ -423,21 +816,28 @@ private Element interpretElement0(
)
or
// Member functions
exists(Class namedClass, Class classWithMethod, Function method |
classWithMethod = method.getClassAndName(name) and
namedClass.hasQualifiedName(namespace, type) and
matchesSignature(method, signature) and
result = method
|
// member declared in the named type or a subtype of it
subtypes = true and
classWithMethod = namedClass.getADerivedClass*()
or
// member declared directly in the named type
subtypes = false and
classWithMethod = namedClass
exists(Class namedClass, Class classWithMethod |
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) and
hasClassAndName(classWithMethod, result, name)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
hasClassAndName(classWithMethod, result, name)
) and
hasQualifiedName(namedClass, namespace, type) and
(
// member declared in the named type or a subtype of it
subtypes = true and
classWithMethod = namedClass.getADerivedClass*()
or
// member declared directly in the named type
subtypes = false and
classWithMethod = namedClass
)
)
or
elementSpec(namespace, type, subtypes, name, signature, _) and
// Member variables
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
@@ -456,6 +856,7 @@ private Element interpretElement0(
)
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
subtypes = false and
@@ -480,9 +881,9 @@ private module Cached {
* model.
*/
cached
predicate sourceNode(DataFlow::Node node, string kind) {
predicate sourceNode(DataFlow::Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isSourceNode(n, kind, _) and n.asNode() = node // TODO
isSourceNode(n, kind, model) and n.asNode() = node
)
}
@@ -491,40 +892,57 @@ private module Cached {
* model.
*/
cached
predicate sinkNode(DataFlow::Node node, string kind) {
predicate sinkNode(DataFlow::Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isSinkNode(n, kind, _) and n.asNode() = node // TODO
isSinkNode(n, kind, model) and n.asNode() = node
)
}
}
import Cached
/**
* Holds if `node` is specified as a source with the given kind in a MaD flow
* model.
*/
predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind, _) }
/**
* Holds if `node` is specified as a sink with the given kind in a MaD flow
* model.
*/
predicate sinkNode(DataFlow::Node node, string kind) { sinkNode(node, kind, _) }
private predicate interpretSummary(
Function f, string input, string output, string kind, string provenance
Function f, string input, string output, string kind, string provenance, string model
) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance,
model) and
f = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _) }
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
private predicate relevantSummaryElementManual(string input, string output, string kind) {
private predicate relevantSummaryElementManual(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance) and
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isManual()
)
}
private predicate relevantSummaryElementGenerated(string input, string output, string kind) {
private predicate relevantSummaryElementGenerated(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance) and
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isGenerated()
)
}
@@ -533,18 +951,17 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
string input, string output, boolean preservesValue, string model
) {
exists(string kind |
this.relevantSummaryElementManual(input, output, kind)
this.relevantSummaryElementManual(input, output, kind, model)
or
not this.relevantSummaryElementManual(_, _, _) and
this.relevantSummaryElementGenerated(input, output, kind)
not this.relevantSummaryElementManual(_, _, _, _) and
this.relevantSummaryElementGenerated(input, output, kind, model)
|
if kind = "value" then preservesValue = true else preservesValue = false
) and
model = "" // TODO
)
}
override predicate hasProvenance(Provenance provenance) {
interpretSummary(this, _, _, _, provenance)
interpretSummary(this, _, _, _, provenance, _)
}
}

View File

@@ -215,25 +215,19 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
DataFlowType getNodeType(Node n) {
exists(n) and
result instanceof VoidType // stub implementation
}
/** Gets a string representation of a type returned by `getNodeType`. */
string ppReprType(Type t) { none() } // stub implementation
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(Type t1, Type t2) {
any() // stub implementation
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
//////////////////////////////////////////////////////////////////////////////
@@ -242,21 +236,15 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
class DataFlowCallable extends Function {
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
c order by file, startline, startcolumn
)
}
}
class DataFlowCallable extends Function { }
class DataFlowExpr = Expr;
class DataFlowType = Type;
final private class TypeFinal = Type;
class DataFlowType extends TypeFinal {
string toString() { result = "" }
}
/** A function call relevant for data flow. */
class DataFlowCall extends Expr instanceof Call {
@@ -272,24 +260,12 @@ class DataFlowCall extends Expr instanceof Call {
/** Gets the enclosing callable of this call. */
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCall c, int startline, int startcolumn |
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
c order by startline, startcolumn
)
}
}
class NodeRegion instanceof Unit {
string toString() { result = "NodeRegion" }
predicate contains(Node n) { none() }
int totalOrder() { result = 1 }
}
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation

View File

@@ -35,16 +35,22 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
result = "Field" and
arg = repeatStars(c.getIndirectionIndex() - 1) + c.getField().getName()
)
or
exists(ElementContent ec |
cs.isSingleton(ec) and
result = "Element" and
arg = repeatStars(ec.getIndirectionIndex() - 1)
)
}
string encodeWithoutContent(ContentSet c, string arg) {
// used for type tracking, not currently used in C/C++.
result = "WithoutContent" + c and arg = ""
none()
}
string encodeWithContent(ContentSet c, string arg) {
// used for type tracking, not currently used in C/C++.
result = "WithContent" + c and arg = ""
none()
}
/**
@@ -79,25 +85,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
token.getName() = "Parameter" and
result = decodePosition(token.getAnArgument())
}
bindingset[token]
ContentSet decodeUnknownContent(AccessPath::AccessPathTokenBase token) {
// field content (no indirection support)
exists(FieldContent c |
result.isSingleton(c) and
token.getName() = c.getField().getName() and
not exists(token.getArgumentList()) and
c.getIndirectionIndex() = 1
)
or
// field content (with indirection support)
exists(FieldContent c |
result.isSingleton(c) and
token.getName() = c.getField().getName() and
// FieldContent indices have 0 for the address, 1 for content, so we need to subtract one.
token.getAnArgument() = repeatStars(c.getIndirectionIndex() - 1)
)
}
}
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
@@ -125,9 +112,8 @@ module SourceSinkInterpretationInput implements
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
e = interpretElement(namespace, type, subtypes, name, signature, ext) and
model = "" // TODO
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
@@ -141,9 +127,8 @@ module SourceSinkInterpretationInput implements
exists(
string package, string type, boolean subtypes, string name, string signature, string ext
|
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
e = interpretElement(package, type, subtypes, name, signature, ext) and
model = "" // TODO
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, model) and
e = interpretElement(package, type, subtypes, name, signature, ext)
)
}

View File

@@ -383,6 +383,37 @@ class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertibleTo" }
}
/**
* A C++ `__is_convertible` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the first type can be converted to the second type.
* ```
* bool v = __is_convertible(MyType, OtherType);
* ```
*/
class BuiltInOperationIsConvertible extends BuiltInOperation, @isconvertible {
override string toString() { result = "__is_convertible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertible" }
}
/**
* A C++ `__is_nothrow_convertible` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the first type can be converted to the second type and the
* conversion operator has an empty exception specification.
* ```
* bool v = __is_nothrow_convertible(MyType, OtherType);
* ```
*/
class BuiltInOperationIsNothrowConvertible extends BuiltInOperation, @isnothrowconvertible {
override string toString() { result = "__is_nothrow_convertible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowConvertible" }
}
/**
* A C++ `__is_empty` built-in operation (used by some implementations of the
* `<type_traits>` header).
@@ -647,8 +678,7 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
* The `__is_nothrow_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d) nothrow`
* assignment operator (i.e, with an empty exception specification).
* Returns true if there exists an assignment operator with an empty exception specification.
* ```
* bool v = __is_nothrow_assignable(MyType1, MyType2);
* ```
@@ -663,8 +693,7 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
* The `__is_assignable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d)` assignment
* operator.
* Returns true if there exists an assignment operator.
* ```
* bool v = __is_assignable(MyType1, MyType2);
* ```
@@ -675,6 +704,25 @@ class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
}
/**
* The `__is_assignable_no_precondition_check` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if there exists an assignment operator.
* ```
* bool v = __is_assignable_no_precondition_check(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsAssignableNoPreconditionCheck extends BuiltInOperation,
@isassignablenopreconditioncheck
{
override string toString() { result = "__is_assignable_no_precondition_check" }
override string getAPrimaryQlClass() {
result = "BuiltInOperationIsAssignableNoPreconditionCheck"
}
}
/**
* The `__is_standard_layout` built-in operation (used by some implementations
* of the `<type_traits>` header).
@@ -708,6 +756,20 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyable" }
}
/**
* The `__is_trivially_copy_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if instances of this type can be copied using a trivial
* copy operator.
*/
class BuiltInOperationIsTriviallyCopyAssignable extends BuiltInOperation, @istriviallycopyassignable
{
override string toString() { result = "__is_trivially_copy_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyAssignable" }
}
/**
* The `__is_literal_type` built-in operation (used by some implementations of
* the `<type_traits>` header).
@@ -1062,6 +1124,24 @@ class BuiltInOperationIsSame extends BuiltInOperation, @issame {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSame" }
}
/**
* A C++ `__is_same_as` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if two types are the same.
* ```
* template<typename _Tp, typename _Up>
* struct is_same
* : public integral_constant<bool, __is_same_as(_Tp, _Up)>
* { };
* ```
*/
class BuiltInOperationIsSameAs extends BuiltInOperation, @issameas {
override string toString() { result = "__is_same_as" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSameAs" }
}
/**
* A C++ `__is_function` built-in operation (used by some implementations of the
* `<type_traits>` header).
@@ -1120,6 +1200,87 @@ class BuiltInOperationIsPointerInterconvertibleBaseOf extends BuiltInOperation,
}
}
/**
* A C++ `__is_pointer_interconvertible_with_class` built-in operation (used
* by some implementations of the `<type_traits>` header).
*
* Returns `true` if a member pointer is pointer-interconvertible with a
* class type.
* ```
* template<typename _Tp, typename _Up>
* constexpr bool is_pointer_interconvertible_with_class(_Up _Tp::*mp) noexcept
* = __is_pointer_interconvertible_with_class(_Tp, mp);
* ```
*/
class BuiltInOperationIsPointerInterconvertibleWithClass extends BuiltInOperation,
@ispointerinterconvertiblewithclass
{
override string toString() { result = "__is_pointer_interconvertible_with_class" }
override string getAPrimaryQlClass() {
result = "BuiltInOperationIsPointerInterconvertibleWithClass"
}
}
/**
* A C++ `__builtin_is_pointer_interconvertible_with_class` built-in operation (used
* by some implementations of the `<type_traits>` header).
*
* Returns `true` if a member pointer is pointer-interconvertible with a class type.
* ```
* template<typename _Tp, typename _Up>
* constexpr bool is_pointer_interconvertible_with_class(_Up _Tp::*mp) noexcept
* = __builtin_is_pointer_interconvertible_with_class(mp);
* ```
*/
class BuiltInOperationBuiltInIsPointerInterconvertible extends BuiltInOperation,
@builtinispointerinterconvertiblewithclass
{
override string toString() { result = "__builtin_is_pointer_interconvertible_with_class" }
override string getAPrimaryQlClass() {
result = "BuiltInOperationBuiltInIsPointerInterconvertible"
}
}
/**
* A C++ `__is_corresponding_member` built-in operation (used
* by some implementations of the `<type_traits>` header).
*
* Returns `true` if two member pointers refer to corresponding
* members in the initial sequences of two class types.
* ```
* template<typename _Tp1, typename _Tp2, typename _Up1, typename _Up2>
* constexpr bool is_corresponding_member(_Up1 _Tp1::*mp1, _Up2 _Tp2::*mp2 ) noexcept
* = __is_corresponding_member(_Tp1, _Tp2, mp1, mp2);
* ```
*/
class BuiltInOperationIsCorrespondingMember extends BuiltInOperation, @iscorrespondingmember {
override string toString() { result = "__is_corresponding_member" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsCorrespondingMember" }
}
/**
* A C++ `__builtin_is_corresponding_member` built-in operation (used
* by some implementations of the `<type_traits>` header).
*
* Returns `true` if two member pointers refer to corresponding
* members in the initial sequences of two class types.
* ```
* template<typename _Tp1, typename _Tp2, typename _Up1, typename _Up2>
* constexpr bool is_corresponding_member(_Up1 _Tp1::*mp1, _Up2 _Tp2::*mp2 ) noexcept
* = __builtin_is_corresponding_member(mp1, mp2);
* ```
*/
class BuiltInOperationBuiltInIsCorrespondingMember extends BuiltInOperation,
@builtiniscorrespondingmember
{
override string toString() { result = "__builtin_is_corresponding_member" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInIsCorrespondingMember" }
}
/**
* A C++ `__is_array` built-in operation (used by some implementations of the
* `<type_traits>` header).
@@ -1138,6 +1299,42 @@ class BuiltInOperationIsArray extends BuiltInOperation, @isarray {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsArray" }
}
/**
* A C++ `__is_bounded_array` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a type is a bounded array type.
* ```
* template<typename _Tp>
* struct is_bounded_array
* : public integral_constant<bool, __is_bounded_array(_Tp)>
* { };
* ```
*/
class BuiltInOperationIsBoundedArray extends BuiltInOperation, @isboundedarray {
override string toString() { result = "__is_bounded_array" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsBoundedArray" }
}
/**
* A C++ `__is_unbounded_array` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a type is an unbounded array type.
* ```
* template<typename _Tp>
* struct is_bounded_array
* : public integral_constant<bool, __is_unbounded_array(_Tp)>
* { };
* ```
*/
class BuiltInOperationIsUnboundedArray extends BuiltInOperation, @isunboundedarray {
override string toString() { result = "__is_unbounded_array" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnboundedArray" }
}
/**
* A C++ `__array_rank` built-in operation (used by some implementations of the
* `<type_traits>` header).
@@ -1554,10 +1751,10 @@ class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
*
* Returns `true` if a type is a trivial type.
* ```
* template<typename _Tp>
* struct is_trivial
* : public integral_constant<bool, __is_trivial(_Tp)>
* {};
* template<typename _Tp>
* struct is_trivial
* : public integral_constant<bool, __is_trivial(_Tp)>
* {};
* ```
*/
class BuiltInIsTrivial extends BuiltInOperation, @istrivialexpr {
@@ -1565,3 +1762,126 @@ class BuiltInIsTrivial extends BuiltInOperation, @istrivialexpr {
override string getAPrimaryQlClass() { result = "BuiltInIsTrivial" }
}
/**
* A C++ `__reference_constructs_from_temporary` built-in operation
* (used by some implementations of the `<type_traits>` header).
*
* Returns `true` if a reference type `_Tp` is bound to an expression of
* type `_Up` in direct-initialization, and a temporary object is bound.
* ```
* template<typename _Tp, typename _Up>
* struct reference_constructs_from_temporary
* : public integral_constant<bool, __reference_constructs_from_temporary(_Tp, _Up)>
* {};
* ```
*/
class BuiltInOperationReferenceConstructsFromTemporary extends BuiltInOperation,
@referenceconstructsfromtemporary
{
override string toString() { result = "__reference_constructs_from_temporary" }
override string getAPrimaryQlClass() {
result = "BuiltInOperationReferenceConstructsFromTemporary"
}
}
/**
* A C++ `__reference_converts_from_temporary` built-in operation
* (used by some implementations of the `<type_traits>` header).
*
* Returns `true` if a reference type `_Tp` is bound to an expression of
* type `_Up` in copy-initialization, and a temporary object is bound.
* ```
* template<typename _Tp, typename _Up>
* struct reference_converts_from_temporary
* : public integral_constant<bool, __reference_converts_from_temporary(_Tp, _Up)>
* {};
* ```
*/
class BuiltInOperationReferenceCovertsFromTemporary extends BuiltInOperation,
@referenceconvertsfromtemporary
{
override string toString() { result = "__reference_converts_from_temporary" }
override string getAPrimaryQlClass() { result = "BuiltInOperationReferenceCovertsFromTemporary" }
}
/**
* A C++ `__reference_binds_to_temporary` built-in operation (used by some
* implementations of the `<tuple>` header).
*
* Returns `true` if a reference of type `Type1` is bound to an expression of
* type `Type1`, and a temporary object is bound.
* ```
* __reference_binds_to_temporary(Type1, Type2)
*/
class BuiltInOperationReferenceBindsToTemporary extends BuiltInOperation, @referencebindstotemporary
{
override string toString() { result = "__reference_binds_to_temporary" }
override string getAPrimaryQlClass() { result = "BuiltInOperationReferenceBindsToTemporary" }
}
/**
* A C++ `__builtin_has_attribute` built-in operation.
*
* Returns `true` if a type or expression has been declared with the
* specified attribute.
* ```
* __attribute__ ((aligned(8))) int v;
* bool has_attribute = __builtin_has_attribute(v, aligned);
* ```
*/
class BuiltInOperationHasAttribute extends BuiltInOperation, @builtinhasattribute {
override string toString() { result = "__builtin_has_attribute" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasAttribute" }
}
/**
* A C++ `__is_referenceable` built-in operation.
*
* Returns `true` if a type can be referenced.
* ```
* bool is_referenceable = __is_referenceable(int);
* ```
*/
class BuiltInOperationIsReferenceable extends BuiltInOperation, @isreferenceable {
override string toString() { result = "__is_referenceable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsReferenceable" }
}
/**
* The `__is_valid_winrt_type` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type is a valid WinRT type.
*/
class BuiltInOperationIsValidWinRtType extends BuiltInOperation, @isvalidwinrttype {
override string toString() { result = "__is_valid_winrt_type" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsValidWinRtType" }
}
/**
* The `__is_win_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the class is a ref class.
*/
class BuiltInOperationIsWinClass extends BuiltInOperation, @iswinclass {
override string toString() { result = "__is_win_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinClass" }
}
/**
* The `__is_win_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the class is an interface class.
*/
class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
override string toString() { result = "__is_win_interface" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
}

View File

@@ -855,6 +855,16 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
)
}
/**
* Holds if the deallocation function is a destroying delete.
*/
predicate isDestroyingDeleteDeallocation() {
exists(int form |
expr_deallocator(underlyingElement(this), _, form) and
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
)
}
/**
* Gets the type that is being allocated.
*
@@ -949,6 +959,16 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
* gives nothing, as the 10 is considered part of the type.
*/
Expr getExtent() { result = this.getChild(2) }
/**
* Gets the number of elements in the array, if available.
*
* For example, `new int[]{1,2,3}` has an array size of 3.
*/
int getArraySize() {
result = this.getAllocatedType().(ArrayType).getArraySize() or
result = this.getInitializer().(ArrayAggregateLiteral).getArraySize()
}
}
private class TDeleteOrDeleteArrayExpr = @delete_expr or @delete_array_expr;
@@ -1015,6 +1035,16 @@ class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
)
}
/**
* Holds if the deallocation function is a destroying delete.
*/
predicate isDestroyingDeleteDeallocation() {
exists(int form |
expr_deallocator(underlyingElement(this), _, form) and
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
)
}
/**
* Gets the object or array being deleted.
*/

View File

@@ -11,6 +11,7 @@ private import Node0ToString
private import ModelUtil
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
private import semmle.code.cpp.models.interfaces.DataFlow as DF
private import semmle.code.cpp.dataflow.ExternalFlow as External
cached
private module Cached {
@@ -412,6 +413,8 @@ class ArgumentPosition = Position;
abstract class Position extends TPosition {
abstract string toString();
abstract int getIndirectionIndex();
}
class DirectPosition extends Position, TDirectPosition {
@@ -421,13 +424,15 @@ class DirectPosition extends Position, TDirectPosition {
override string toString() {
index = -1 and
result = "this"
result = "this pointer"
or
index != -1 and
result = index.toString()
}
int getIndex() { result = index }
final override int getIndirectionIndex() { result = 0 }
}
class IndirectionPosition extends Position, TIndirectionPosition {
@@ -438,16 +443,13 @@ class IndirectionPosition extends Position, TIndirectionPosition {
override string toString() {
if argumentIndex = -1
then if indirectionIndex > 0 then result = "this indirection" else result = "this"
else
if indirectionIndex > 0
then result = argumentIndex.toString() + " indirection"
else result = argumentIndex.toString()
then result = repeatStars(indirectionIndex - 1) + "this"
else result = repeatStars(indirectionIndex) + argumentIndex.toString()
}
int getArgumentIndex() { result = argumentIndex }
int getIndirectionIndex() { result = indirectionIndex }
final override int getIndirectionIndex() { result = indirectionIndex }
}
newtype TPosition =
@@ -988,24 +990,18 @@ predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(Node n) {
suppressUnusedNode(n) and
exists(n) and
result instanceof VoidType // stub implementation
}
/** Gets a string representation of a type returned by `getNodeType`. */
string ppReprType(DataFlowType t) { none() } // stub implementation
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
any() // stub implementation
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
//////////////////////////////////////////////////////////////////////////////
@@ -1062,16 +1058,6 @@ class DataFlowCallable extends TDataFlowCallable {
result = this.asSummarizedCallable() or // SummarizedCallable = Function (in CPP)
result = this.asSourceCallable()
}
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
c order by file, startline, startcolumn
)
}
}
/**
@@ -1108,7 +1094,11 @@ class SummarizedCallable extends DataFlowCallable, TSummarizedCallable {
class DataFlowExpr = Expr;
class DataFlowType = Type;
final private class TypeFinal = Type;
class DataFlowType extends TypeFinal {
string toString() { result = "" }
}
cached
private newtype TDataFlowCall =
@@ -1169,16 +1159,6 @@ class DataFlowCall extends TDataFlowCall {
* Gets the location of this call.
*/
Location getLocation() { none() }
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCall c, int startline, int startcolumn |
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
c order by startline, startcolumn
)
}
}
/**
@@ -1271,15 +1251,6 @@ module IsUnreachableInCall {
string toString() { result = "NodeRegion" }
predicate contains(Node n) { this = n.getBasicBlock() }
int totalOrder() {
this =
rank[result](IRBlock b, int startline, int startcolumn |
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
b order by startline, startcolumn
)
}
}
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
@@ -1325,7 +1296,7 @@ import IsUnreachableInCall
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { none() }
predicate forceHighPrecision(Content c) { c instanceof ElementContent }
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
@@ -1364,9 +1335,9 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
predicate knownSourceModel(Node source, string model) { none() }
predicate knownSourceModel(Node source, string model) { External::sourceNode(source, _, model) }
predicate knownSinkModel(Node sink, string model) { none() }
predicate knownSinkModel(Node sink, string model) { External::sinkNode(sink, _, model) }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
@@ -1396,7 +1367,8 @@ private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().c
cached
private newtype TContentApprox =
TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or
TUnionApproxContent(string s) { unionHasApproxName(_, s) }
TUnionApproxContent(string s) { unionHasApproxName(_, s) } or
TElementApproxContent()
/** An approximated `Content`. */
class ContentApprox extends TContentApprox {
@@ -1427,6 +1399,10 @@ private class UnionApproxContent extends ContentApprox, TUnionApproxContent {
final override string toString() { result = s }
}
private class ElementApproxContent extends ContentApprox, TElementApproxContent {
final override string toString() { result = "ElementApprox" }
}
/** Gets an approximated value for content `c`. */
pragma[inline]
ContentApprox getContentApprox(Content c) {
@@ -1441,6 +1417,9 @@ ContentApprox getContentApprox(Content c) {
u = c.(UnionContent).getUnion() and
unionHasApproxName(u, prefix)
)
or
c instanceof ElementContent and
result instanceof ElementApproxContent
}
/**
@@ -1700,6 +1679,14 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
/** Gets the second-level scope containing the node `n`, if any. */
DataFlowSecondLevelScope getSecondLevelScope(Node n) { result.getANode() = n }
/**
* Gets the maximum number of indirections to use for `ElementContent`.
*
* This should be equal to the largest number of stars (i.e., `*`s) in any
* `Element` content across all of our MaD summaries, sources, and sinks.
*/
int getMaxElementContentIndirectionIndex() { result = 5 }
/**
* Module that defines flow through iterators.
* For example,
@@ -1812,7 +1799,7 @@ module IteratorFlow {
* Holds if `(bb, i)` contains a write to an iterator that may have been obtained
* by calling `begin` (or related functions) on the variable `v`.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
certain = false and
exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
isIteratorStoreInstruction(beginCall, writeToDeref) and
@@ -1823,7 +1810,7 @@ module IteratorFlow {
}
/** Holds if `(bb, i)` reads the container variable `v`. */
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
Ssa::variableRead(bb, i, v, certain)
}
}

View File

@@ -17,6 +17,7 @@ private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
import ExprNodes
/**
* The IR dataflow graph consists of the following nodes:
@@ -1296,466 +1297,6 @@ class UninitializedNode extends Node {
LocalVariable getLocalVariable() { result = v }
}
private module GetConvertedResultExpression {
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
private Operand getAnInitializeDynamicAllocationInstructionAddress() {
result = any(InitializeDynamicAllocationInstruction init).getAllocationAddressOperand()
}
/**
* Gets the expression that should be returned as the result expression from `instr`.
*
* Note that this predicate may return multiple results in cases where a conversion belongs to a
* different AST element than its operand.
*/
Expr getConvertedResultExpression(Instruction instr, int n) {
// Only fully converted instructions have a result for `asConvertedExpr`
not conversionFlow(unique(Operand op |
// The address operand of a `InitializeDynamicAllocationInstruction` is
// special: we need to handle it during dataflow (since it's
// effectively a store to an indirection), but it doesn't appear in
// source syntax, so dataflow node <-> expression conversion shouldn't
// care about it.
op = getAUse(instr) and not op = getAnInitializeDynamicAllocationInstructionAddress()
|
op
), _, false, false) and
result = getConvertedResultExpressionImpl(instr) and
n = 0
or
// If the conversion also has a result then we return multiple results
exists(Operand operand | conversionFlow(operand, instr, false, false) |
n = 1 and
result = getConvertedResultExpressionImpl(operand.getDef())
or
result = getConvertedResultExpression(operand.getDef(), n - 1)
)
}
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
// IR construction inserts an additional cast to a `size_t` on the extent
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
// a result for `getConvertedResultExpression`. We remap this here so that
// this `ConvertInstruction` maps to the result of the expression that
// represents the extent.
exists(TranslatedNonConstantAllocationSize tas |
result = tas.getExtent().getExpr() and
instr = tas.getInstruction(AllocationExtentConvertTag())
)
or
// There's no instruction that returns `ParenthesisExpr`, but some queries
// expect this
exists(TranslatedTransparentConversion ttc |
result = ttc.getExpr().(ParenthesisExpr) and
instr = ttc.getResult()
)
or
// Certain expressions generate `CopyValueInstruction`s only when they
// are needed. Examples of this include crement operations and compound
// assignment operations. For example:
// ```cpp
// int x = ...
// int y = x++;
// ```
// this generate IR like:
// ```
// r1(glval<int>) = VariableAddress[x] :
// r2(int) = Constant[0] :
// m3(int) = Store[x] : &:r1, r2
// r4(glval<int>) = VariableAddress[y] :
// r5(glval<int>) = VariableAddress[x] :
// r6(int) = Load[x] : &:r5, m3
// r7(int) = Constant[1] :
// r8(int) = Add : r6, r7
// m9(int) = Store[x] : &:r5, r8
// r11(int) = CopyValue : r6
// m12(int) = Store[y] : &:r4, r11
// ```
// When the `CopyValueInstruction` is not generated there is no instruction
// whose `getConvertedResultExpression` maps back to the expression. When
// such an instruction doesn't exist it means that the old value is not
// needed, and in that case the only value that will propagate forward in
// the program is the value that's been updated. So in those cases we just
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
exists(TranslatedCoreExpr tco |
tco.getInstruction(_) = instr and
tco.producesExprResult() and
result = asDefinitionImpl0(instr)
)
}
private Expr getConvertedResultExpressionImpl(Instruction instr) {
result = getConvertedResultExpressionImpl0(instr)
or
not exists(getConvertedResultExpressionImpl0(instr)) and
result = instr.getConvertedResultExpression()
}
/**
* Gets the result for `node.asDefinition()` (when `node` is the instruction
* node that wraps `store`) in the cases where `store.getAst()` should not be
* used to define the result of `node.asDefinition()`.
*/
private Expr asDefinitionImpl0(StoreInstruction store) {
// For an expression such as `i += 2` we pretend that the generated
// `StoreInstruction` contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedAssignOperation tao |
store = tao.getInstruction(AssignmentStoreTag()) and
result = tao.getExpr()
)
or
// Similarly for `i++` and `++i` we pretend that the generated
// `StoreInstruction` is contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedCrementOperation tco |
store = tco.getInstruction(CrementStoreTag()) and
result = tco.getExpr()
)
}
/**
* Holds if the expression returned by `store.getAst()` should not be
* returned as the result of `node.asDefinition()` when `node` is the
* instruction node that wraps `store`.
*/
private predicate excludeAsDefinitionResult(StoreInstruction store) {
// Exclude the store to the temporary generated by a ternary expression.
exists(TranslatedConditionalExpr tce |
store = tce.getInstruction(ConditionValueFalseStoreTag())
or
store = tce.getInstruction(ConditionValueTrueStoreTag())
)
}
/**
* Gets the expression that represents the result of `StoreInstruction` for
* dataflow purposes.
*
* For example, consider the following example
* ```cpp
* int x = 42; // 1
* x = 34; // 2
* ++x; // 3
* x++; // 4
* x += 1; // 5
* int y = x += 2; // 6
* ```
* For (1) the result is `42`.
* For (2) the result is `x = 34`.
* For (3) the result is `++x`.
* For (4) the result is `x++`.
* For (5) the result is `x += 1`.
* For (6) there are two results:
* - For the `StoreInstruction` generated by `x += 2` the result
* is `x += 2`
* - For the `StoreInstruction` generated by `int y = ...` the result
* is also `x += 2`
*/
Expr asDefinitionImpl(StoreInstruction store) {
not exists(asDefinitionImpl0(store)) and
not excludeAsDefinitionResult(store) and
result = store.getAst().(Expr).getUnconverted()
or
result = asDefinitionImpl0(store)
}
}
private import GetConvertedResultExpression
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
not exprNodeShouldBeIndirectOperand(_, e, n) and
exists(Instruction def |
unique( | | getAUse(def)) = node.getOperand() and
e = getConvertedResultExpression(def, n)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
private predicate indirectExprNodeShouldBeIndirectOperand(
IndirectOperand node, Expr e, int n, int indirectionIndex
) {
exists(Instruction def |
node.hasOperandAndIndirectionIndex(unique( | | getAUse(def)), indirectionIndex) and
e = getConvertedResultExpression(def, n)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
exists(ArgumentOperand operand |
// When an argument (qualifier or positional) is a prvalue and the
// parameter (qualifier or positional) is a (const) reference, IR
// construction introduces a temporary `IRVariable`. The `VariableAddress`
// instruction has the argument as its `getConvertedResultExpression`
// result. However, the instruction actually represents the _address_ of
// the argument. So to fix this mismatch, we have the indirection of the
// `VariableAddressInstruction` map to the expression.
node.hasOperandAndIndirectionIndex(operand, 1) and
e = getConvertedResultExpression(operand.getDef(), n) and
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
)
}
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
exists(CallInstruction call |
call.getStaticCallTarget() instanceof Constructor and
e = getConvertedResultExpression(call, n) and
call.getThisArgumentOperand() = node.getAddressOperand()
)
}
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
not exprNodeShouldBeOperand(_, e, n) and
not exprNodeShouldBeIndirectOutNode(_, e, n) and
not exprNodeShouldBeIndirectOperand(_, e, n) and
e = getConvertedResultExpression(node.asInstruction(), n)
}
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
predicate indirectExprNodeShouldBeIndirectInstruction(
IndirectInstruction node, Expr e, int n, int indirectionIndex
) {
not indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) and
exists(Instruction instr |
node.hasInstructionAndIndirectionIndex(instr, indirectionIndex) and
e = getConvertedResultExpression(instr, n)
)
}
abstract private class ExprNodeBase extends Node {
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr(int n);
/** Gets the non-conversion expression corresponding to this node, if any. */
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
}
/**
* Holds if there exists a dataflow node whose `asExpr(n)` should evaluate
* to `e`.
*/
private predicate exprNodeShouldBe(Expr e, int n) {
exprNodeShouldBeInstruction(_, e, n) or
exprNodeShouldBeOperand(_, e, n) or
exprNodeShouldBeIndirectOutNode(_, e, n) or
exprNodeShouldBeIndirectOperand(_, e, n)
}
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
InstructionExprNode() {
exists(Expr e, int n |
exprNodeShouldBeInstruction(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
)
}
final override Expr getConvertedExpr(int n) { exprNodeShouldBeInstruction(this, result, n) }
}
private class OperandExprNode extends ExprNodeBase, OperandNode {
OperandExprNode() {
exists(Expr e, int n |
exprNodeShouldBeOperand(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
)
}
final override Expr getConvertedExpr(int n) { exprNodeShouldBeOperand(this, result, n) }
}
abstract private class IndirectExprNodeBase extends Node {
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr(int n, int indirectionIndex);
/** Gets the non-conversion expression corresponding to this node, if any. */
final Expr getExpr(int n, int indirectionIndex) {
result = this.getConvertedExpr(n, indirectionIndex).getUnconverted()
}
}
/** A signature for converting an indirect node to an expression. */
private signature module IndirectNodeToIndirectExprSig {
/** The indirect node class to be converted to an expression */
class IndirectNode;
/**
* Holds if the indirect expression at indirection index `indirectionIndex`
* of `node` is `e`. The integer `n` specifies how many conversions has been
* applied to `node`.
*/
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
}
/**
* A module that implements the logic for deciding whether an indirect node
* should be an `IndirectExprNode`.
*/
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
import Sig
/**
* This predicate shifts the indirection index by one when `conv` is a
* `ReferenceDereferenceExpr`.
*
* This is necessary because `ReferenceDereferenceExpr` is a conversion
* in the AST, but appears as a `LoadInstruction` in the IR.
*/
bindingset[e, indirectionIndex]
private predicate adjustForReference(
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
) {
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1
or
not conv instanceof ReferenceDereferenceExpr and
conv = e and
adjustedIndirectionIndex = indirectionIndex
}
/** Holds if `node` should be an `IndirectExprNode`. */
predicate charpred(IndirectNode node) {
exists(Expr e, int n, int indirectionIndex |
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
)
)
}
}
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
}
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
}
module IndirectOperandToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectInstruction;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
}
module IndirectInstructionToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode {
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _, _) }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
}
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
class ExprNode extends Node instanceof ExprNodeBase {
/**
* INTERNAL: Do not use.
*/
Expr getExpr(int n) { result = super.getExpr(n) }
/**
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
final Expr getExpr() { result = this.getExpr(_) }
/**
* INTERNAL: Do not use.
*/
Expr getConvertedExpr(int n) { result = super.getConvertedExpr(n) }
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
final Expr getConvertedExpr() { result = this.getConvertedExpr(_) }
}
/**
* An indirect expression, viewed as a node in a data flow graph.
*/
class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
/**
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
final Expr getExpr(int indirectionIndex) { result = this.getExpr(_, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
Expr getExpr(int n, int indirectionIndex) { result = super.getExpr(n, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
Expr getConvertedExpr(int n, int indirectionIndex) {
result = super.getConvertedExpr(n, indirectionIndex)
}
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
Expr getConvertedExpr(int indirectionIndex) {
result = this.getConvertedExpr(_, indirectionIndex)
}
}
abstract private class AbstractParameterNode extends Node {
/**
* Holds if this node is the parameter of `f` at the specified position. The
@@ -2542,6 +2083,9 @@ private newtype TContent =
indirectionIndex =
[1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))]
)
} or
TElementContent(int indirectionIndex) {
indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()]
}
/**
@@ -2652,6 +2196,25 @@ class UnionContent extends Content, TUnionContent {
}
}
/**
* A `Content` that represents one of the elements of a
* container (e.g., `std::vector`).
*/
class ElementContent extends Content, TElementContent {
int indirectionIndex;
ElementContent() { this = TElementContent(indirectionIndex) }
pragma[inline]
override int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) { none() }
override string toString() { result = contentStars(this) + "element" }
}
/**
* An entity that represents a set of `Content`s.
*

View File

@@ -0,0 +1,518 @@
/**
* Provides the classes `ExprNode` and `IndirectExprNode` for converting between `Expr` and `Node`.
*/
private import cpp
private import semmle.code.cpp.ir.IR
private import DataFlowUtil
private import DataFlowPrivate
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
cached
private module Cached {
private Operand getAnInitializeDynamicAllocationInstructionAddress() {
result = any(InitializeDynamicAllocationInstruction init).getAllocationAddressOperand()
}
/**
* Gets the expression that should be returned as the result expression from `instr`.
*
* Note that this predicate may return multiple results in cases where a conversion belongs to a
* different AST element than its operand.
*/
private Expr getConvertedResultExpression(Instruction instr, int n) {
// Only fully converted instructions have a result for `asConvertedExpr`
not conversionFlow(unique(Operand op |
// The address operand of a `InitializeDynamicAllocationInstruction` is
// special: we need to handle it during dataflow (since it's
// effectively a store to an indirection), but it doesn't appear in
// source syntax, so dataflow node <-> expression conversion shouldn't
// care about it.
op = getAUse(instr) and not op = getAnInitializeDynamicAllocationInstructionAddress()
|
op
), _, false, false) and
result = getConvertedResultExpressionImpl(instr) and
n = 0
or
// If the conversion also has a result then we return multiple results
exists(Operand operand | conversionFlow(operand, instr, false, false) |
n = 1 and
result = getConvertedResultExpressionImpl(operand.getDef())
or
result = getConvertedResultExpression(operand.getDef(), n - 1)
)
}
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
// IR construction inserts an additional cast to a `size_t` on the extent
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
// a result for `getConvertedResultExpression`. We remap this here so that
// this `ConvertInstruction` maps to the result of the expression that
// represents the extent.
exists(TranslatedNonConstantAllocationSize tas |
result = tas.getExtent().getExpr() and
instr = tas.getInstruction(AllocationExtentConvertTag())
)
or
// There's no instruction that returns `ParenthesisExpr`, but some queries
// expect this
exists(TranslatedTransparentConversion ttc |
result = ttc.getExpr().(ParenthesisExpr) and
instr = ttc.getResult()
)
or
// Certain expressions generate `CopyValueInstruction`s only when they
// are needed. Examples of this include crement operations and compound
// assignment operations. For example:
// ```cpp
// int x = ...
// int y = x++;
// ```
// this generate IR like:
// ```
// r1(glval<int>) = VariableAddress[x] :
// r2(int) = Constant[0] :
// m3(int) = Store[x] : &:r1, r2
// r4(glval<int>) = VariableAddress[y] :
// r5(glval<int>) = VariableAddress[x] :
// r6(int) = Load[x] : &:r5, m3
// r7(int) = Constant[1] :
// r8(int) = Add : r6, r7
// m9(int) = Store[x] : &:r5, r8
// r11(int) = CopyValue : r6
// m12(int) = Store[y] : &:r4, r11
// ```
// When the `CopyValueInstruction` is not generated there is no instruction
// whose `getConvertedResultExpression` maps back to the expression. When
// such an instruction doesn't exist it means that the old value is not
// needed, and in that case the only value that will propagate forward in
// the program is the value that's been updated. So in those cases we just
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
exists(TranslatedCoreExpr tco |
tco.getInstruction(_) = instr and
tco.producesExprResult() and
result = asDefinitionImpl0(instr)
)
}
private Expr getConvertedResultExpressionImpl(Instruction instr) {
result = getConvertedResultExpressionImpl0(instr)
or
not exists(getConvertedResultExpressionImpl0(instr)) and
result = instr.getConvertedResultExpression()
}
/**
* Gets the result for `node.asDefinition()` (when `node` is the instruction
* node that wraps `store`) in the cases where `store.getAst()` should not be
* used to define the result of `node.asDefinition()`.
*/
private Expr asDefinitionImpl0(StoreInstruction store) {
// For an expression such as `i += 2` we pretend that the generated
// `StoreInstruction` contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedAssignOperation tao |
store = tao.getInstruction(AssignmentStoreTag()) and
result = tao.getExpr()
)
or
// Similarly for `i++` and `++i` we pretend that the generated
// `StoreInstruction` is contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedCrementOperation tco |
store = tco.getInstruction(CrementStoreTag()) and
result = tco.getExpr()
)
}
/**
* Holds if the expression returned by `store.getAst()` should not be
* returned as the result of `node.asDefinition()` when `node` is the
* instruction node that wraps `store`.
*/
private predicate excludeAsDefinitionResult(StoreInstruction store) {
// Exclude the store to the temporary generated by a ternary expression.
exists(TranslatedConditionalExpr tce |
store = tce.getInstruction(ConditionValueFalseStoreTag())
or
store = tce.getInstruction(ConditionValueTrueStoreTag())
)
}
/**
* Gets the expression that represents the result of `StoreInstruction` for
* dataflow purposes.
*
* For example, consider the following example
* ```cpp
* int x = 42; // 1
* x = 34; // 2
* ++x; // 3
* x++; // 4
* x += 1; // 5
* int y = x += 2; // 6
* ```
* For (1) the result is `42`.
* For (2) the result is `x = 34`.
* For (3) the result is `++x`.
* For (4) the result is `x++`.
* For (5) the result is `x += 1`.
* For (6) there are two results:
* - For the `StoreInstruction` generated by `x += 2` the result
* is `x += 2`
* - For the `StoreInstruction` generated by `int y = ...` the result
* is also `x += 2`
*/
cached
Expr asDefinitionImpl(StoreInstruction store) {
not exists(asDefinitionImpl0(store)) and
not excludeAsDefinitionResult(store) and
result = store.getAst().(Expr).getUnconverted()
or
result = asDefinitionImpl0(store)
}
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
not exprNodeShouldBeIndirectOperand(_, e, n) and
exists(Instruction def |
unique( | | getAUse(def)) = node.getOperand() and
e = getConvertedResultExpression(def, n)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
private predicate indirectExprNodeShouldBeIndirectOperand(
IndirectOperand node, Expr e, int n, int indirectionIndex
) {
exists(Instruction def |
node.hasOperandAndIndirectionIndex(unique( | | getAUse(def)), indirectionIndex) and
e = getConvertedResultExpression(def, n)
)
}
/** Holds if `operand`'s definition is a `VariableAddressInstruction` whose variable is a temporary */
private predicate isIRTempVariable(Operand operand) {
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
}
/**
* Holds if `node` is an indirect operand whose operand is an argument, and
* the `n`'th expression associated with the operand is `e`.
*/
private predicate isIndirectOperandOfArgument(
IndirectOperand node, ArgumentOperand operand, Expr e, int n
) {
node.hasOperandAndIndirectionIndex(operand, 1) and
e = getConvertedResultExpression(operand.getDef(), n)
}
/**
* Holds if `opFrom` is an operand to a conversion, and `opTo` is the unique
* use of the conversion.
*/
private predicate isConversionStep(Operand opFrom, Operand opTo) {
exists(Instruction mid |
conversionFlow(opFrom, mid, false, false) and
opTo = unique( | | getAUse(mid))
)
}
/**
* Holds if an operand that satisfies `isIRTempVariable` flows to `op`
* through a (possibly empty) sequence of conversions.
*/
private predicate irTempOperandConversionFlows(Operand op) {
isIRTempVariable(op)
or
exists(Operand mid |
irTempOperandConversionFlows(mid) and
isConversionStep(mid, op)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
exists(ArgumentOperand operand |
// When an argument (qualifier or positional) is a prvalue and the
// parameter (qualifier or positional) is a (const) reference, IR
// construction introduces a temporary `IRVariable`. The `VariableAddress`
// instruction has the argument as its `getConvertedResultExpression`
// result. However, the instruction actually represents the _address_ of
// the argument. So to fix this mismatch, we have the indirection of the
// `VariableAddressInstruction` map to the expression.
isIndirectOperandOfArgument(node, operand, e, n) and
irTempOperandConversionFlows(operand)
)
}
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
exists(CallInstruction call |
call.getStaticCallTarget() instanceof Constructor and
e = getConvertedResultExpression(call, n) and
call.getThisArgumentOperand() = node.getAddressOperand()
)
}
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
not exprNodeShouldBeOperand(_, e, n) and
not exprNodeShouldBeIndirectOutNode(_, e, n) and
not exprNodeShouldBeIndirectOperand(_, e, n) and
e = getConvertedResultExpression(node.asInstruction(), n)
}
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
private predicate indirectExprNodeShouldBeIndirectInstruction(
IndirectInstruction node, Expr e, int n, int indirectionIndex
) {
not indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) and
exists(Instruction instr |
node.hasInstructionAndIndirectionIndex(instr, indirectionIndex) and
e = getConvertedResultExpression(instr, n)
)
}
abstract private class ExprNodeBase extends Node {
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr(int n);
/** Gets the non-conversion expression corresponding to this node, if any. */
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
}
/**
* Holds if there exists a dataflow node whose `asExpr(n)` should evaluate
* to `e`.
*/
private predicate exprNodeShouldBe(Expr e, int n) {
exprNodeShouldBeInstruction(_, e, n) or
exprNodeShouldBeOperand(_, e, n) or
exprNodeShouldBeIndirectOutNode(_, e, n) or
exprNodeShouldBeIndirectOperand(_, e, n)
}
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
InstructionExprNode() {
exists(Expr e, int n |
exprNodeShouldBeInstruction(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
)
}
final override Expr getConvertedExpr(int n) { exprNodeShouldBeInstruction(this, result, n) }
}
private class OperandExprNode extends ExprNodeBase, OperandNode {
OperandExprNode() {
exists(Expr e, int n |
exprNodeShouldBeOperand(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
)
}
final override Expr getConvertedExpr(int n) { exprNodeShouldBeOperand(this, result, n) }
}
abstract private class IndirectExprNodeBase extends Node {
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr(int n, int indirectionIndex);
/** Gets the non-conversion expression corresponding to this node, if any. */
final Expr getExpr(int n, int indirectionIndex) {
result = this.getConvertedExpr(n, indirectionIndex).getUnconverted()
}
}
/** A signature for converting an indirect node to an expression. */
private signature module IndirectNodeToIndirectExprSig {
/** The indirect node class to be converted to an expression */
class IndirectNode;
/**
* Holds if the indirect expression at indirection index `indirectionIndex`
* of `node` is `e`. The integer `n` specifies how many conversions has been
* applied to `node`.
*/
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
}
/**
* A module that implements the logic for deciding whether an indirect node
* should be an `IndirectExprNode`.
*/
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
import Sig
/**
* This predicate shifts the indirection index by one when `conv` is a
* `ReferenceDereferenceExpr`.
*
* This is necessary because `ReferenceDereferenceExpr` is a conversion
* in the AST, but appears as a `LoadInstruction` in the IR.
*/
bindingset[e, indirectionIndex]
private predicate adjustForReference(
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
) {
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1
or
not conv instanceof ReferenceDereferenceExpr and
conv = e and
adjustedIndirectionIndex = indirectionIndex
}
/** Holds if `node` should be an `IndirectExprNode`. */
predicate charpred(IndirectNode node) {
exists(Expr e, int n, int indirectionIndex |
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
)
)
}
}
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
}
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
}
module IndirectOperandToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectInstruction;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
}
module IndirectInstructionToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode {
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _, _) }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
}
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
cached
class ExprNode extends Node instanceof ExprNodeBase {
/**
* INTERNAL: Do not use.
*/
cached
Expr getExpr(int n) { result = super.getExpr(n) }
/**
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
cached
final Expr getExpr() { result = this.getExpr(_) }
/**
* INTERNAL: Do not use.
*/
cached
Expr getConvertedExpr(int n) { result = super.getConvertedExpr(n) }
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
cached
final Expr getConvertedExpr() { result = this.getConvertedExpr(_) }
}
/**
* An indirect expression, viewed as a node in a data flow graph.
*/
cached
class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
/**
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
cached
final Expr getExpr(int indirectionIndex) { result = this.getExpr(_, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
cached
Expr getExpr(int n, int indirectionIndex) { result = super.getExpr(n, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
cached
Expr getConvertedExpr(int n, int indirectionIndex) {
result = super.getConvertedExpr(n, indirectionIndex)
}
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
cached
Expr getConvertedExpr(int indirectionIndex) {
result = this.getConvertedExpr(_, indirectionIndex)
}
}
}
import Cached

View File

@@ -104,7 +104,7 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
cached
private newtype TDefImpl =
TDefAddressImpl(BaseIRVariable v) or
TDefAddressImpl(BaseSourceVariable v) or
TDirectDefImpl(Operand address, int indirectionIndex) {
isDef(_, _, address, _, _, indirectionIndex)
} or
@@ -325,9 +325,9 @@ private Instruction getInitializationTargetAddress(IRVariable v) {
)
}
/** An initial definition of an `IRVariable`'s address. */
private class DefAddressImpl extends DefImpl, TDefAddressImpl {
BaseIRVariable v;
/** An initial definition of an SSA variable address. */
abstract private class DefAddressImpl extends DefImpl, TDefAddressImpl {
BaseSourceVariable v;
DefAddressImpl() {
this = TDefAddressImpl(v) and
@@ -342,6 +342,19 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
final override Node0Impl getValue() { none() }
override Cpp::Location getLocation() { result = v.getLocation() }
final override SourceVariable getSourceVariable() {
result.getBaseVariable() = v and
result.getIndirection() = 0
}
final override BaseSourceVariable getBaseSourceVariable() { result = v }
}
private class DefVariableAddressImpl extends DefAddressImpl {
override BaseIRVariable v;
final override predicate hasIndexInBlock(IRBlock block, int index) {
exists(IRVariable var | var = v.getIRVariable() |
block.getInstruction(index) = getInitializationTargetAddress(var)
@@ -353,15 +366,14 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
index = 0
)
}
}
override Cpp::Location getLocation() { result = v.getIRVariable().getLocation() }
private class DefCallAddressImpl extends DefAddressImpl {
override BaseCallVariable v;
final override SourceVariable getSourceVariable() {
result.getBaseVariable() = v and
result.getIndirection() = 0
final override predicate hasIndexInBlock(IRBlock block, int index) {
block.getInstruction(index) = v.getCallInstruction()
}
final override BaseSourceVariable getBaseSourceVariable() { result = v }
}
private class DirectDef extends DefImpl, TDirectDefImpl {
@@ -981,7 +993,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
(
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
@@ -999,7 +1011,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(UseImpl use | use.hasIndexInBlock(bb, i, v) |
if use.isCertain() then certain = true else certain = false
)

View File

@@ -40,7 +40,8 @@ predicate ignoreInstruction(Instruction instr) {
instr instanceof AliasedDefinitionInstruction or
instr instanceof AliasedUseInstruction or
instr instanceof InitializeNonLocalInstruction or
instr instanceof ReturnIndirectionInstruction
instr instanceof ReturnIndirectionInstruction or
instr instanceof UninitializedGroupInstruction
)
}
@@ -757,13 +758,19 @@ import Cached
* between the SSA pruning stage, and the final SSA stage.
*/
module InputSigCommon {
class BasicBlock = IRBlock;
class BasicBlock extends IRBlock {
ControlFlowNode getNode(int i) { result = this.getInstruction(i) }
int length() { result = this.getInstructionCount() }
}
class ControlFlowNode = Instruction;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
}

View File

@@ -147,7 +147,10 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, st
* of `c` at sinks and inputs to additional taint steps.
*/
bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
node instanceof ArgumentNode and
c.isSingleton(any(ElementContent ec))
}
/**
* Holds if `node` should be a sanitizer in all global taint flow configurations

View File

@@ -13,7 +13,8 @@ private newtype TMemoryAccessKind =
TPhiMemoryAccess() or
TUnmodeledMemoryAccess() or
TChiTotalMemoryAccess() or
TChiPartialMemoryAccess()
TChiPartialMemoryAccess() or
TGroupedMemoryAccess()
/**
* Describes the set of memory locations memory accessed by a memory operand or
@@ -99,3 +100,11 @@ class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
override string toString() { result = "chi(partial)" }
}
/**
* The result of an `UninitializedGroup` instruction, which initializes a set of
* allocations that are each assigned the same virtual variable.
*/
class GroupedMemoryAccess extends MemoryAccessKind, TGroupedMemoryAccess {
override string toString() { result = "group" }
}

View File

@@ -89,6 +89,7 @@ private newtype TOpcode =
TSizedBufferMayWriteSideEffect() or
TInitializeDynamicAllocation() or
TChi() or
TUninitializedGroup() or
TInlineAsm() or
TUnreached() or
TNewObj()
@@ -1237,6 +1238,17 @@ module Opcode {
}
}
/**
* The `Opcode` for a `UninitializedGroup`.
*
* See the `UninitializedGroupInstruction` documentation for more details.
*/
class UninitializedGroup extends Opcode, TUninitializedGroup {
final override string toString() { result = "UninitializedGroup" }
override GroupedMemoryAccess getWriteMemoryAccess() { any() }
}
/**
* The `Opcode` for an `InlineAsmInstruction`.
*

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -106,8 +106,7 @@ private predicate operandEscapesDomain(Operand operand) {
not isArgumentForParameter(_, operand, _) and
not isOnlyEscapesViaReturnArgument(operand) and
not operand.getUse() instanceof ReturnValueInstruction and
not operand.getUse() instanceof ReturnIndirectionInstruction and
not operand instanceof PhiInputOperand
not operand.getUse() instanceof ReturnIndirectionInstruction
}
/**
@@ -191,6 +190,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset, Instr
// A copy propagates the source value.
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
)
or
operand = instr.(PhiInstruction).getAnInputOperand() and
// Using `unknown` ensures termination since we cannot keep incrementing a bit offset
// through the back edge of a loop (or through recursion).
bitOffset = Ints::unknown()
}
private predicate operandEscapesNonReturn(Operand operand) {
@@ -212,9 +216,6 @@ private predicate operandEscapesNonReturn(Operand operand) {
or
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultEscapesNonReturn(operand.getUse())
or
operandEscapesDomain(operand)
}
@@ -236,9 +237,6 @@ private predicate operandMayReachReturn(Operand operand) {
operand.getUse() instanceof ReturnValueInstruction
or
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultMayReachReturn(operand.getUse())
}
private predicate operandReturned(Operand operand, IntValue bitOffset) {
@@ -340,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled()
}
/** Holds if `operand` may (transitively) flow to an `AddressOperand`. */
private predicate consumedAsAddressOperand(Operand operand) {
operand instanceof AddressOperand
or
exists(Operand address |
consumedAsAddressOperand(address) and
operandIsPropagated(operand, _, address.getDef())
)
}
/**
* Holds if `operand` may originate from a base instruction of an allocation,
* and that operand may transitively flow to an `AddressOperand`.
*/
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
consumedAsAddressOperand(operand) and
(
not exists(Configuration::getOldAllocation(allocation)) and
operand.getDef() = allocation.getABaseInstruction()
or
exists(Operand address |
operandIsPropagated(address, _, operand.getDef()) and
propagatedFromAllocationBase(address, allocation)
)
)
}
private predicate propagatedFromNonAllocationBase(Operand operand) {
exists(Instruction def |
def = operand.getDef() and
not operandIsPropagated(_, _, def) and
not def = any(Configuration::Allocation allocation).getABaseInstruction()
)
or
exists(Operand address |
operandIsPropagated(address, _, operand.getDef()) and
propagatedFromNonAllocationBase(address)
)
}
/**
* Holds if we cannot see all producers of an operand for which allocation also flows into.
*/
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
exists(AddressOperand address |
propagatedFromAllocationBase(address, allocation) and
propagatedFromNonAllocationBase(address)
)
}
/**
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
* either because the allocation's address is taken within the function and escapes, or because the
@@ -348,12 +396,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes()
or
exists(IREscapeAnalysisConfiguration config |
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
resultEscapesNonReturn(allocation.getABaseInstruction())
or
operandConsumesEscaped(allocation)
)
or
Configuration::phaseNeedsSoundEscapeAnalysis() and
resultEscapesNonReturn(allocation.getABaseInstruction())
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
}
/**

View File

@@ -101,6 +101,8 @@ class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocati
final override predicate isAlwaysAllocatedOnStack() { none() }
final override predicate alwaysEscapes() { none() }
final IRAutomaticVariable getIRVariable() { result = var }
}
class DynamicAllocation extends Allocation, TDynamicAllocation {
@@ -144,3 +146,8 @@ class DynamicAllocation extends Allocation, TDynamicAllocation {
}
predicate phaseNeedsSoundEscapeAnalysis() { none() }
UnaliasedSsa::Allocation getOldAllocation(VariableAllocation allocation) {
UnaliasedSsa::canReuseSsaForVariable(allocation.getIRVariable()) and
result = allocation.getIRVariable()
}

View File

@@ -7,7 +7,8 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConst
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import AliasConfiguration
import AliasConfiguration
private import codeql.util.Boolean
private class IntValue = Ints::IntValue;
@@ -16,49 +17,196 @@ private predicate isIndirectOrBufferMemoryAccess(MemoryAccessKind kind) {
kind instanceof BufferMemoryAccess
}
private predicate hasResultMemoryAccess(
Instruction instr, Allocation var, IRType type, Language::LanguageType languageType,
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
private predicate hasMemoryAccess(
AddressOperand addrOperand, Allocation var, IntValue startBitOffset, boolean grouped
) {
exists(AddressOperand addrOperand |
addrOperand = instr.getResultAddressOperand() and
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
languageType = instr.getResultLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(instr.getResultMemoryAccess()) and
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
)
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
if strictcount(Allocation alloc | addressOperandAllocationAndOffset(addrOperand, alloc, _)) > 1
then grouped = true
else grouped = false
}
private predicate hasResultMemoryAccess(
AddressOperand address, Instruction instr, Allocation var, IRType type,
Language::LanguageType languageType, IntValue startBitOffset, IntValue endBitOffset,
boolean isMayAccess, boolean grouped
) {
address = instr.getResultAddressOperand() and
hasMemoryAccess(address, var, startBitOffset, grouped) and
languageType = instr.getResultLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(instr.getResultMemoryAccess()) and
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
}
private predicate hasOperandMemoryAccess(
MemoryOperand operand, Allocation var, IRType type, Language::LanguageType languageType,
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
AddressOperand address, MemoryOperand operand, Allocation var, IRType type,
Language::LanguageType languageType, IntValue startBitOffset, IntValue endBitOffset,
boolean isMayAccess, boolean grouped
) {
exists(AddressOperand addrOperand |
addrOperand = operand.getAddressOperand() and
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
languageType = operand.getLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(operand.getMemoryAccess()) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
address = operand.getAddressOperand() and
hasMemoryAccess(address, var, startBitOffset, grouped) and
languageType = operand.getLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(operand.getMemoryAccess()) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
}
private Allocation getAnAllocation(AddressOperand address) {
hasResultMemoryAccess(address, _, result, _, _, _, _, _, true) or
hasOperandMemoryAccess(address, _, result, _, _, _, _, _, true)
}
private module AllocationSet0 =
QlBuiltins::InternSets<AddressOperand, Allocation, getAnAllocation/1>;
/**
* A set of allocations containing at least 2 elements.
*/
private class NonSingletonSets extends AllocationSet0::Set {
NonSingletonSets() { strictcount(Allocation var | this.contains(var)) > 1 }
/** Gets an allocation from this set. */
Allocation getAnAllocation() { this.contains(result) }
/** Gets the string representation of this set. */
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
}
/** Holds the instersection of `s1` and `s2` is non-empty. */
private predicate hasOverlappingElement(NonSingletonSets s1, NonSingletonSets s2) {
exists(Allocation var |
s1.contains(var) and
s2.contains(var)
)
}
private module AllocationSet =
QlBuiltins::EquivalenceRelation<NonSingletonSets, hasOverlappingElement/2>;
/**
* Holds if `var` is created by the AST element `e`. Furthermore, the value `d`
* represents which branch of the `Allocation` type `var` is from.
*/
private predicate allocationAst(Allocation var, @element e, int d) {
var.(VariableAllocation).getIRVariable().getAst() = e and d = 0
or
var.(IndirectParameterAllocation).getIRVariable().getAst() = e and d = 1
or
var.(DynamicAllocation).getABaseInstruction().getAst() = e and d = 2
}
/** Holds if `x = y` and `x` is an AST element that creates an `Allocation`. */
private predicate id(@element x, @element y) {
allocationAst(_, x, _) and
x = y
}
private predicate idOf(@element x, int y) = equivalenceRelation(id/2)(x, y)
/** Gets a unique integer representation of `var`. */
private int getUniqueAllocationId(Allocation var) {
exists(int r, @element e, int d |
allocationAst(var, e, d) and
idOf(e, r) and
result = 3 * r + d
)
}
/**
* An equivalence class of a set of allocations.
*
* Any `VariableGroup` will be completely disjunct from any other
* `VariableGroup`.
*/
class VariableGroup extends AllocationSet::EquivalenceClass {
/** Gets the location of this set. */
final Location getLocation() { result = this.getIRFunction().getLocation() }
/** Gets the enclosing `IRFunction` of this set. */
final IRFunction getIRFunction() {
result = unique( | | this.getAnAllocation().getEnclosingIRFunction())
}
/** Gets the type of elements contained in this set. */
final Language::LanguageType getType() {
strictcount(Language::LanguageType langType |
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, langType, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, langType, _, _, _, true)
)
) = 1 and
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, result, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, result, _, _, _, true)
)
or
strictcount(Language::LanguageType langType |
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, langType, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, langType, _, _, _, true)
)
) > 1 and
result = any(IRUnknownType type).getCanonicalLanguageType()
}
/** Gets an allocation of this set. */
final Allocation getAnAllocation() {
exists(AllocationSet0::Set set |
this = AllocationSet::getEquivalenceClass(set) and
set.contains(result)
)
}
/** Gets a unique string representing this set. */
final private string getUniqueId() {
result = strictconcat(getUniqueAllocationId(this.getAnAllocation()).toString(), ",")
}
/**
* Gets the order that this set should be initialized in.
*
* Note: This is _not_ the order in which the _members_ of the set should be
* initialized. Rather, it represents the order in which the set should be
* initialized in relation to other sets. That is, if
* ```
* getInitializationOrder() = 2
* ```
* then this set will be initialized as the second (third) set in the
* enclosing function. In order words, the third `UninitializedGroup`
* instruction in the entry block of the enclosing function will initialize
* this set of allocations.
*/
final int getInitializationOrder() {
exists(IRFunction func |
func = this.getIRFunction() and
this =
rank[result + 1](VariableGroup vg, string uniq |
vg.getIRFunction() = func and uniq = vg.getUniqueId()
|
vg order by uniq
)
)
}
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
}
private newtype TMemoryLocation =
TVariableMemoryLocation(
Allocation var, IRType type, Language::LanguageType languageType, IntValue startBitOffset,
IntValue endBitOffset, boolean isMayAccess
) {
(
hasResultMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
hasResultMemoryAccess(_, _, var, type, _, startBitOffset, endBitOffset, isMayAccess, false)
or
hasOperandMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
hasOperandMemoryAccess(_, _, var, type, _, startBitOffset, endBitOffset, isMayAccess, false)
or
// For a stack variable, always create a memory location for the entire variable.
var.isAlwaysAllocatedOnStack() and
@@ -69,31 +217,25 @@ private newtype TMemoryLocation =
) and
languageType = type.getCanonicalLanguageType()
} or
TEntireAllocationMemoryLocation(Allocation var, boolean isMayAccess) {
(
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
) and
(isMayAccess = false or isMayAccess = true)
TEntireAllocationMemoryLocation(Allocation var, Boolean isMayAccess) {
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
} or
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
} or
TAllNonLocalMemory(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
} or
TAllAliasedMemory(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
}
TGroupedMemoryLocation(VariableGroup vg, Boolean isMayAccess, Boolean isAll) or
TUnknownMemoryLocation(IRFunction irFunc, Boolean isMayAccess) or
TAllNonLocalMemory(IRFunction irFunc, Boolean isMayAccess) or
TAllAliasedMemory(IRFunction irFunc, Boolean isMayAccess)
/**
* Represents the memory location accessed by a memory operand or memory result. In this implementation, the location is
* A memory location accessed by a memory operand or memory result. In this implementation, the location is
* one of the following:
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
* unknown.
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
*
* Some of these memory locations will be filtered out for performance reasons before being passed to SSA construction.
*/
abstract class MemoryLocation extends TMemoryLocation {
abstract private class MemoryLocation0 extends TMemoryLocation {
final string toString() {
if this.isMayAccess()
then result = "?" + this.toStringInternal()
@@ -116,7 +258,14 @@ abstract class MemoryLocation extends TMemoryLocation {
abstract predicate isMayAccess();
Allocation getAllocation() { none() }
/**
* Gets an allocation associated with this `MemoryLocation`.
*
* This returns zero or one results in all cases except when `this` is an
* instance of `GroupedMemoryLocation`. When `this` is an instance of
* `GroupedMemoryLocation` this predicate always returns two or more results.
*/
Allocation getAnAllocation() { none() }
/**
* Holds if the location cannot be overwritten except by definition of a `MemoryLocation` for
@@ -147,30 +296,35 @@ abstract class MemoryLocation extends TMemoryLocation {
* represented by a `MemoryLocation` that totally overlaps all other
* `MemoryLocations` in the set.
*/
abstract class VirtualVariable extends MemoryLocation { }
abstract class VirtualVariable extends MemoryLocation0 { }
abstract class AllocationMemoryLocation extends MemoryLocation {
abstract class AllocationMemoryLocation extends MemoryLocation0 {
Allocation var;
boolean isMayAccess;
AllocationMemoryLocation() {
this instanceof TMemoryLocation and
isMayAccess = false
or
isMayAccess = true // Just ensures that `isMayAccess` is bound.
}
bindingset[isMayAccess]
AllocationMemoryLocation() { any() }
final override VirtualVariable getVirtualVariable() {
if allocationEscapes(var)
then result = TAllAliasedMemory(var.getEnclosingIRFunction(), false)
else result.(AllocationMemoryLocation).getAllocation() = var
else (
// It may be that the grouped memory location contains an escaping
// allocation. In that case, the virtual variable is still the memory
// location that represents all aliased memory. Thus, we need to
// call `getVirtualVariable` on the grouped memory location.
result = getGroupedMemoryLocation(var, false, false).getVirtualVariable()
or
not exists(getGroupedMemoryLocation(var, false, false)) and
result.(AllocationMemoryLocation).getAnAllocation() = var
)
}
final override IRFunction getIRFunction() { result = var.getEnclosingIRFunction() }
final override Location getLocation() { result = var.getLocation() }
final override Allocation getAllocation() { result = var }
final override Allocation getAnAllocation() { result = var }
final override predicate isMayAccess() { isMayAccess = true }
@@ -211,13 +365,13 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
final override Language::LanguageType getType() {
if
strictcount(Language::LanguageType accessType |
hasResultMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset, _) or
hasOperandMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset, _)
hasResultMemoryAccess(_, _, var, type, accessType, startBitOffset, endBitOffset, _, false) or
hasOperandMemoryAccess(_, _, var, type, accessType, startBitOffset, endBitOffset, _, false)
) = 1
then
// All of the accesses have the same `LanguageType`, so just use that.
hasResultMemoryAccess(_, var, type, result, startBitOffset, endBitOffset, _) or
hasOperandMemoryAccess(_, var, type, result, startBitOffset, endBitOffset, _)
hasResultMemoryAccess(_, _, var, type, result, startBitOffset, endBitOffset, _, false) or
hasOperandMemoryAccess(_, _, var, type, result, startBitOffset, endBitOffset, _, false)
else
// There is no single type for all accesses, so just use the canonical one for this `IRType`.
result = type.getCanonicalLanguageType()
@@ -247,6 +401,89 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
}
}
/**
* A group of allocations represented as a single memory location.
*
* If `isAll()` holds then this memory location represents all the enclosing
* allocations, and if `isSome()` holds then this memory location represents
* one or more of the enclosing allocations.
*
* For example, consider the following snippet:
* ```
* int* p;
* int a, b;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 42;
* ```
*
* The write memory location associated with the write to `*p` writes to a
* grouped memory location representing the _some_ allocation in the set
* `{a, b}`, and the subsequent `Chi` instruction merges the new value of
* `{a, b}` into a memory location that represents _all_ of the allocations
* in the set.
*/
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation0 {
VariableGroup vg;
boolean isMayAccess;
boolean isAll;
GroupedMemoryLocation() { this = TGroupedMemoryLocation(vg, isMayAccess, isAll) }
final override Location getLocation() { result = vg.getLocation() }
final override IRFunction getIRFunction() { result = vg.getIRFunction() }
final override predicate isMayAccess() { isMayAccess = true }
final override string getUniqueId() {
if this.isAll()
then result = "All{" + strictconcat(vg.getAnAllocation().getUniqueId(), ", ") + "}"
else result = "Some{" + strictconcat(vg.getAnAllocation().getUniqueId(), ", ") + "}"
}
final override string toStringInternal() { result = this.getUniqueId() }
final override Language::LanguageType getType() { result = vg.getType() }
final override VirtualVariable getVirtualVariable() {
if allocationEscapes(this.getAnAllocation())
then result = TAllAliasedMemory(vg.getIRFunction(), false)
else result = TGroupedMemoryLocation(vg, false, true)
}
/** Gets an allocation of this memory location. */
override Allocation getAnAllocation() { result = vg.getAnAllocation() }
/** Gets the set of allocations associated with this memory location. */
VariableGroup getGroup() { result = vg }
/** Holds if this memory location represents all the enclosing allocations. */
predicate isAll() { isAll = true }
/** Holds if this memory location represents one or more of the enclosing allocations. */
predicate isSome() { isAll = false }
}
private GroupedMemoryLocation getGroupedMemoryLocation(
Allocation alloc, boolean isMayAccess, boolean isAll
) {
result.getAnAllocation() = alloc and
(
isMayAccess = true and result.isMayAccess()
or
isMayAccess = false and not result.isMayAccess()
) and
(
isAll = true and result.isAll()
or
isAll = false and result.isSome()
)
}
class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
AllocationMemoryLocation
{
@@ -282,10 +519,18 @@ class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
}
}
class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
GroupedVirtualVariable() {
forex(Allocation var | var = this.getAnAllocation() | not allocationEscapes(var)) and
not this.isMayAccess() and
this.isAll()
}
}
/**
* An access to memory that is not known to be confined to a specific `IRVariable`.
*/
class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation0 {
IRFunction irFunc;
boolean isMayAccess;
@@ -312,7 +557,7 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
* An access to memory that is not known to be confined to a specific `IRVariable`, but is known to
* not access memory on the current function's stack frame.
*/
class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation0 {
IRFunction irFunc;
boolean isMayAccess;
@@ -346,7 +591,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
/**
* An access to all aliased memory.
*/
class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation0 {
IRFunction irFunc;
boolean isMayAccess;
@@ -377,7 +622,7 @@ class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
/**
* Gets the overlap relationship between the definition location `def` and the use location `use`.
*/
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
Overlap getOverlap(MemoryLocation0 def, MemoryLocation0 use) {
exists(Overlap overlap |
// Compute the overlap based only on the extent.
overlap = getExtentOverlap(def, use) and
@@ -405,7 +650,7 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
* based only on the set of memory locations accessed. Handling of "may" accesses and read-only
* locations occurs in `getOverlap()`.
*/
private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
private Overlap getExtentOverlap(MemoryLocation0 def, MemoryLocation0 use) {
// The def and the use must have the same virtual variable, or no overlap is possible.
(
// AllAliasedMemory must totally overlap any location within the same virtual variable.
@@ -446,7 +691,7 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
result instanceof MustExactlyOverlap
or
not use instanceof EntireAllocationMemoryLocation and
if def.getAllocation() = use.getAllocation()
if def.getAnAllocation() = use.getAnAllocation()
then
// EntireAllocationMemoryLocation totally overlaps any location within
// the same allocation.
@@ -454,11 +699,48 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
else (
// There is no overlap with a location that's known to belong to a
// different allocation, but all other locations may partially overlap.
not exists(use.getAllocation()) and
not exists(use.getAnAllocation()) and
result instanceof MayPartiallyOverlap
)
)
or
exists(GroupedMemoryLocation group |
group = def and
def.getVirtualVariable() = use.getVirtualVariable()
|
(
use instanceof UnknownMemoryLocation or
use instanceof AllAliasedMemory
) and
result instanceof MayPartiallyOverlap
or
group.isAll() and
(
group.getAnAllocation() =
[
use.(EntireAllocationMemoryLocation).getAnAllocation(),
use.(VariableMemoryLocation).getAnAllocation()
]
or
use.(GroupedMemoryLocation).isSome()
) and
result instanceof MustTotallyOverlap
or
group.isAll() and
use.(GroupedMemoryLocation).isAll() and
result instanceof MustExactlyOverlap
or
group.isSome() and
(
use instanceof EntireAllocationMemoryLocation
or
use instanceof VariableMemoryLocation
or
use instanceof GroupedMemoryLocation
) and
result instanceof MayPartiallyOverlap
)
or
exists(VariableMemoryLocation defVariableLocation |
defVariableLocation = def and
(
@@ -468,7 +750,8 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
(
use instanceof UnknownMemoryLocation or
use instanceof AllAliasedMemory or
use instanceof EntireAllocationMemoryLocation
use instanceof EntireAllocationMemoryLocation or
use instanceof GroupedMemoryLocation
) and
result instanceof MayPartiallyOverlap
or
@@ -534,7 +817,7 @@ private predicate isCoveredOffset(Allocation var, int offsetRank, VariableMemory
exists(int startRank, int endRank, VirtualVariable vvar |
vml.getStartBitOffset() = rank[startRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
vml.getEndBitOffset() = rank[endRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
var = vml.getAllocation() and
var = vml.getAnAllocation() and
vvar = vml.getVirtualVariable() and
isRelatableMemoryLocation(vml) and
offsetRank in [startRank .. endRank]
@@ -542,7 +825,7 @@ private predicate isCoveredOffset(Allocation var, int offsetRank, VariableMemory
}
private predicate hasUnknownOffset(Allocation var, VariableMemoryLocation vml) {
vml.getAllocation() = var and
vml.getAnAllocation() = var and
(
vml.getStartBitOffset() = Ints::unknown() or
vml.getEndBitOffset() = Ints::unknown()
@@ -557,9 +840,9 @@ private predicate overlappingIRVariableMemoryLocations(
isCoveredOffset(var, offsetRank, use)
)
or
hasUnknownOffset(use.getAllocation(), def)
hasUnknownOffset(use.getAnAllocation(), def)
or
hasUnknownOffset(def.getAllocation(), use)
hasUnknownOffset(def.getAnAllocation(), use)
}
private Overlap getVariableMemoryLocationOverlap(
@@ -580,6 +863,40 @@ predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMem
bindingset[result, b]
private boolean unbindBool(boolean b) { result != b.booleanNot() }
/** Gets the number of overlapping uses of `def`. */
private int numberOfOverlappingUses(MemoryLocation0 def) {
result = strictcount(MemoryLocation0 use | exists(getOverlap(def, use)))
}
/**
* Holds if `def` is a busy definition. That is, it has a large number of
* overlapping uses.
*/
private predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 }
/** Holds if `use` is a use that overlaps with a busy definition. */
private predicate useOverlapWithBusyDef(MemoryLocation0 use) {
exists(MemoryLocation0 def |
exists(getOverlap(def, use)) and
isBusyDef(def)
)
}
final private class FinalMemoryLocation = MemoryLocation0;
/**
* A memory location accessed by a memory operand or memory result. In this implementation, the location is
* one of the following:
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
* unknown.
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
*
* Compared to `MemoryLocation0`, this class does not contain memory locations that represent uses of busy definitions.
*/
class MemoryLocation extends FinalMemoryLocation {
MemoryLocation() { not useOverlapWithBusyDef(this) }
}
MemoryLocation getResultMemoryLocation(Instruction instr) {
not canReuseSsaForOldResult(instr) and
exists(MemoryAccessKind kind, boolean isMayAccess |
@@ -588,13 +905,24 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
(
(
isIndirectOrBufferMemoryAccess(kind) and
if hasResultMemoryAccess(instr, _, _, _, _, _, _)
if hasResultMemoryAccess(_, instr, _, _, _, _, _, _, _)
then
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
hasResultMemoryAccess(instr, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset,
unbindBool(isMayAccess))
exists(
Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset,
boolean grouped
|
hasResultMemoryAccess(_, instr, var, type, _, startBitOffset, endBitOffset, isMayAccess,
grouped)
|
// If the instruction is only associated with one allocation we assign it a `VariableMemoryLocation`
if grouped = false
then
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset,
unbindBool(isMayAccess))
else
// And otherwise we assign it a memory location that groups all the relevant memory locations into one.
result = getGroupedMemoryLocation(var, unbindBool(isMayAccess), false)
)
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction(), isMayAccess)
)
@@ -613,20 +941,31 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
)
}
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
private MemoryLocation0 getOperandMemoryLocation0(MemoryOperand operand, boolean isMayAccess) {
not canReuseSsaForOldResult(operand.getAnyDef()) and
exists(MemoryAccessKind kind, boolean isMayAccess |
exists(MemoryAccessKind kind |
kind = operand.getMemoryAccess() and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
(
(
isIndirectOrBufferMemoryAccess(kind) and
if hasOperandMemoryAccess(operand, _, _, _, _, _, _)
if hasOperandMemoryAccess(_, operand, _, _, _, _, _, _, _)
then
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
hasOperandMemoryAccess(operand, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
exists(
Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset,
boolean grouped
|
hasOperandMemoryAccess(_, operand, var, type, _, startBitOffset, endBitOffset,
isMayAccess, grouped)
|
// If the operand is only associated with one memory location we assign it a `VariableMemoryLocation`
if grouped = false
then
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
else
// And otherwise we assign it a memory location that groups all relevant memory locations into one.
result = getGroupedMemoryLocation(var, isMayAccess, false)
)
else result = TUnknownMemoryLocation(operand.getEnclosingIRFunction(), isMayAccess)
)
@@ -645,6 +984,19 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
)
}
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
exists(MemoryLocation0 use0, boolean isMayAccess |
use0 = getOperandMemoryLocation0(operand, isMayAccess)
|
result = use0
or
// If `use0` overlaps with a busy definition we turn it into a use
// of `UnknownMemoryLocation`.
not use0 instanceof MemoryLocation and
result = TUnknownMemoryLocation(operand.getEnclosingIRFunction(), isMayAccess)
)
}
/** Gets the start bit offset of a `MemoryLocation`, if any. */
int getStartBitOffset(VariableMemoryLocation location) {
result = location.getStartBitOffset() and Ints::hasValue(result)

View File

@@ -15,6 +15,51 @@ private class OldInstruction = Reachability::ReachableInstruction;
import Cached
/**
* Holds if `instruction` is the first instruction that may be followed by
* an `UninitializedGroup` instruction, and the enclosing function of
* `instruction` is `func`.
*/
private predicate isFirstInstructionBeforeUninitializedGroup(
Instruction instruction, IRFunction func
) {
instruction = getChi(any(OldIR::InitializeNonLocalInstruction init)) and
func = instruction.getEnclosingIRFunction()
}
/** Gets the `i`'th `UninitializedGroup` instruction in `func`. */
private UninitializedGroupInstruction getInitGroupInstruction(int i, IRFunction func) {
exists(Alias::VariableGroup vg |
vg.getIRFunction() = func and
vg.getInitializationOrder() = i and
result = uninitializedGroup(vg)
)
}
/**
* Holds if `instruction` is the last instruction in the chain of `UninitializedGroup`
* instructions in `func`. The chain of instructions may be empty in which case
* `instruction` satisfies
* ```
* isFirstInstructionBeforeUninitializedGroup(instruction, func)
* ```
*/
predicate isLastInstructionForUninitializedGroups(Instruction instruction, IRFunction func) {
exists(int i |
instruction = getInitGroupInstruction(i, func) and
not exists(getChi(instruction)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
exists(int i |
instruction = getChi(getInitGroupInstruction(i, func)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
not exists(getInitGroupInstruction(0, func))
}
cached
private module Cached {
cached
@@ -32,6 +77,11 @@ private module Cached {
hasChiNode(_, primaryInstruction)
}
cached
predicate hasChiNodeAfterUninitializedGroup(UninitializedGroupInstruction initGroup) {
hasChiNodeAfterUninitializedGroup(_, initGroup)
}
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldIR::Instruction oldInstruction |
@@ -45,7 +95,8 @@ private module Cached {
}
class TStageInstruction =
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
TUninitializedGroupInstruction;
/**
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +129,8 @@ private module Cached {
or
instr instanceof TChiInstruction
or
instr instanceof TUninitializedGroupInstruction
or
instr instanceof TUnreachedInstruction
}
@@ -123,7 +176,8 @@ private module Cached {
predicate hasModeledMemoryResult(Instruction instruction) {
canModelResultForOldInstruction(getOldInstruction(instruction)) or
instruction instanceof PhiInstruction or // Phis always have modeled results
instruction instanceof ChiInstruction // Chis always have modeled results
instruction instanceof ChiInstruction or // Chis always have modeled results
instruction instanceof UninitializedGroupInstruction // Group initializers always have modeled results
}
cached
@@ -134,16 +188,23 @@ private module Cached {
or
// Chi instructions track virtual variables, and therefore a chi instruction is
// conflated if it's associated with the aliased virtual variable.
exists(OldInstruction oldInstruction | instruction = getChi(oldInstruction) |
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
exists(Instruction input | instruction = getChi(input) |
Alias::getResultMemoryLocation(input).getVirtualVariable() instanceof
Alias::AliasedVirtualVariable
or
// A chi following an `UninitializedGroupInstruction` only happens when the virtual
// variable of the grouped memory location is `{AllAliasedMemory}`.
exists(Alias::GroupedMemoryLocation gml |
input = uninitializedGroup(gml.getGroup()) and
gml.getVirtualVariable() instanceof Alias::AliasedVirtualVariable
)
)
or
// Phi instructions track locations, and therefore a phi instruction is
// conflated if it's associated with a conflated location.
exists(Alias::MemoryLocation location |
instruction = getPhi(_, location) and
not exists(location.getAllocation())
not exists(location.getAnAllocation())
)
}
@@ -205,7 +266,11 @@ private module Cached {
hasMemoryOperandDefinition(oldInstruction, oldOperand, overlap, result)
)
or
instruction = getChi(getOldInstruction(result)) and
(
instruction = getChi(getOldInstruction(result))
or
instruction = getChi(result.(UninitializedGroupInstruction))
) and
tag instanceof ChiPartialOperandTag and
overlap instanceof MustExactlyOverlap
or
@@ -263,6 +328,14 @@ private module Cached {
)
}
cached
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction init) {
exists(Alias::VariableGroup vg |
init = uninitializedGroup(vg) and
result = vg.getAnAllocation().getABaseInstruction().(VariableInstruction).getIRVariable()
)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
@@ -316,6 +389,19 @@ private module Cached {
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
}
private ChiInstruction getChiAfterUninitializedGroup(int i, IRFunction func) {
result =
rank[i + 1](VariableGroup vg, UninitializedGroupInstruction initGroup, ChiInstruction chi,
int r |
initGroup.getEnclosingIRFunction() = func and
chi = getChi(initGroup) and
initGroup = uninitializedGroup(vg) and
r = vg.getInitializationOrder()
|
chi order by r
)
}
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
@@ -329,6 +415,19 @@ private module Cached {
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)
)
or
exists(UninitializedGroupInstruction initGroup, IRFunction func |
chiInstr = getChi(initGroup) and
func = initGroup.getEnclosingIRFunction()
|
chiInstr = getChiAfterUninitializedGroup(0, func) and
isFirstInstructionBeforeUninitializedGroup(result, func)
or
exists(int i |
chiInstr = getChiAfterUninitializedGroup(i + 1, func) and
result = getChiAfterUninitializedGroup(i, func)
)
)
}
cached
@@ -344,14 +443,40 @@ private module Cached {
)
}
/*
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction
*/
private UninitializedGroupInstruction firstInstructionToUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
result = getInitGroupInstruction(0, func) and
kind instanceof GotoEdge
)
}
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
private Instruction getNextUninitializedGroupInstruction(Instruction instruction, EdgeKind kind) {
exists(int i, IRFunction func |
func = instruction.getEnclosingIRFunction() and
instruction = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
if hasChiNodeAfterUninitializedGroup(_, instruction)
then result = getChi(instruction)
else result = getInitGroupInstruction(i + 1, func)
)
or
exists(int i, IRFunction func, UninitializedGroupInstruction initGroup |
func = instruction.getEnclosingIRFunction() and
instruction = getChi(initGroup) and
initGroup = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
result = getInitGroupInstruction(i + 1, func)
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup0(
Instruction instruction, EdgeKind kind
) {
if hasChiNode(_, getOldInstruction(instruction))
then
result = getChi(getOldInstruction(instruction)) and
@@ -371,6 +496,107 @@ private module Cached {
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func, Instruction firstBeforeUninitializedGroup |
isLastInstructionForUninitializedGroups(instruction, func) and
isFirstInstructionBeforeUninitializedGroup(firstBeforeUninitializedGroup, func) and
result = getInstructionSuccessorAfterUninitializedGroup0(firstBeforeUninitializedGroup, kind)
)
}
/**
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction.
*
* Furthermore, the entry block is augmented with `UninitializedGroup` instructions and `Chi`
* instructions. For example, consider this example:
* ```cpp
* int x, y;
* int* p;
* if(b) {
* p = &x;
* escape(&x);
* } else {
* p = &y;
* }
* *p = 42;
*
* int z, w;
* int* q;
* if(b) {
* q = &z;
* } else {
* q = &w;
* }
* *q = 43;
* ```
*
* the unaliased IR for the entry block of this snippet is:
* ```
* v1(void) = EnterFunction :
* m1(unknown) = AliasedDefinition :
* m2(unknown) = InitializeNonLocal :
* r1(glval<bool>) = VariableAddress[b] :
* m3(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m4(int) = Uninitialized[x] : &:r2
* r3(glval<int>) = VariableAddress[y] :
* m5(int) = Uninitialized[y] : &:r3
* r4(glval<int *>) = VariableAddress[p] :
* m6(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m3
* v2(void) = ConditionalBranch : r6
* ```
* and we need to transform this to aliased IR by inserting an `UninitializedGroup`
* instruction for every `VariableGroup` memory location in the function. Furthermore,
* if the `VariableGroup` memory location contains an allocation that escapes we need
* to insert a `Chi` that writes the memory produced by `UninitializedGroup` into
* `{AllAliasedMemory}`. For the above snippet we then end up with:
* ```
* v1(void) = EnterFunction :
* m2(unknown) = AliasedDefinition :
* m3(unknown) = InitializeNonLocal :
* m4(unknown) = Chi : total:m2, partial:m3
* m5(int) = UninitializedGroup[x,y] :
* m6(unknown) = Chi : total:m4, partial:m5
* m7(int) = UninitializedGroup[w,z] :
* r1(glval<bool>) = VariableAddress[b] :
* m8(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m10(int) = Uninitialized[x] : &:r2
* m11(unknown) = Chi : total:m6, partial:m10
* r3(glval<int>) = VariableAddress[y] :
* m12(int) = Uninitialized[y] : &:r3
* m13(unknown) = Chi : total:m11, partial:m12
* r4(glval<int *>) = VariableAddress[p] :
* m14(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m8
* v2(void) = ConditionalBranch : r6
* ```
*
* Here, the group `{x, y}` contains an allocation that escapes (`x`), so there
* is a `Chi` after the `UninitializedGroup` that initializes the memory for the
* `VariableGroup` containing `x`. None of the allocations in `{w, z}` escape so
* there is no `Chi` following that the `UninitializedGroup` that initializes the
* memory of `{w, z}`.
*/
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = firstInstructionToUninitializedGroup(instruction, kind)
or
result = getNextUninitializedGroupInstruction(instruction, kind)
or
result = getInstructionSuccessorAfterUninitializedGroup(instruction, kind)
or
not isFirstInstructionBeforeUninitializedGroup(instruction, _) and
result = getInstructionSuccessorAfterUninitializedGroup0(instruction, kind)
}
cached
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
exists(OldInstruction oldInstruction |
@@ -406,6 +632,16 @@ private module Cached {
exists(IRFunctionBase irFunc |
instr = unreachedInstruction(irFunc) and result = irFunc.getFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction().getFunction()
)
or
exists(UninitializedGroupInstruction initGroup |
instr = chiInstruction(initGroup) and
result = getInstructionAst(initGroup)
)
}
cached
@@ -418,9 +654,16 @@ private module Cached {
)
or
exists(Instruction primaryInstr, Alias::VirtualVariable vvar |
instr = chiInstruction(primaryInstr) and
hasChiNode(vvar, primaryInstr) and
result = vvar.getType()
instr = chiInstruction(primaryInstr) and result = vvar.getType()
|
hasChiNode(vvar, primaryInstr)
or
hasChiNodeAfterUninitializedGroup(vvar, primaryInstr)
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getType()
)
or
instr = reusedPhiInstruction(_) and
@@ -448,6 +691,8 @@ private module Cached {
or
instr = chiInstruction(_) and opcode instanceof Opcode::Chi
or
instr = uninitializedGroup(_) and opcode instanceof Opcode::UninitializedGroup
or
instr = unreachedInstruction(_) and opcode instanceof Opcode::Unreached
}
@@ -460,10 +705,15 @@ private module Cached {
result = blockStartInstr.getEnclosingIRFunction()
)
or
exists(OldInstruction primaryInstr |
exists(Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and result = primaryInstr.getEnclosingIRFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction()
)
or
instr = unreachedInstruction(result)
}
@@ -478,6 +728,8 @@ private module Cached {
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction)
)
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
}
@@ -485,7 +737,7 @@ private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(
private OldInstruction getOldInstruction(Instruction instr) { instr = result }
private ChiInstruction getChi(OldInstruction primaryInstr) { result = chiInstruction(primaryInstr) }
private ChiInstruction getChi(Instruction primaryInstr) { result = chiInstruction(primaryInstr) }
private PhiInstruction getPhi(OldBlock defBlock, Alias::MemoryLocation defLocation) {
result = phiInstruction(defBlock.getFirstInstruction(), defLocation)
@@ -506,6 +758,16 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
)
}
private predicate hasChiNodeAfterUninitializedGroup(
Alias::AliasedVirtualVariable vvar, UninitializedGroupInstruction initGroup
) {
exists(Alias::GroupedMemoryLocation defLocation |
initGroup = uninitializedGroup(defLocation.getGroup()) and
defLocation.getVirtualVariable() = vvar and
Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap
)
}
private import PhiInsertion
/**
@@ -668,19 +930,37 @@ private import DefUse
* potentially very sparse.
*/
module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
func = block.getEnclosingIRFunction() and
i = block.getInstruction(index) and
entryBlock = func.getEntryBlock()
|
if
block = entryBlock and
not i instanceof InitializeNonLocalInstruction and
not i instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index
)
}
bindingset[index, block]
pragma[inline_late]
private int getChiOffset(int index, OldBlock block) { result = getNonChiOffset(index, block) + 1 }
/**
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
*/
Instruction getDefinitionOrChiInstruction(
private Instruction getDefinitionOrChiInstruction0(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(OldInstruction oldInstr, int oldOffset |
oldInstr = defBlock.getInstruction(oldOffset) and
oldOffset >= 0
|
exists(OldInstruction oldInstr, int oldOffset | oldInstr = defBlock.getInstruction(oldOffset) |
// An odd offset corresponds to the `Chi` instruction.
defOffset = oldOffset * 2 + 1 and
defOffset = getChiOffset(oldOffset, defBlock) and
result = getChi(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -689,7 +969,7 @@ module DefUse {
actualDefLocation = defLocation.getVirtualVariable()
or
// An even offset corresponds to the original instruction.
defOffset = oldOffset * 2 and
defOffset = getNonChiOffset(oldOffset, defBlock) and
result = getNewInstruction(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -702,6 +982,54 @@ module DefUse {
hasDefinition(_, defLocation, defBlock, defOffset) and
result = getPhi(defBlock, defLocation) and
actualDefLocation = defLocation
or
exists(
Alias::VariableGroup vg, int index, UninitializedGroupInstruction initGroup,
Alias::GroupedMemoryLocation gml
|
// Add 3 to account for the function prologue:
// v1(void) = EnterFunction
// m1(unknown) = AliasedDefinition
// m2(unknown) = InitializeNonLocal
index = 3 + vg.getInitializationOrder() and
not gml.isMayAccess() and
gml.isSome() and
gml.getGroup() = vg and
vg.getIRFunction().getEntryBlock() = defBlock and
initGroup = uninitializedGroup(vg) and
(defLocation = gml or defLocation = gml.getVirtualVariable())
|
result = initGroup and
defOffset = 2 * index and
actualDefLocation = defLocation
or
result = getChi(initGroup) and
defOffset = 2 * index + 1 and
actualDefLocation = defLocation.getVirtualVariable()
)
}
private ChiInstruction remapGetDefinitionOrChiInstruction(Instruction oldResult) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(oldResult, func) and
isLastInstructionForUninitializedGroups(result, func)
)
}
Instruction getDefinitionOrChiInstruction(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(Instruction oldResult |
oldResult =
getDefinitionOrChiInstruction0(defBlock, defOffset, defLocation, actualDefLocation) and
(
result = remapGetDefinitionOrChiInstruction(oldResult)
or
not exists(remapGetDefinitionOrChiInstruction(oldResult)) and
result = oldResult
)
)
}
/**
@@ -842,8 +1170,20 @@ module DefUse {
block.getInstruction(index) = def and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = index * 2 // The use will be connected to the definition on the original instruction.
then offset = getChiOffset(index, block) // The use will be connected to the definition on the `Chi` instruction.
else offset = getNonChiOffset(index, block) // The use will be connected to the definition on the original instruction.
)
or
exists(UninitializedGroupInstruction initGroup, int index, Overlap overlap, VariableGroup vg |
initGroup.getEnclosingIRFunction().getEntryBlock() = getNewBlock(block) and
vg = defLocation.(Alias::GroupedMemoryLocation).getGroup() and
// EnterFunction + AliasedDefinition + InitializeNonLocal + index
index = 3 + vg.getInitializationOrder() and
initGroup = uninitializedGroup(vg) and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap and hasChiNodeAfterUninitializedGroup(initGroup)
then offset = 2 * index + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = 2 * index // The use will be connected to the definition on the original instruction.
)
}
@@ -904,10 +1244,11 @@ module DefUse {
block.getInstruction(index) = use and
(
// A direct use of the location.
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
offset = getNonChiOffset(index, block)
or
// A `Chi` instruction will include a use of the virtual variable.
hasChiNode(useLocation, use) and offset = (index * 2) + 1
hasChiNode(useLocation, use) and offset = getChiOffset(index, block)
)
)
}
@@ -1057,5 +1398,9 @@ module Ssa {
predicate hasChiInstruction = Cached::hasChiInstructionCached/1;
predicate hasChiNodeAfterUninitializedGroup = Cached::hasChiNodeAfterUninitializedGroup/1;
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
class VariableGroup = Alias::VariableGroup;
}

View File

@@ -31,6 +31,7 @@ newtype TInstruction =
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or
TUnaliasedSsaUninitializedGroupInstruction(UnaliasedSsa::Ssa::VariableGroup vg) or
TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) {
@@ -41,6 +42,12 @@ newtype TInstruction =
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaUninitializedGroupInstruction(AliasedSsa::Ssa::VariableGroup vg) or
TAliasedSsaChiAfterUninitializedGroupInstruction(
TAliasedSsaUninitializedGroupInstruction initGroup
) {
AliasedSsa::Ssa::hasChiNodeAfterUninitializedGroup(initGroup)
}
/**
@@ -62,7 +69,11 @@ module UnaliasedSsaInstructions {
class TChiInstruction = TUnaliasedSsaChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
class TUninitializedGroupInstruction = TUnaliasedSsaUninitializedGroupInstruction;
class TRawOrUninitializedGroupInstruction = TRawInstruction or TUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawOrUninitializedGroupInstruction primaryInstruction) {
result = TUnaliasedSsaChiInstruction(primaryInstruction)
}
@@ -71,6 +82,12 @@ module UnaliasedSsaInstructions {
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TUnaliasedSsaUnreachedInstruction(irFunc)
}
class VariableGroup = UnaliasedSsa::Ssa::VariableGroup;
// This really should just be `TUnaliasedSsaUninitializedGroupInstruction`, but that makes the
// compiler realize that certain expressions in `SSAConstruction` are unsatisfiable.
TRawOrUninitializedGroupInstruction uninitializedGroup(VariableGroup vg) { none() }
}
/**
@@ -92,10 +109,16 @@ module AliasedSsaInstructions {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, _)
}
class TChiInstruction = TAliasedSsaChiInstruction;
class TChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
class TRawOrInitialzieGroupInstruction =
TRawInstruction or TAliasedSsaUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawOrInitialzieGroupInstruction primaryInstruction) {
result = TAliasedSsaChiInstruction(primaryInstruction)
or
result = TAliasedSsaChiAfterUninitializedGroupInstruction(primaryInstruction)
}
class TUnreachedInstruction = TAliasedSsaUnreachedInstruction;
@@ -103,4 +126,12 @@ module AliasedSsaInstructions {
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TAliasedSsaUnreachedInstruction(irFunc)
}
class VariableGroup = AliasedSsa::Ssa::VariableGroup;
class TUninitializedGroupInstruction = TAliasedSsaUninitializedGroupInstruction;
TUninitializedGroupInstruction uninitializedGroup(VariableGroup vg) {
result = TAliasedSsaUninitializedGroupInstruction(vg)
}
}

View File

@@ -12,6 +12,9 @@ private import semmle.code.cpp.ir.internal.Overlap
* Provides the newtype used to represent operands across all phases of the IR.
*/
private module Internal {
private class TAliasedChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
/**
* An IR operand. `TOperand` is shared across all phases of the IR. There are branches of this
* type for operands created directly from the AST (`TRegisterOperand` and `TNonSSAMemoryOperand`),
@@ -52,7 +55,7 @@ private module Internal {
) {
exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap))
} or
TAliasedChiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) { any() }
TAliasedChiOperand(TAliasedChiInstruction useInstr, ChiOperandTag tag) { any() }
}
/**
@@ -198,10 +201,13 @@ module AliasedSsaOperands {
)
}
private class TChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
/**
* Returns the Chi operand with the specified parameters.
*/
TChiOperand chiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) {
TChiOperand chiOperand(TChiInstruction useInstr, ChiOperandTag tag) {
result = Internal::TAliasedChiOperand(useInstr, tag)
}
}

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.implementation.raw.IR
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -407,6 +407,8 @@ predicate hasUnreachedInstruction(IRFunction func) {
)
}
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction instr) { none() }
import CachedForDebugging
cached

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -106,8 +106,7 @@ private predicate operandEscapesDomain(Operand operand) {
not isArgumentForParameter(_, operand, _) and
not isOnlyEscapesViaReturnArgument(operand) and
not operand.getUse() instanceof ReturnValueInstruction and
not operand.getUse() instanceof ReturnIndirectionInstruction and
not operand instanceof PhiInputOperand
not operand.getUse() instanceof ReturnIndirectionInstruction
}
/**
@@ -191,6 +190,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset, Instr
// A copy propagates the source value.
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
)
or
operand = instr.(PhiInstruction).getAnInputOperand() and
// Using `unknown` ensures termination since we cannot keep incrementing a bit offset
// through the back edge of a loop (or through recursion).
bitOffset = Ints::unknown()
}
private predicate operandEscapesNonReturn(Operand operand) {
@@ -212,9 +216,6 @@ private predicate operandEscapesNonReturn(Operand operand) {
or
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultEscapesNonReturn(operand.getUse())
or
operandEscapesDomain(operand)
}
@@ -236,9 +237,6 @@ private predicate operandMayReachReturn(Operand operand) {
operand.getUse() instanceof ReturnValueInstruction
or
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultMayReachReturn(operand.getUse())
}
private predicate operandReturned(Operand operand, IntValue bitOffset) {
@@ -340,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled()
}
/** Holds if `operand` may (transitively) flow to an `AddressOperand`. */
private predicate consumedAsAddressOperand(Operand operand) {
operand instanceof AddressOperand
or
exists(Operand address |
consumedAsAddressOperand(address) and
operandIsPropagated(operand, _, address.getDef())
)
}
/**
* Holds if `operand` may originate from a base instruction of an allocation,
* and that operand may transitively flow to an `AddressOperand`.
*/
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
consumedAsAddressOperand(operand) and
(
not exists(Configuration::getOldAllocation(allocation)) and
operand.getDef() = allocation.getABaseInstruction()
or
exists(Operand address |
operandIsPropagated(address, _, operand.getDef()) and
propagatedFromAllocationBase(address, allocation)
)
)
}
private predicate propagatedFromNonAllocationBase(Operand operand) {
exists(Instruction def |
def = operand.getDef() and
not operandIsPropagated(_, _, def) and
not def = any(Configuration::Allocation allocation).getABaseInstruction()
)
or
exists(Operand address |
operandIsPropagated(address, _, operand.getDef()) and
propagatedFromNonAllocationBase(address)
)
}
/**
* Holds if we cannot see all producers of an operand for which allocation also flows into.
*/
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
exists(AddressOperand address |
propagatedFromAllocationBase(address, allocation) and
propagatedFromNonAllocationBase(address)
)
}
/**
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
* either because the allocation's address is taken within the function and escapes, or because the
@@ -348,12 +396,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes()
or
exists(IREscapeAnalysisConfiguration config |
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
resultEscapesNonReturn(allocation.getABaseInstruction())
or
operandConsumesEscaped(allocation)
)
or
Configuration::phaseNeedsSoundEscapeAnalysis() and
resultEscapesNonReturn(allocation.getABaseInstruction())
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
}
/**

View File

@@ -1,4 +1,5 @@
private import AliasConfigurationImports
private import codeql.util.Unit
/**
* A memory allocation that can be tracked by the SimpleSSA alias analysis.
@@ -16,3 +17,5 @@ class Allocation extends IRAutomaticVariable {
}
predicate phaseNeedsSoundEscapeAnalysis() { any() }
Unit getOldAllocation(Allocation allocation) { any() }

View File

@@ -15,6 +15,51 @@ private class OldInstruction = Reachability::ReachableInstruction;
import Cached
/**
* Holds if `instruction` is the first instruction that may be followed by
* an `UninitializedGroup` instruction, and the enclosing function of
* `instruction` is `func`.
*/
private predicate isFirstInstructionBeforeUninitializedGroup(
Instruction instruction, IRFunction func
) {
instruction = getChi(any(OldIR::InitializeNonLocalInstruction init)) and
func = instruction.getEnclosingIRFunction()
}
/** Gets the `i`'th `UninitializedGroup` instruction in `func`. */
private UninitializedGroupInstruction getInitGroupInstruction(int i, IRFunction func) {
exists(Alias::VariableGroup vg |
vg.getIRFunction() = func and
vg.getInitializationOrder() = i and
result = uninitializedGroup(vg)
)
}
/**
* Holds if `instruction` is the last instruction in the chain of `UninitializedGroup`
* instructions in `func`. The chain of instructions may be empty in which case
* `instruction` satisfies
* ```
* isFirstInstructionBeforeUninitializedGroup(instruction, func)
* ```
*/
predicate isLastInstructionForUninitializedGroups(Instruction instruction, IRFunction func) {
exists(int i |
instruction = getInitGroupInstruction(i, func) and
not exists(getChi(instruction)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
exists(int i |
instruction = getChi(getInitGroupInstruction(i, func)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
not exists(getInitGroupInstruction(0, func))
}
cached
private module Cached {
cached
@@ -32,6 +77,11 @@ private module Cached {
hasChiNode(_, primaryInstruction)
}
cached
predicate hasChiNodeAfterUninitializedGroup(UninitializedGroupInstruction initGroup) {
hasChiNodeAfterUninitializedGroup(_, initGroup)
}
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldIR::Instruction oldInstruction |
@@ -45,7 +95,8 @@ private module Cached {
}
class TStageInstruction =
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
TUninitializedGroupInstruction;
/**
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +129,8 @@ private module Cached {
or
instr instanceof TChiInstruction
or
instr instanceof TUninitializedGroupInstruction
or
instr instanceof TUnreachedInstruction
}
@@ -123,7 +176,8 @@ private module Cached {
predicate hasModeledMemoryResult(Instruction instruction) {
canModelResultForOldInstruction(getOldInstruction(instruction)) or
instruction instanceof PhiInstruction or // Phis always have modeled results
instruction instanceof ChiInstruction // Chis always have modeled results
instruction instanceof ChiInstruction or // Chis always have modeled results
instruction instanceof UninitializedGroupInstruction // Group initializers always have modeled results
}
cached
@@ -134,16 +188,23 @@ private module Cached {
or
// Chi instructions track virtual variables, and therefore a chi instruction is
// conflated if it's associated with the aliased virtual variable.
exists(OldInstruction oldInstruction | instruction = getChi(oldInstruction) |
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
exists(Instruction input | instruction = getChi(input) |
Alias::getResultMemoryLocation(input).getVirtualVariable() instanceof
Alias::AliasedVirtualVariable
or
// A chi following an `UninitializedGroupInstruction` only happens when the virtual
// variable of the grouped memory location is `{AllAliasedMemory}`.
exists(Alias::GroupedMemoryLocation gml |
input = uninitializedGroup(gml.getGroup()) and
gml.getVirtualVariable() instanceof Alias::AliasedVirtualVariable
)
)
or
// Phi instructions track locations, and therefore a phi instruction is
// conflated if it's associated with a conflated location.
exists(Alias::MemoryLocation location |
instruction = getPhi(_, location) and
not exists(location.getAllocation())
not exists(location.getAnAllocation())
)
}
@@ -205,7 +266,11 @@ private module Cached {
hasMemoryOperandDefinition(oldInstruction, oldOperand, overlap, result)
)
or
instruction = getChi(getOldInstruction(result)) and
(
instruction = getChi(getOldInstruction(result))
or
instruction = getChi(result.(UninitializedGroupInstruction))
) and
tag instanceof ChiPartialOperandTag and
overlap instanceof MustExactlyOverlap
or
@@ -263,6 +328,14 @@ private module Cached {
)
}
cached
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction init) {
exists(Alias::VariableGroup vg |
init = uninitializedGroup(vg) and
result = vg.getAnAllocation().getABaseInstruction().(VariableInstruction).getIRVariable()
)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
@@ -316,6 +389,19 @@ private module Cached {
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
}
private ChiInstruction getChiAfterUninitializedGroup(int i, IRFunction func) {
result =
rank[i + 1](VariableGroup vg, UninitializedGroupInstruction initGroup, ChiInstruction chi,
int r |
initGroup.getEnclosingIRFunction() = func and
chi = getChi(initGroup) and
initGroup = uninitializedGroup(vg) and
r = vg.getInitializationOrder()
|
chi order by r
)
}
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
@@ -329,6 +415,19 @@ private module Cached {
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)
)
or
exists(UninitializedGroupInstruction initGroup, IRFunction func |
chiInstr = getChi(initGroup) and
func = initGroup.getEnclosingIRFunction()
|
chiInstr = getChiAfterUninitializedGroup(0, func) and
isFirstInstructionBeforeUninitializedGroup(result, func)
or
exists(int i |
chiInstr = getChiAfterUninitializedGroup(i + 1, func) and
result = getChiAfterUninitializedGroup(i, func)
)
)
}
cached
@@ -344,14 +443,40 @@ private module Cached {
)
}
/*
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction
*/
private UninitializedGroupInstruction firstInstructionToUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
result = getInitGroupInstruction(0, func) and
kind instanceof GotoEdge
)
}
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
private Instruction getNextUninitializedGroupInstruction(Instruction instruction, EdgeKind kind) {
exists(int i, IRFunction func |
func = instruction.getEnclosingIRFunction() and
instruction = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
if hasChiNodeAfterUninitializedGroup(_, instruction)
then result = getChi(instruction)
else result = getInitGroupInstruction(i + 1, func)
)
or
exists(int i, IRFunction func, UninitializedGroupInstruction initGroup |
func = instruction.getEnclosingIRFunction() and
instruction = getChi(initGroup) and
initGroup = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
result = getInitGroupInstruction(i + 1, func)
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup0(
Instruction instruction, EdgeKind kind
) {
if hasChiNode(_, getOldInstruction(instruction))
then
result = getChi(getOldInstruction(instruction)) and
@@ -371,6 +496,107 @@ private module Cached {
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func, Instruction firstBeforeUninitializedGroup |
isLastInstructionForUninitializedGroups(instruction, func) and
isFirstInstructionBeforeUninitializedGroup(firstBeforeUninitializedGroup, func) and
result = getInstructionSuccessorAfterUninitializedGroup0(firstBeforeUninitializedGroup, kind)
)
}
/**
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction.
*
* Furthermore, the entry block is augmented with `UninitializedGroup` instructions and `Chi`
* instructions. For example, consider this example:
* ```cpp
* int x, y;
* int* p;
* if(b) {
* p = &x;
* escape(&x);
* } else {
* p = &y;
* }
* *p = 42;
*
* int z, w;
* int* q;
* if(b) {
* q = &z;
* } else {
* q = &w;
* }
* *q = 43;
* ```
*
* the unaliased IR for the entry block of this snippet is:
* ```
* v1(void) = EnterFunction :
* m1(unknown) = AliasedDefinition :
* m2(unknown) = InitializeNonLocal :
* r1(glval<bool>) = VariableAddress[b] :
* m3(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m4(int) = Uninitialized[x] : &:r2
* r3(glval<int>) = VariableAddress[y] :
* m5(int) = Uninitialized[y] : &:r3
* r4(glval<int *>) = VariableAddress[p] :
* m6(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m3
* v2(void) = ConditionalBranch : r6
* ```
* and we need to transform this to aliased IR by inserting an `UninitializedGroup`
* instruction for every `VariableGroup` memory location in the function. Furthermore,
* if the `VariableGroup` memory location contains an allocation that escapes we need
* to insert a `Chi` that writes the memory produced by `UninitializedGroup` into
* `{AllAliasedMemory}`. For the above snippet we then end up with:
* ```
* v1(void) = EnterFunction :
* m2(unknown) = AliasedDefinition :
* m3(unknown) = InitializeNonLocal :
* m4(unknown) = Chi : total:m2, partial:m3
* m5(int) = UninitializedGroup[x,y] :
* m6(unknown) = Chi : total:m4, partial:m5
* m7(int) = UninitializedGroup[w,z] :
* r1(glval<bool>) = VariableAddress[b] :
* m8(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m10(int) = Uninitialized[x] : &:r2
* m11(unknown) = Chi : total:m6, partial:m10
* r3(glval<int>) = VariableAddress[y] :
* m12(int) = Uninitialized[y] : &:r3
* m13(unknown) = Chi : total:m11, partial:m12
* r4(glval<int *>) = VariableAddress[p] :
* m14(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m8
* v2(void) = ConditionalBranch : r6
* ```
*
* Here, the group `{x, y}` contains an allocation that escapes (`x`), so there
* is a `Chi` after the `UninitializedGroup` that initializes the memory for the
* `VariableGroup` containing `x`. None of the allocations in `{w, z}` escape so
* there is no `Chi` following that the `UninitializedGroup` that initializes the
* memory of `{w, z}`.
*/
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = firstInstructionToUninitializedGroup(instruction, kind)
or
result = getNextUninitializedGroupInstruction(instruction, kind)
or
result = getInstructionSuccessorAfterUninitializedGroup(instruction, kind)
or
not isFirstInstructionBeforeUninitializedGroup(instruction, _) and
result = getInstructionSuccessorAfterUninitializedGroup0(instruction, kind)
}
cached
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
exists(OldInstruction oldInstruction |
@@ -406,6 +632,16 @@ private module Cached {
exists(IRFunctionBase irFunc |
instr = unreachedInstruction(irFunc) and result = irFunc.getFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction().getFunction()
)
or
exists(UninitializedGroupInstruction initGroup |
instr = chiInstruction(initGroup) and
result = getInstructionAst(initGroup)
)
}
cached
@@ -418,9 +654,16 @@ private module Cached {
)
or
exists(Instruction primaryInstr, Alias::VirtualVariable vvar |
instr = chiInstruction(primaryInstr) and
hasChiNode(vvar, primaryInstr) and
result = vvar.getType()
instr = chiInstruction(primaryInstr) and result = vvar.getType()
|
hasChiNode(vvar, primaryInstr)
or
hasChiNodeAfterUninitializedGroup(vvar, primaryInstr)
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getType()
)
or
instr = reusedPhiInstruction(_) and
@@ -448,6 +691,8 @@ private module Cached {
or
instr = chiInstruction(_) and opcode instanceof Opcode::Chi
or
instr = uninitializedGroup(_) and opcode instanceof Opcode::UninitializedGroup
or
instr = unreachedInstruction(_) and opcode instanceof Opcode::Unreached
}
@@ -460,10 +705,15 @@ private module Cached {
result = blockStartInstr.getEnclosingIRFunction()
)
or
exists(OldInstruction primaryInstr |
exists(Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and result = primaryInstr.getEnclosingIRFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction()
)
or
instr = unreachedInstruction(result)
}
@@ -478,6 +728,8 @@ private module Cached {
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction)
)
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
}
@@ -485,7 +737,7 @@ private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(
private OldInstruction getOldInstruction(Instruction instr) { instr = result }
private ChiInstruction getChi(OldInstruction primaryInstr) { result = chiInstruction(primaryInstr) }
private ChiInstruction getChi(Instruction primaryInstr) { result = chiInstruction(primaryInstr) }
private PhiInstruction getPhi(OldBlock defBlock, Alias::MemoryLocation defLocation) {
result = phiInstruction(defBlock.getFirstInstruction(), defLocation)
@@ -506,6 +758,16 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
)
}
private predicate hasChiNodeAfterUninitializedGroup(
Alias::AliasedVirtualVariable vvar, UninitializedGroupInstruction initGroup
) {
exists(Alias::GroupedMemoryLocation defLocation |
initGroup = uninitializedGroup(defLocation.getGroup()) and
defLocation.getVirtualVariable() = vvar and
Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap
)
}
private import PhiInsertion
/**
@@ -668,19 +930,37 @@ private import DefUse
* potentially very sparse.
*/
module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
func = block.getEnclosingIRFunction() and
i = block.getInstruction(index) and
entryBlock = func.getEntryBlock()
|
if
block = entryBlock and
not i instanceof InitializeNonLocalInstruction and
not i instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index
)
}
bindingset[index, block]
pragma[inline_late]
private int getChiOffset(int index, OldBlock block) { result = getNonChiOffset(index, block) + 1 }
/**
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
*/
Instruction getDefinitionOrChiInstruction(
private Instruction getDefinitionOrChiInstruction0(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(OldInstruction oldInstr, int oldOffset |
oldInstr = defBlock.getInstruction(oldOffset) and
oldOffset >= 0
|
exists(OldInstruction oldInstr, int oldOffset | oldInstr = defBlock.getInstruction(oldOffset) |
// An odd offset corresponds to the `Chi` instruction.
defOffset = oldOffset * 2 + 1 and
defOffset = getChiOffset(oldOffset, defBlock) and
result = getChi(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -689,7 +969,7 @@ module DefUse {
actualDefLocation = defLocation.getVirtualVariable()
or
// An even offset corresponds to the original instruction.
defOffset = oldOffset * 2 and
defOffset = getNonChiOffset(oldOffset, defBlock) and
result = getNewInstruction(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -702,6 +982,54 @@ module DefUse {
hasDefinition(_, defLocation, defBlock, defOffset) and
result = getPhi(defBlock, defLocation) and
actualDefLocation = defLocation
or
exists(
Alias::VariableGroup vg, int index, UninitializedGroupInstruction initGroup,
Alias::GroupedMemoryLocation gml
|
// Add 3 to account for the function prologue:
// v1(void) = EnterFunction
// m1(unknown) = AliasedDefinition
// m2(unknown) = InitializeNonLocal
index = 3 + vg.getInitializationOrder() and
not gml.isMayAccess() and
gml.isSome() and
gml.getGroup() = vg and
vg.getIRFunction().getEntryBlock() = defBlock and
initGroup = uninitializedGroup(vg) and
(defLocation = gml or defLocation = gml.getVirtualVariable())
|
result = initGroup and
defOffset = 2 * index and
actualDefLocation = defLocation
or
result = getChi(initGroup) and
defOffset = 2 * index + 1 and
actualDefLocation = defLocation.getVirtualVariable()
)
}
private ChiInstruction remapGetDefinitionOrChiInstruction(Instruction oldResult) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(oldResult, func) and
isLastInstructionForUninitializedGroups(result, func)
)
}
Instruction getDefinitionOrChiInstruction(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(Instruction oldResult |
oldResult =
getDefinitionOrChiInstruction0(defBlock, defOffset, defLocation, actualDefLocation) and
(
result = remapGetDefinitionOrChiInstruction(oldResult)
or
not exists(remapGetDefinitionOrChiInstruction(oldResult)) and
result = oldResult
)
)
}
/**
@@ -842,8 +1170,20 @@ module DefUse {
block.getInstruction(index) = def and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = index * 2 // The use will be connected to the definition on the original instruction.
then offset = getChiOffset(index, block) // The use will be connected to the definition on the `Chi` instruction.
else offset = getNonChiOffset(index, block) // The use will be connected to the definition on the original instruction.
)
or
exists(UninitializedGroupInstruction initGroup, int index, Overlap overlap, VariableGroup vg |
initGroup.getEnclosingIRFunction().getEntryBlock() = getNewBlock(block) and
vg = defLocation.(Alias::GroupedMemoryLocation).getGroup() and
// EnterFunction + AliasedDefinition + InitializeNonLocal + index
index = 3 + vg.getInitializationOrder() and
initGroup = uninitializedGroup(vg) and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap and hasChiNodeAfterUninitializedGroup(initGroup)
then offset = 2 * index + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = 2 * index // The use will be connected to the definition on the original instruction.
)
}
@@ -904,10 +1244,11 @@ module DefUse {
block.getInstruction(index) = use and
(
// A direct use of the location.
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
offset = getNonChiOffset(index, block)
or
// A `Chi` instruction will include a use of the virtual variable.
hasChiNode(useLocation, use) and offset = (index * 2) + 1
hasChiNode(useLocation, use) and offset = getChiOffset(index, block)
)
)
}
@@ -1057,5 +1398,9 @@ module Ssa {
predicate hasChiInstruction = Cached::hasChiInstructionCached/1;
predicate hasChiNodeAfterUninitializedGroup = Cached::hasChiNodeAfterUninitializedGroup/1;
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
class VariableGroup = Alias::VariableGroup;
}

View File

@@ -1,7 +1,8 @@
import AliasAnalysis
private import SimpleSSAImports
import SimpleSSAPublicImports
private import AliasConfiguration
import AliasConfiguration
private import codeql.util.Unit
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {
exists(Instruction constantBase, int bitOffset |
@@ -48,7 +49,7 @@ predicate canReuseSsaForVariable(IRAutomaticVariable var) {
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAnAllocation() = var }
class MemoryLocation extends TMemoryLocation {
Allocation var;
@@ -57,7 +58,7 @@ class MemoryLocation extends TMemoryLocation {
final string toString() { result = var.getAllocationString() }
final Allocation getAllocation() { result = var }
final Allocation getAnAllocation() { result = var }
final Language::Location getLocation() { result = var.getLocation() }
@@ -77,6 +78,40 @@ class MemoryLocation extends TMemoryLocation {
predicate canReuseSsaForOldResult(Instruction instr) { none() }
abstract class VariableGroup extends Unit {
abstract Allocation getAnAllocation();
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
abstract Language::Location getLocation();
abstract IRFunction getIRFunction();
abstract Language::LanguageType getType();
abstract int getInitializationOrder();
}
class GroupedMemoryLocation extends MemoryLocation {
VariableGroup vg;
GroupedMemoryLocation() { none() }
/** Gets an allocation of this memory location. */
Allocation getAnAllocation() { result = vg.getAnAllocation() }
/** Gets the set of allocations associated with this memory location. */
VariableGroup getGroup() { result = vg }
predicate isMayAccess() { none() }
/** Holds if this memory location represents all the enclosing allocations. */
predicate isAll() { none() }
/** Holds if this memory location represents one or more of the enclosing allocations. */
predicate isSome() { none() }
}
/**
* Represents a set of `MemoryLocation`s that cannot overlap with
* `MemoryLocation`s outside of the set. The `VirtualVariable` will be

View File

@@ -27,6 +27,11 @@ private import implementations.StdPair
private import implementations.StdMap
private import implementations.StdSet
private import implementations.StdString
private import implementations.StdFunction
private import implementations.StdException
private import implementations.StdAllocator
private import implementations.StdAlgorithm
private import implementations.StdMath
private import implementations.Swap
private import implementations.GetDelim
private import implementations.SmartPointer

View File

@@ -7,119 +7,6 @@
import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.Taint
/**
* An allocation function (such as `malloc`) that has an argument for the size
* in bytes.
*/
private class MallocAllocationFunction extends AllocationFunction {
int sizeArg;
MallocAllocationFunction() {
// --- C library allocation
this.hasGlobalOrStdOrBslName("malloc") and // malloc(size)
sizeArg = 0
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"MmAllocateContiguousMemory", // MmAllocateContiguousMemory(size, maxaddress)
"MmAllocateContiguousNodeMemory", // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer)
"MmAllocateContiguousMemorySpecifyCache", // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type)
"MmAllocateContiguousMemorySpecifyCacheNode", // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer)
"MmAllocateNonCachedMemory", // MmAllocateNonCachedMemory(size)
"MmAllocateMappingAddress", // MmAllocateMappingAddress(size, tag)
// --- Windows COM allocation
"CoTaskMemAlloc", // CoTaskMemAlloc(size)
// --- Solaris/BSD kernel memory allocator
"kmem_alloc", // kmem_alloc(size, flags)
"kmem_zalloc", // kmem_zalloc(size, flags)
// --- OpenSSL memory allocation
"CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line)
"CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc", // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"g_malloc", // g_malloc (n_bytes);
"g_try_malloc" // g_try_malloc(n_bytes);
]) and
sizeArg = 0
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"ExAllocatePool", // ExAllocatePool(type, size)
"ExAllocatePool2", // ExAllocatePool2(flags, size, tag)
"ExAllocatePool3", // ExAllocatePool3(flags, size, tag, extparams, extparamscount)
"ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag)
"ExAllocatePoolWithTagPriority", // ExAllocatePoolWithTagPriority(type, size, tag, priority)
"ExAllocatePoolWithQuota", // ExAllocatePoolWithQuota(type, size)
"ExAllocatePoolWithQuotaTag", // ExAllocatePoolWithQuotaTag(type, size, tag)
"ExAllocatePoolZero", // ExAllocatePoolZero(type, size, tag)
"IoAllocateMdl", // IoAllocateMdl(address, size, flag, flag, irp)
"IoAllocateErrorLogEntry", // IoAllocateErrorLogEntry(object, size)
// --- Windows Global / Local legacy allocation
"LocalAlloc", // LocalAlloc(flags, size)
"GlobalAlloc", // GlobalAlloc(flags, size)
// --- Windows System Services allocation
"VirtualAlloc" // VirtualAlloc(address, size, type, flag)
]) and
sizeArg = 1
or
this.hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size)
sizeArg = 2
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"MmAllocatePagesForMdl", // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size)
"MmAllocatePagesForMdlEx", // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags)
"MmAllocateNodePagesForMdlEx" // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags)
]) and
sizeArg = 3
}
override int getSizeArg() { result = sizeArg }
}
/**
* An allocation function (such as `alloca`) that does not require a
* corresponding free (and has an argument for the size in bytes).
*/
private class AllocaAllocationFunction extends AllocationFunction {
int sizeArg;
AllocaAllocationFunction() {
this.hasGlobalName([
// --- stack allocation
"alloca", // // alloca(size)
"__builtin_alloca", // __builtin_alloca(size)
"_alloca", // _alloca(size)
"_malloca" // _malloca(size)
]) and
sizeArg = 0
}
override int getSizeArg() { result = sizeArg }
override predicate requiresDealloc() { none() }
}
/**
* An allocation function (such as `calloc`) that has an argument for the size
* and another argument for the size of those units (in bytes).
*/
private class CallocAllocationFunction extends AllocationFunction {
int sizeArg;
int multArg;
CallocAllocationFunction() {
// --- C library allocation
this.hasGlobalOrStdOrBslName("calloc") and // calloc(num, size)
sizeArg = 1 and
multArg = 0
}
override int getSizeArg() { result = sizeArg }
override int getSizeMult() { result = multArg }
}
/**
* An allocation function (such as `realloc`) that has an argument for the size
* in bytes, and an argument for an existing pointer that is to be reallocated.
@@ -373,6 +260,63 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr {
override predicate requiresDealloc() { not exists(this.getPlacementPointer()) }
}
/**
* Holds if `f` is an allocation function according to the
* extensible `allocationFunctionModel` predicate.
*/
private predicate isAllocationFunctionFromModel(
Function f, string namespace, string type, string name
) {
exists(boolean subtypes | allocationFunctionModel(namespace, type, subtypes, name, _, _, _, _) |
if type = ""
then f.hasQualifiedName(namespace, "", name)
else
exists(Class c |
c.hasQualifiedName(namespace, type) and f.hasQualifiedName(namespace, _, name)
|
if subtypes = true
then f = c.getADerivedClass*().getAMemberFunction()
else f = c.getAMemberFunction()
)
)
}
/**
* An allocation function modeled via the extensible `allocationFunctionModel` predicate.
*/
private class AllocationFunctionFromModel extends AllocationFunction {
string namespace;
string type;
string name;
AllocationFunctionFromModel() { isAllocationFunctionFromModel(this, namespace, type, name) }
final override int getSizeArg() {
exists(string sizeArg |
allocationFunctionModel(namespace, type, _, name, sizeArg, _, _, _) and
result = sizeArg.toInt()
)
}
final override int getSizeMult() {
exists(string sizeMult |
allocationFunctionModel(namespace, type, _, name, _, sizeMult, _, _) and
result = sizeMult.toInt()
)
}
final override int getReallocPtrArg() {
exists(string reallocPtrArg |
allocationFunctionModel(namespace, type, _, name, _, _, reallocPtrArg, _) and
result = reallocPtrArg.toInt()
)
}
final override predicate requiresDealloc() {
allocationFunctionModel(namespace, type, _, name, _, _, _, true)
}
}
private module HeuristicAllocation {
/** A class that maps an `AllocationExpr` to an `HeuristicAllocationExpr`. */
private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr

View File

@@ -7,61 +7,42 @@
import semmle.code.cpp.models.interfaces.Deallocation
/**
* A deallocation function such as `free`.
* Holds if `f` is an deallocation function according to the
* extensible `deallocationFunctionModel` predicate.
*/
private class StandardDeallocationFunction extends DeallocationFunction {
int freedArg;
private predicate isDeallocationFunctionFromModel(
Function f, string namespace, string type, string name
) {
exists(boolean subtypes | deallocationFunctionModel(namespace, type, subtypes, name, _) |
if type = ""
then f.hasQualifiedName(namespace, "", name)
else
exists(Class c |
c.hasQualifiedName(namespace, type) and f.hasQualifiedName(namespace, _, name)
|
if subtypes = true
then f = c.getADerivedClass*().getAMemberFunction()
else f = c.getAMemberFunction()
)
)
}
StandardDeallocationFunction() {
this.hasGlobalOrStdOrBslName([
// --- C library allocation
"free", "realloc"
]) and
freedArg = 0
or
this.hasGlobalName([
// --- OpenSSL memory deallocation
"CRYPTO_free", "CRYPTO_secure_free",
// --- glib memory deallocation
"g_free"
]) and
freedArg = 0
or
this.hasGlobalOrStdName([
// --- Windows Memory Management for Windows Drivers
"ExFreePool", "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeIrp", "IoFreeMdl",
"IoFreeErrorLogEntry", "IoFreeWorkItem", "MmFreeContiguousMemory",
"MmFreeContiguousMemorySpecifyCache", "MmFreeNonCachedMemory", "MmFreeMappingAddress",
"MmFreePagesFromMdl", "MmUnmapReservedMapping", "MmUnmapLockedPages",
"NdisFreeGenericObject", "NdisFreeMemory", "NdisFreeMemoryWithTag", "NdisFreeMdl",
"NdisFreeNetBufferListPool", "NdisFreeNetBufferPool",
// --- Windows Global / Local legacy allocation
"LocalFree", "GlobalFree", "LocalReAlloc", "GlobalReAlloc",
// --- Windows System Services allocation
"VirtualFree",
// --- Windows COM allocation
"CoTaskMemFree", "CoTaskMemRealloc",
// --- Windows Automation
"SysFreeString",
// --- Solaris/BSD kernel memory allocator
"kmem_free"
]) and
freedArg = 0
or
this.hasGlobalOrStdName([
// --- Windows Memory Management for Windows Drivers
"ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList",
"NdisFreeMemoryWithTagPriority", "StorPortFreeMdl", "StorPortFreePool",
// --- NetBSD pool manager
"pool_put", "pool_cache_put"
]) and
freedArg = 1
or
this.hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and
freedArg = 2
/**
* A deallocation function modeled via the extensible `deallocationFunctionModel` predicate.
*/
private class DeallocationFunctionFromModel extends DeallocationFunction {
string namespace;
string type;
string name;
DeallocationFunctionFromModel() { isDeallocationFunctionFromModel(this, namespace, type, name) }
final override int getFreedArg() {
exists(string freedArg |
deallocationFunctionModel(namespace, type, _, name, freedArg) and
result = freedArg.toInt()
)
}
override int getFreedArg() { result = freedArg }
}
/**

View File

@@ -86,6 +86,41 @@ private class StdIterator extends Iterator, Class {
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}
private class StdReverseIterator extends Iterator, Class {
StdReverseIterator() { this.hasQualifiedName(["std", "bsl"], "reverse_iterator") }
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}
private class StdIstreamBufIterator extends Iterator, Class {
StdIstreamBufIterator() { this.hasQualifiedName(["std", "bsl"], "istreambuf_iterator") }
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}
private class StdIstreambufIteratorConstructor extends Constructor, SideEffectFunction,
AliasFunction
{
StdIstreambufIteratorConstructor() { this.getDeclaringType() instanceof StdIstreamBufIterator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
/**
* Gets the `FunctionInput` corresponding to an iterator parameter to
* user-defined operator `op`, at `index`.
@@ -579,23 +614,43 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}
private string beginName() {
result = ["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]
}
/**
* A `begin` member function, or a related function, that returns an iterator.
*/
class BeginFunction extends MemberFunction {
class BeginFunction extends Function {
BeginFunction() {
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
this.getType().getUnspecifiedType() instanceof Iterator
this.getUnspecifiedType() instanceof Iterator and
(
this.hasName(beginName()) and
this instanceof MemberFunction
or
this.hasGlobalOrStdOrBslName(beginName()) and
not this instanceof MemberFunction and
this.getNumberOfParameters() = 1
)
}
}
private string endName() { result = ["end", "cend", "rend", "crend"] }
/**
* An `end` member function, or a related function, that returns an iterator.
*/
class EndFunction extends MemberFunction {
class EndFunction extends Function {
EndFunction() {
this.hasName(["end", "cend", "rend", "crend"]) and
this.getType().getUnspecifiedType() instanceof Iterator
this.getUnspecifiedType() instanceof Iterator and
(
this.hasName(endName()) and
this instanceof MemberFunction
or
this.hasGlobalOrStdOrBslName(endName()) and
this instanceof MemberFunction and
this.getNumberOfParameters() = 1
)
}
}
@@ -603,7 +658,7 @@ class EndFunction extends MemberFunction {
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
class BeginOrEndFunction extends MemberFunction {
class BeginOrEndFunction extends Function {
BeginOrEndFunction() {
this instanceof BeginFunction or
this instanceof EndFunction

View File

@@ -7,6 +7,7 @@
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard functions `printf`, `wprintf` and their glib variants.
@@ -96,7 +97,7 @@ private class Sprintf extends FormattingFunction {
/**
* Implements `Snprintf`.
*/
private class SnprintfImpl extends Snprintf {
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
SnprintfImpl() {
this instanceof TopLevelFunction and
(
@@ -143,6 +144,26 @@ private class SnprintfImpl extends Snprintf {
}
override int getSizeParameterIndex() { result = 1 }
override predicate parameterNeverEscapes(int index) {
// We don't know how many parameters are passed to the function since it's varargs, but they also don't escape.
index = this.getFormatParameterIndex()
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getOutputParameterIndex(false) and buffer = true and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
// We don't know how many parameters are passed to the function since it's varargs, but they also have read side effects.
i = this.getFormatParameterIndex() and buffer = true
}
}
/**

View File

@@ -0,0 +1,115 @@
/**
* Provides models for C++ functions from the `algorithms` header.
*/
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
private class StdPartialSort extends Function, SideEffectFunction, AliasFunction {
StdPartialSort() { this.hasGlobalOrStdName("partial_sort") }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and
buffer = true and
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
override predicate parameterNeverEscapes(int index) {
index = this.getAnIteratorParameterIndex()
or
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
private class StdSortHeap extends Function, SideEffectFunction, AliasFunction {
StdSortHeap() { this.hasGlobalOrStdName("sort_heap") }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and
buffer = true
}
private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
private class StdGenerateN extends Function, SideEffectFunction, AliasFunction {
StdGenerateN() { this.hasGlobalOrStdName("generate_n") }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
private class StdFindIfOrIfNot extends Function, SideEffectFunction, AliasFunction {
StdFindIfOrIfNot() { this.hasGlobalOrStdName(["find_if", "find_if_not"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and buffer = true
or
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
override predicate parameterNeverEscapes(int index) {
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}
override predicate parameterEscapesOnlyViaReturn(int index) {
index = this.getAnIteratorParameterIndex()
}
}

View File

@@ -0,0 +1,256 @@
/**
* Provides models for C++ `allocator` and `allocator_traits` classes.
*/
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
/** The `std::allocator` class. */
class StdAllocator extends Class {
StdAllocator() { this.hasGlobalOrStdOrBslName("allocator") }
}
/** The `std::allocator_traits` class. */
class StdAllocatorTraits extends Class {
StdAllocatorTraits() { this.hasGlobalOrStdOrBslName("allocator_traits") }
}
private class StdAllocatorConstructor extends Constructor, AliasFunction, SideEffectFunction {
StdAllocatorConstructor() { this.getDeclaringType() instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
}
private class StdAllocatorDestructor extends Destructor, AliasFunction, SideEffectFunction {
StdAllocatorDestructor() { this.getDeclaringType() instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
}
private class StdAllocatorAddress extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorAddress() { this.getClassAndName("address") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class StdAllocatorAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorAllocate() { this.getClassAndName("allocate") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class StdAllocatorTraitsAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorTraitsAllocate() {
this.getClassAndName(["allocate", "allocate_at_least"]) instanceof StdAllocatorTraits
}
override predicate parameterNeverEscapes(int index) {
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
}
private class StdAllocatorDeallocate extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorDeallocate() { this.getClassAndName("deallocate") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and
buffer = false and
mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and
buffer = false
}
}
private class StdAllocatorTraitsDeallocate extends MemberFunction, AliasFunction, SideEffectFunction
{
StdAllocatorTraitsDeallocate() {
this.getClassAndName("deallocate") instanceof StdAllocatorTraits
}
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 1 and
buffer = false and
mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = [0, 1] and
buffer = false
}
}
private class StdAllocatorMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorMaxSize() { this.getClassAndName("max_size") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class StdAllocatTraitsMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatTraitsMaxSize() { this.getClassAndName("max_size") instanceof StdAllocatorTraits }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class StdAllocatorConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorConstruct() { this.getClassAndName("construct") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
}
class StdAllocatorTraitsConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorTraitsConstruct() { this.getClassAndName("construct") instanceof StdAllocatorTraits }
override predicate parameterNeverEscapes(int index) {
index = 1 or this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
class StdAllocatorDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorDestroy() { this.getClassAndName("destroy") instanceof StdAllocator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = false
}
}
class StdAllocatorTraitsDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
StdAllocatorTraitsDestroy() { this.getClassAndName("destroy") instanceof StdAllocatorTraits }
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = false
}
}

View File

@@ -2,8 +2,10 @@
* Provides models for C++ containers `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
*/
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.FlowSource
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
/**
* A sequence container template class (for example, `std::vector`) from the
@@ -55,77 +57,10 @@ private class Vector extends StdSequenceContainer {
Vector() { this.hasQualifiedName(["std", "bsl"], "vector") }
}
/**
* Additional model for standard container constructors that reference the
* value type of the container (that is, the `T` in `std::vector<T>`). For
* example the fill constructor:
* ```
* std::vector<std::string> v(100, potentially_tainted_string);
* ```
*/
private class StdSequenceContainerConstructor extends Constructor, TaintFunction {
StdSequenceContainerConstructor() {
this.getDeclaringType() instanceof Vector or
this.getDeclaringType() instanceof Deque or
this.getDeclaringType() instanceof List or
this.getDeclaringType() instanceof ForwardList
}
/**
* Gets the index of a parameter to this function that is a reference to the
* value type of the container.
*/
int getAValueTypeParameterIndex() {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
/**
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// taint flow from any parameter of the value type to the returned object
(
input.isParameterDeref(this.getAValueTypeParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(
output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object
or
output.isQualifierObject()
)
}
}
/**
* The standard container function `data`.
*/
private class StdSequenceContainerData extends TaintFunction {
StdSequenceContainerData() {
this.getClassAndName("data") instanceof Array or
this.getClassAndName("data") instanceof Vector
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from container itself (qualifier) to return value
input.isQualifierObject() and
output.isReturnValueDeref()
or
// reverse flow from returned reference to the qualifier (for writes to
// `data`)
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
* The standard container functions `push_back` and `push_front`.
*/
class StdSequenceContainerPush extends MemberFunction {
class StdSequenceContainerPush extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerPush() {
this.getClassAndName("push_back") instanceof Vector or
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
@@ -141,41 +76,115 @@ class StdSequenceContainerPush extends MemberFunction {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
}
private class StdSequenceContainerPushModel extends StdSequenceContainerPush, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to qualifier
input.isParameterDeref(0) and
output.isQualifierObject()
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
// the `std::vector<bool>` specialization doesn't take a reference as a
// parameter. So we need to check that the parameter is actually a
// reference.
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
/**
* The standard container functions `front` and `back`.
*/
private class StdSequenceContainerFrontBack extends TaintFunction {
StdSequenceContainerFrontBack() {
this.getClassAndName(["front", "back"]) instanceof Array or
this.getClassAndName(["front", "back"]) instanceof Deque or
this.getClassAndName("front") instanceof ForwardList or
this.getClassAndName(["front", "back"]) instanceof List or
this.getClassAndName(["front", "back"]) instanceof Vector
private class StdSequenceContainerPopFrontOrBack extends MemberFunction, SideEffectFunction,
AliasFunction
{
StdSequenceContainerPopFrontOrBack() {
this.getClassAndName("pop_back") instanceof Vector or
this.getClassAndName("pop_front") instanceof ForwardList or
this.getClassAndName(["pop_front", "pop_back"]) instanceof Deque or
this.getClassAndName(["pop_front", "pop_back"]) instanceof List
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from object to returned reference
input.isQualifierObject() and
output.isReturnValueDeref()
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and
buffer = false
}
}
private class StdSequenceContainerClear extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerClear() {
this.getClassAndName("clear") instanceof Vector or
this.getClassAndName("clear") instanceof Deque or
this.getClassAndName("clear") instanceof ForwardList or
this.getClassAndName("clear") instanceof List
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and
buffer = false
}
}
private class StdVectorReserve extends MemberFunction, SideEffectFunction, AliasFunction {
StdVectorReserve() { this.getClassAndName("reserve") instanceof Vector }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and
buffer = false
}
}
/**
* The standard container functions `insert` and `insert_after`.
*/
class StdSequenceContainerInsert extends MemberFunction {
class StdSequenceContainerInsert extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerInsert() {
this.getClassAndName("insert") instanceof Deque or
this.getClassAndName("insert") instanceof List or
@@ -196,83 +205,138 @@ class StdSequenceContainerInsert extends MemberFunction {
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
private class StdSequenceContainerInsertModel extends StdSequenceContainerInsert, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to container itself (qualifier) and return value
(
input.isQualifierObject() or
input.isParameterDeref(this.getAValueTypeParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
(
output.isQualifierObject() or
output.isReturnValue()
)
private class StdSequenceContainerFrontBack extends MemberFunction, SideEffectFunction,
AliasFunction
{
StdSequenceContainerFrontBack() {
this.getClassAndName(["front", "back"]) instanceof Deque or
this.getClassAndName(["front", "back"]) instanceof List or
this.getClassAndName(["front", "back"]) instanceof Vector or
// forward_list does not have a 'back' member function
this.getClassAndName("front") instanceof ForwardList
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
override predicate parameterNeverEscapes(int index) { index = -1 }
/**
* The standard container function `assign`.
*/
private class StdSequenceContainerAssign extends TaintFunction {
StdSequenceContainerAssign() {
this.getClassAndName("assign") instanceof Deque or
this.getClassAndName("assign") instanceof ForwardList or
this.getClassAndName("assign") instanceof List or
this.getClassAndName("assign") instanceof Vector
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
/**
* Gets the index of a parameter to this function that is a reference to the
* value type of the container.
*/
int getAValueTypeParameterIndex() {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
override predicate hasOnlySpecificReadSideEffects() { any() }
/**
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to container itself (qualifier)
(
input.isParameterDeref(this.getAValueTypeParameterIndex()) or
input.isParameter(this.getAnIteratorParameterIndex())
) and
output.isQualifierObject()
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
/**
* The standard container functions `at` and `operator[]`.
*/
class StdSequenceContainerAt extends MemberFunction {
class StdSequenceContainerAt extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerAt() {
this.getClassAndName(["at", "operator[]"]) instanceof Array or
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
this.getClassAndName(["at", "operator[]"]) instanceof Vector
}
}
private class StdSequenceContainerAtModel extends StdSequenceContainerAt, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
input.isQualifierObject() and
output.isReturnValueDeref()
or
// reverse flow from returned reference to the qualifier
input.isReturnValueDeref() and
output.isQualifierObject()
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
private class StdSequenceContainerMemberEquals extends MemberFunction, SideEffectFunction,
AliasFunction
{
StdSequenceContainerMemberEquals() {
this.getClassAndName("operator==") instanceof Array or
this.getClassAndName("operator==") instanceof Deque or
this.getClassAndName("operator==") instanceof Vector
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = -1 or index = 0 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
or
i = 0 and buffer = false
}
}
private class StdSequenceContainerEquals extends Function, SideEffectFunction, AliasFunction {
StdSequenceContainerEquals() {
this.hasGlobalOrStdOrBslName("operator==") and
not this instanceof MemberFunction and
this.getNumberOfParameters() = 2 and
(
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector and
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector
or
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List and
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List
or
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque and
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque
)
}
override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = [0, 1] and buffer = false
}
}
/**
@@ -297,20 +361,6 @@ class StdSequenceEmplace extends MemberFunction {
}
}
private class StdSequenceEmplaceModel extends StdSequenceEmplace, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter except the position iterator to qualifier and return value
// (here we assume taint flow from any constructor parameter to the constructed object)
input.isParameterDeref([1 .. this.getNumberOfParameters() - 1]) and
(
output.isQualifierObject() or
output.isReturnValue()
)
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
* The standard vector `emplace` function.
*/
@@ -318,6 +368,115 @@ class StdVectorEmplace extends StdSequenceEmplace {
StdVectorEmplace() { this.getDeclaringType() instanceof Vector }
}
private class StdSequenceSize extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceSize() {
this.getClassAndName("size") instanceof Vector
or
this.getClassAndName("size") instanceof List
or
this.getClassAndName("size") instanceof Deque
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
private class StdSequenceDestructor extends Destructor, SideEffectFunction, AliasFunction {
StdSequenceDestructor() {
this.getDeclaringType() instanceof Vector
or
this.getDeclaringType() instanceof List
or
this.getDeclaringType() instanceof Deque
}
private Destructor getElementDestructor() {
result.getDeclaringType() = this.getTemplateArgument(0)
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() {
this.getElementDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
or
not exists(this.getElementDestructor())
}
override predicate hasOnlySpecificWriteSideEffects() {
this.getElementDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
or
not exists(this.getElementDestructor())
}
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
private class StdSequenceConstructor extends Constructor, SideEffectFunction, AliasFunction {
StdSequenceConstructor() {
this.getDeclaringType() instanceof Vector
or
this.getDeclaringType() instanceof List
or
this.getDeclaringType() instanceof Deque
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
private class InitializerList extends Class {
InitializerList() { this.hasQualifiedName(["std", "bsl"], "initializer_list") }
Type getElementType() { result = this.getTemplateArgument(0) }
}
private class InitializerListConstructor extends Constructor, SideEffectFunction, AliasFunction {
InitializerListConstructor() { this.getDeclaringType() instanceof InitializerList }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
}
/**
* The standard vector `emplace_back` function.
*/
@@ -340,17 +499,6 @@ class StdSequenceEmplaceBack extends MemberFunction {
}
}
private class StdSequenceEmplaceBackModel extends StdSequenceEmplaceBack, TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter to qualifier
// (here we assume taint flow from any constructor parameter to the constructed object)
input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
* The standard vector `emplace_back` function.
*/

View File

@@ -0,0 +1,38 @@
/**
* Provides models for the C++ `std::exception` class and subclasses.
*/
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/** The `std::exception` class. */
class StdException extends Class {
StdException() { this.hasGlobalOrStdOrBslName("exception") }
}
/** The `std::bad_alloc` class. */
class StdBadAllocException extends Class {
StdBadAllocException() { this.hasGlobalOrStdOrBslName("bad_alloc") }
}
private class StdBadAllocExceptionConstructor extends Constructor, SideEffectFunction, AliasFunction
{
StdBadAllocExceptionConstructor() { this.getDeclaringType() instanceof StdBadAllocException }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
}

View File

@@ -0,0 +1,53 @@
/**
* Provides models for C++ `std::function` class.
*/
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
/**
* An instantiation of the `std::function` class template.
*/
class StdFunction extends ClassTemplateInstantiation {
StdFunction() { this.hasGlobalOrStdOrBslName("function") }
}
private class StdFunctionConstructor extends Constructor, SideEffectFunction, AliasFunction {
StdFunctionConstructor() { this.getDeclaringType() instanceof StdFunction }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}
}
private class StdFunctionDestructor extends Destructor, SideEffectFunction, AliasFunction {
StdFunctionDestructor() { this.getDeclaringType() instanceof StdFunction }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}

View File

@@ -5,6 +5,8 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
/**
* The `std::map` and `std::unordered_map` template classes.
@@ -16,7 +18,9 @@ private class MapOrUnorderedMap extends Class {
/**
* Additional model for map constructors using iterator inputs.
*/
private class StdMapConstructor extends Constructor, TaintFunction {
private class StdMapConstructor extends Constructor, TaintFunction, AliasFunction,
SideEffectFunction
{
StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
/**
@@ -35,6 +39,23 @@ private class StdMapConstructor extends Constructor, TaintFunction {
output.isQualifierObject()
)
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
/**
@@ -133,7 +154,7 @@ class StdMapAt extends MemberFunction {
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
}
private class StdMapAtModels extends StdMapAt, TaintFunction {
private class StdMapAtModels extends StdMapAt, TaintFunction, AliasFunction, SideEffectFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
input.isQualifierObject() and
@@ -144,6 +165,18 @@ private class StdMapAtModels extends StdMapAt, TaintFunction {
output.isQualifierObject()
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
@@ -187,3 +220,63 @@ private class StdMapEqualRange extends TaintFunction {
output.isReturnValue()
}
}
class StdMapDestructor extends Destructor, SideEffectFunction, AliasFunction {
StdMapDestructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
private class StdMapClear extends MemberFunction, SideEffectFunction, AliasFunction {
StdMapClear() { this.getClassAndName("clear") instanceof MapOrUnorderedMap }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and
buffer = false and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and
buffer = false
}
}
class StdMapSize extends MemberFunction, SideEffectFunction, AliasFunction {
StdMapSize() { this.getClassAndName("size") instanceof MapOrUnorderedMap }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and
buffer = false
}
}

View File

@@ -0,0 +1,108 @@
/**
* Provides models for C++ functions from the `cmath` header.
*/
private import semmle.code.cpp.models.interfaces.SideEffect
private import semmle.code.cpp.models.interfaces.Alias
private class LdExp extends Function, SideEffectFunction {
LdExp() { this.hasGlobalOrStdOrBslName(["ldexp", "ldexpf", "ldexpl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Abs extends Function, SideEffectFunction {
Abs() { this.hasGlobalOrStdOrBslName(["abs", "fabs", "fabsf", "fabsl", "llabs", "imaxabs"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Div extends Function, SideEffectFunction {
Div() { this.hasGlobalOrStdOrBslName(["div", "ldiv", "lldiv", "imaxdiv"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class FMod extends Function, SideEffectFunction {
FMod() { this.hasGlobalOrStdOrBslName(["fmod", "fmodf", "fmodl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Remainder extends Function, SideEffectFunction {
Remainder() { this.hasGlobalOrStdOrBslName(["remainder", "remainderf", "remainderl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Remquo extends Function, SideEffectFunction {
Remquo() { this.hasGlobalOrStdOrBslName(["remquo", "remquof", "remquol"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
buffer = false and
mustWrite = true
}
}
private class Fma extends Function, SideEffectFunction {
Fma() { this.hasGlobalOrStdOrBslName(["fma", "fmaf", "fmal"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Fmax extends Function, SideEffectFunction {
Fmax() { this.hasGlobalOrStdOrBslName(["fmax", "fmaxf", "fmaxl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Fmin extends Function, SideEffectFunction {
Fmin() { this.hasGlobalOrStdOrBslName(["fmin", "fminf", "fminl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Fdim extends Function, SideEffectFunction {
Fdim() { this.hasGlobalOrStdOrBslName(["fdim", "fdimf", "fdiml"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
}
private class Nan extends Function, SideEffectFunction, AliasFunction {
Nan() { this.hasGlobalOrStdOrBslName(["nan", "nanf", "nanl"]) }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = 0 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = true
}
}

View File

@@ -3,6 +3,8 @@
*/
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* An instantiation of `std::pair<T1, T2>`.
@@ -37,7 +39,9 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
/**
* Additional model for `std::pair` constructors.
*/
private class StdPairConstructor extends Constructor, TaintFunction {
private class StdPairConstructor extends Constructor, TaintFunction, AliasFunction,
SideEffectFunction
{
StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
/**
@@ -59,4 +63,77 @@ private class StdPairConstructor extends Constructor, TaintFunction {
output.isQualifierObject()
)
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
// All the constructor parameters are references with the exception of this one:
// ```
// template<class... Args1, class... Args2>
// pair(std::piecewise_construct_t, std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
// ```
// So we need to check that the parameters are actually references
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}
private class StdPairDestructor extends Destructor, AliasFunction, SideEffectFunction {
StdPairDestructor() { this.getDeclaringType() instanceof StdPair }
private Type getFirstType() { result = this.getDeclaringType().getTemplateArgument(0) }
private Type getSecondType() { result = this.getDeclaringType().getTemplateArgument(0) }
private Type getAType() { result = [this.getFirstType(), this.getSecondType()] }
/**
* Gets the destructor associated with the base type of this pair
*/
private Destructor getADestructor() { result.getDeclaringType() = this.getAType() }
override predicate hasOnlySpecificReadSideEffects() {
this.getADestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
or
// If there's no declared destructor for the base type then it won't have
// any strange read side effects.
not exists(this.getADestructor())
}
override predicate hasOnlySpecificWriteSideEffects() {
this.getADestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
or
// If there's no declared destructor for the base type then it won't have
// any strange write side effects.
not exists(this.getADestructor())
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate parameterNeverEscapes(int index) {
this.getADestructor().(AliasFunction).parameterNeverEscapes(index)
or
// If there's no declared destructor for the base type then it won't cause
// anything to escape.
not exists(this.getADestructor()) and
index = -1
}
}

View File

@@ -7,6 +7,8 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias
/**
* The `std::basic_string` template class instantiations.
@@ -66,7 +68,7 @@ abstract private class StdStringTaintFunction extends TaintFunction {
* Gets the index of a parameter to this function that is an iterator.
*/
final int getAnIteratorParameterIndex() {
this.getParameter(result).getType() instanceof Iterator
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
}
@@ -78,7 +80,9 @@ abstract private class StdStringTaintFunction extends TaintFunction {
* std::string b(a.begin(), a.end());
* ```
*/
private class StdStringConstructor extends Constructor, StdStringTaintFunction {
private class StdStringConstructor extends Constructor, StdStringTaintFunction, SideEffectFunction,
AliasFunction
{
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -94,6 +98,42 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
output.isQualifierObject()
)
}
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
private class StdStringDestructor extends Destructor, SideEffectFunction, AliasFunction {
StdStringDestructor() { this.getDeclaringType() instanceof StdBasicString }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
/**
@@ -164,7 +204,7 @@ private class StdStringFrontBack extends StdStringTaintFunction {
/**
* The (non-member) `std::string` function `operator+`.
*/
private class StdStringPlus extends StdStringTaintFunction {
private class StdStringPlus extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringPlus() {
this.hasQualifiedName(["std", "bsl"], "operator+") and
this.getUnspecifiedType() instanceof StdBasicString
@@ -178,6 +218,22 @@ private class StdStringPlus extends StdStringTaintFunction {
) and
output.isReturnValue()
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
or
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
buffer = true
}
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
/**
@@ -185,7 +241,7 @@ private class StdStringPlus extends StdStringTaintFunction {
* All of these functions combine the existing string with a new
* string (or character) from one of the arguments.
*/
private class StdStringAppend extends StdStringTaintFunction {
private class StdStringAppend extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringAppend() {
this.getClassAndName(["operator+=", "append", "replace"]) instanceof StdBasicString
}
@@ -210,6 +266,22 @@ private class StdStringAppend extends StdStringTaintFunction {
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and mustWrite = false and buffer = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = [-1, 0] and buffer = true
}
override predicate parameterNeverEscapes(int index) { index = [-1, 0] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
/**
@@ -301,7 +373,7 @@ private class StdStringSubstr extends StdStringTaintFunction {
/**
* The `std::string` functions `at` and `operator[]`.
*/
private class StdStringAt extends StdStringTaintFunction {
private class StdStringAt extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -315,6 +387,22 @@ private class StdStringAt extends StdStringTaintFunction {
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
/**
@@ -324,6 +412,54 @@ private class StdBasicIStream extends ClassTemplateInstantiation {
StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") }
}
private class StdBasicIfStream extends ClassTemplateInstantiation {
StdBasicIfStream() { this.hasQualifiedName(["std", "bsl"], "basic_ifstream") }
}
class StdBasicIfStreamConstructor extends Constructor, SideEffectFunction, AliasFunction {
StdBasicIfStreamConstructor() { this.getDeclaringType() instanceof StdBasicIfStream }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
exists(Type t | t = this.getParameter(i).getUnspecifiedType() |
t instanceof PointerType and buffer = true
or
t instanceof ReferenceType and buffer = false
)
}
}
class StdBasicIfStreamDestructor extends Destructor, SideEffectFunction, AliasFunction {
StdBasicIfStreamDestructor() { this.getDeclaringType() instanceof StdBasicIfStream }
override predicate parameterNeverEscapes(int index) { index = -1 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = -1 and buffer = false and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}
/**
* The `std::istream` function `operator>>` (defined as a member function).
*/
@@ -542,6 +678,33 @@ private class StdBasicOStream extends ClassTemplateInstantiation {
StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") }
}
private class StdStringLessThan extends Function, AliasFunction, SideEffectFunction {
StdStringLessThan() {
this.hasQualifiedName(["std", "bsl"], "operator<") and
this.getNumberOfParameters() = 2 and
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
StdBasicString and
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
StdBasicString
}
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
none()
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = [0, 1] and buffer = false
}
}
/**
* The `std::ostream` functions `operator<<` (defined as a member function),
* `put` and `write`.

View File

@@ -89,6 +89,14 @@ abstract class AllocationFunction extends Function {
predicate requiresDealloc() { any() }
}
/**
* Holds if an external allocation model exists for the given parameters.
*/
extensible predicate allocationFunctionModel(
string namespace, string type, boolean subtypes, string name, string sizeArg, string multArg,
string reallocPtrArg, boolean requiresDealloc
);
/**
* An `operator new` or `operator new[]` function that may be associated with
* `new` or `new[]` expressions. Note that `new` and `new[]` are not function

View File

@@ -34,6 +34,13 @@ abstract class DeallocationFunction extends Function {
int getFreedArg() { none() }
}
/**
* Holds if an external deallocation model exists for the given parameters.
*/
extensible predicate deallocationFunctionModel(
string namespace, string type, boolean subtypes, string name, string freedArg
);
/**
* An `operator delete` or `operator delete[]` function that may be associated
* with `delete` or `delete[]` expressions. Note that `delete` and `delete[]`

View File

@@ -95,7 +95,7 @@ module FlowFromFree<FlowFromFreeParamSig P> {
e = any(StoreInstruction store).getDestinationAddress().getUnconvertedResultExpression()
)
or
n.asExpr() instanceof ArrayExpr
[n.asExpr(), n.asIndirectExpr()] instanceof ArrayExpr
}
}

Some files were not shown because too many files have changed in this diff Show More