Compare commits

...

166 Commits

Author SHA1 Message Date
Andrew Eisenberg
39c3efb8c2 Add autofix reminder and label manager
Remind query authors to validate their changes in autofix before merging.
2024-08-08 12:28:43 -07:00
Jeroen Ketema
46b92f372b Merge pull request #17090 from jketema/macos-unsupported
Remove EOL macOS versions from the supported platforms list
2024-07-29 17:41:28 +02:00
Ian Lynagh
1530037eae Merge pull request #17071 from igfoo/igfoo/dep_env
Java/Kotlin: Remove support for deprecated SOURCE_ARCHIVE and TRAP_FOLDER
2024-07-29 14:55:50 +01:00
Jeroen Ketema
9dff666cb3 Remove EOL macOS versions from the supported platforms list 2024-07-29 15:28:44 +02:00
Joe Farebrother
58689c90fb Merge pull request #16893 from joefarebrother/python-cookie-injectio-promote
Python: Promote cookie injection query from experimental
2024-07-29 10:17:01 +01:00
Owen Mansel-Chan
0a7772d8a7 Merge pull request #17014 from owen-mc/go/provenance-postprocess-qltest
Go: Add support for provenance pretty-printing as a qltest postprocess step
2024-07-29 10:09:05 +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
Owen Mansel-Chan
f307f272d5 Go: Use provenance pretty-printing as a qltest post-process step 2024-07-28 21:31:50 +01:00
Owen Mansel-Chan
6960c5232b Go: Add support for provenance pretty-printing as a qltest post-process step 2024-07-28 21:31:50 +01: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
Joe Farebrother
ebeb187fd9 Remove unneeded experimental file 2024-07-25 23:16:48 +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
Ian Lynagh
225d2915e5 Java/Kotlin: Add changenote for dropping SOURCE_ARCHIVE/TRAP_FOLDER 2024-07-25 12:48:55 +01:00
Ian Lynagh
e4b9335ce0 Kotlin: Remove support for deprecated SOURCE_ARCHIVE and TRAP_FOLDER 2024-07-25 12:46:13 +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
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
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
Alexandre Boulgakov
06a9599906 C++: Update stats for using enum. 2024-07-22 17:42:31 +01: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
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
Joe Farebrother
661a4126ac Add change note 2024-07-19 09:23:33 +01:00
Joe Farebrother
baf51334e4 Update documentation 2024-07-19 09:13:30 +01: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
Anders Schack-Mulligen
94078e851c Shared: Add support for provenance pretty-printing as a qltest postprocess step. 2024-07-18 15:34:30 +02: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
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
Joe Farebrother
070d67816d Remove experimental version 2024-07-16 16:50:10 +01:00
Joe Farebrother
8d93c3a852 Move to cwe-20 2024-07-16 16:50:08 +01:00
Joe Farebrother
e885f1f8c4 Add documentation 2024-07-16 16:50:05 +01:00
Joe Farebrother
983bdb92a1 Add test cases + remove redundant import 2024-07-16 16:50:00 +01:00
Joe Farebrother
123214cb2b Promoto cookie injection query 2024-07-16 16:49:56 +01:00
Owen Mansel-Chan
d4bfab4735 Accept minor copy-editing suggestions. 2024-07-09 07:00:01 +01: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
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
Rasmus Wriedt Larsen
173cd13ded Python: Add test for impossible isinstance flow 2024-07-08 12:06:53 +02:00
Owen Mansel-Chan
60b9d19d72 Add explicit relation between "reverse-dns" and "all" 2024-06-29 21:29:21 +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
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
Alex Ford
f217de9623 Ruby: Move SensitiveDataSource logic into a private module 2024-06-18 16:58:30 +01:00
Alex Ford
6a46fb54c5 Ruby: Add SensitiveDataSource abstract class 2024-06-18 12:11:28 +01: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
220 changed files with 91670 additions and 5310 deletions

View File

@@ -0,0 +1,41 @@
# This workflow ensures that if the "No Autofix Validation Required" label is
# added to a pull request, the "Autofix Validation Required" label is removed.
name: Autofix Label Manager
on:
pull_request_target:
types: [labeled]
# Allows manual triggering of the workflow for testing
workflow_dispatch:
jobs:
check-to-remove-autofix-label:
env:
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REQUIRES_AUTOFIX_LABEL: "Autofix Validation Required"
DOES_NOT_REQUIRE_AUTOFIX_LABEL: "No Autofix Validation Required"
LABEL_ADDED: ${{ github.event.label.name }}
runs-on: ubuntu-latest
steps:
- name: Check if label "No Autofix Validation Required" is added
shell: bash
run: |
if [ "$LABEL_ADDED" != "$DOES_NOT_REQUIRE_AUTOFIX_LABEL" ]; then
echo "Label $DOES_NOT_REQUIRE_AUTOFIX_LABEL was not added."
exit 0
fi
echo "Label $DOES_NOT_REQUIRE_AUTOFIX_LABEL was added."
# Check if Label $REQUIRES_AUTOFIX_LABEL exists and remove it
REQUIRES_AUTOFIX_LABEL_EXISTS=$(gh api /repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/labels | jq --arg label "Autofix Validation Required" '.[] | select(.name==$label) | .name')
if [ "$REQUIRES_AUTOFIX_LABEL_EXISTS" == "$REQUIRES_AUTOFIX_LABEL" ]; then
gh api -X DELETE "/repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/labels/$REQUIRES_AUTOFIX_LABEL"
echo "$REQUIRES_AUTOFIX_LABEL Label removed."
else
echo "$REQUIRES_AUTOFIX_LABEL Label does not exist or was already removed."
fi

56
.github/workflows/autofix-reminder.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
# This workflow creates a reminder to query authors to test their queries
# in autofix.
name: Autofix reminder
permissions:
contents: read
pull-requests: write
issues: write
on:
pull_request:
branches:
- main
- "rc/*"
paths:
- "**/*.qhelp"
- "**/*.ql"
- "**/*.qll"
# This workflow
- ".github/workflows/autofix-reminder.yml"
workflow_dispatch:
jobs:
autofix-reminder:
env:
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REQUIRES_AUTOFIX_LABEL: "Autofix Validation Required"
DOES_NOT_REQUIRE_AUTOFIX_LABEL: "No Autofix Validation Required"
runs-on: ubuntu-latest
steps:
- name: Check existing labels
id: label_check
shell: bash
run: |
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" | jq -r '.[].name' > labels.txt
if grep -q -x -e "${REQUIRES_AUTOFIX_LABEL}" labels.txt || grep -q -x -e "${DOES_NOT_REQUIRE_AUTOFIX_LABEL}" labels.txt; then
echo "Stopping workflow due to label presence."
echo "should_continue=false" >> $GITHUB_OUTPUT
else
echo "Add $REQUIRES_AUTOFIX_LABEL label."
echo "should_continue=true" >> $GITHUB_OUTPUT
fi
- name: Add label
if: steps.label_check.outputs.should_continue == 'true'
run: |
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" -X POST -f "labels[]=$REQUIRES_AUTOFIX_LABEL"
- name: Comment on PR
if: steps.label_check.outputs.should_continue == 'true'
run: gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" -X POST --field body="This pull request updates '.ql', '.qll', or '.qhelp' files, Please validate that autofixes generated based on these changes are valid. See [the documentation](https://github.com/github/codeql-team/blob/main/docs/best-practices/validating-autofix-for-query-changes.md) (internal access required). If autofix validation is not required, please add the label '${DOES_NOT_REQUIRE_AUTOFIX_LABEL}' to this pull request."

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

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

@@ -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

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 1.3.0
version: 1.3.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

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

@@ -215,19 +215,16 @@ 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) {
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`.
*/
predicate compatibleTypes(Type t1, Type t2) {
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
}
@@ -243,7 +240,11 @@ 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 {

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.
*
@@ -1025,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

@@ -994,9 +994,6 @@ DataFlowType getNodeType(Node n) {
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`.
@@ -1097,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 =

View File

@@ -338,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
@@ -346,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

@@ -146,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,7 @@ 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;
@@ -227,13 +227,15 @@ private newtype TMemoryLocation =
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()
@@ -294,9 +296,9 @@ 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;
@@ -424,7 +426,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
* `{a, b}` into a memory location that represents _all_ of the allocations
* in the set.
*/
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation {
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation0 {
VariableGroup vg;
boolean isMayAccess;
boolean isAll;
@@ -528,7 +530,7 @@ class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
/**
* 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;
@@ -555,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;
@@ -589,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;
@@ -620,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
@@ -648,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.
@@ -861,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 |
@@ -905,9 +941,9 @@ 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
(
@@ -948,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

@@ -933,11 +933,15 @@ module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(IRFunction func | func = block.getEnclosingIRFunction() |
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
func = block.getEnclosingIRFunction() and
i = block.getInstruction(index) and
entryBlock = func.getEntryBlock()
|
if
getNewBlock(block) = func.getEntryBlock() and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
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
)

View File

@@ -338,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
@@ -346,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

@@ -933,11 +933,15 @@ module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(IRFunction func | func = block.getEnclosingIRFunction() |
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
func = block.getEnclosingIRFunction() and
i = block.getInstruction(index) and
entryBlock = func.getEntryBlock()
|
if
getNewBlock(block) = func.getEntryBlock() and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
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
)

View File

@@ -1,7 +1,7 @@
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) {

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

@@ -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

@@ -4,6 +4,8 @@
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
@@ -58,7 +60,7 @@ private class Vector extends StdSequenceContainer {
/**
* 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
@@ -74,12 +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>`
}
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) {
// 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
}
}
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 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
@@ -100,17 +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 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 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
}
}
/**
* 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
}
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
}
}
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
}
}
/**
@@ -142,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.
*/

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.
@@ -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

@@ -485,10 +485,17 @@ namespace_decls(
int bodylocation: @location_default ref
);
case @using.kind of
1 = @using_declaration
| 2 = @using_directive
| 3 = @using_enum_declaration
;
usings(
unique int id: @using,
int element_id: @element ref,
int location: @location_default ref
int location: @location_default ref,
int kind: int ref
);
/** The element which contains the `using` declaration. */
@@ -1358,6 +1365,8 @@ funbind(
@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr
/*
Binary encoding of the allocator form.
case @allocator.form of
0 = plain
| 1 = alignment
@@ -1376,11 +1385,13 @@ expr_allocator(
);
/*
Binary encoding of the deallocator form.
case @deallocator.form of
0 = plain
| 1 = size
| 2 = alignment
| 3 = size_and_alignment
| 4 = destroying_delete
;
*/

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: partial

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Support using-enum declarations.
compatibility: partial
usings.rel: run usings.qlo

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) and
if target instanceof @namespace then kind = 2 else kind = 1
select u, target, loc, kind

View File

@@ -38,11 +38,18 @@ private string getEofValue() {
private predicate checkedForEof(ScanfFunctionCall call) {
exists(IRGuardCondition gc |
exists(Instruction i | i.getUnconvertedResultExpression() = call |
// call == EOF
gc.comparesEq(valueNumber(i).getAUse(), getEofValue().toInt(), _, _)
exists(int val | gc.comparesEq(valueNumber(i).getAUse(), val, _, _) |
// call == EOF
val = getEofValue().toInt()
or
// call == [any positive number]
val > 0
)
or
// call < 0 (EOF is guaranteed to be negative)
gc.comparesLt(valueNumber(i).getAUse(), 0, true, _)
exists(int val | gc.comparesLt(valueNumber(i).getAUse(), val, true, _) |
// call < [any non-negative number] (EOF is guaranteed to be negative)
val >= 0
)
)
)
}

View File

@@ -15,6 +15,7 @@
import cpp
import semmle.code.cpp.models.Models
import semmle.code.cpp.commons.Buffer
predicate baseType(AllocationExpr alloc, Type base) {
exists(PointerType pointer |
@@ -30,7 +31,8 @@ predicate baseType(AllocationExpr alloc, Type base) {
}
predicate decideOnSize(Type t, int size) {
// If the codebase has more than one type with the same name, it can have more than one size.
// If the codebase has more than one type with the same name, it can have more than one size. For
// most purposes in this query, we use the smallest.
size = min(t.getSize())
}
@@ -45,7 +47,8 @@ where
size = 0 or
(allocated / size) * size = allocated
) and
not basesize > allocated // covered by SizeCheck.ql
not basesize > allocated and // covered by SizeCheck.ql
not memberMayBeVarSize(base.getUnspecifiedType(), _) // exclude variable size types
select alloc,
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
base.getName() + "' (" + basesize.toString() + " bytes)."

View File

@@ -10,11 +10,12 @@ contains sensitive data that could somehow be retrieved by an attacker.</p>
</overview>
<recommendation>
<p>Use alternative platform-supplied functions that will not get optimized away. Examples of such
functions include <code>memset_s</code>, <code>SecureZeroMemory</code>, and <code>bzero_explicit</code>.
Alternatively, passing the <code>-fno-builtin-memset</code> option to the GCC/Clang compiler usually
also prevents the optimization. Finally, you can use the public-domain <code>secure_memzero</code> function
(see references below). This function, however, is not guaranteed to work on all platforms and compilers.</p>
<p>Use <code>memset_s</code> (from C11) instead of <code>memset</code>, as <code>memset_s</code> will not
get optimized away. Alternatively use platform-supplied functions such as <code>SecureZeroMemory</code> or
<code>bzero_explicit</code> that make the same guarantee. Passing the <code>-fno-builtin-memset</code>
option to the GCC/Clang compiler usually also prevents the optimization. Finally, you can use the
public-domain <code>secure_memzero</code> function (see references below). This function, however, is not
guaranteed to work on all platforms and compilers.</p>
</recommendation>
<example>

View File

@@ -5,7 +5,7 @@
* @id cpp/unsigned-difference-expression-compared-zero
* @problem.severity warning
* @security-severity 9.8
* @precision medium
* @precision high
* @tags security
* correctness
* external/cwe/cwe-191

View File

@@ -1,12 +1,31 @@
void writeCredentials() {
char *password = "cleartext password";
FILE* file = fopen("credentials.txt", "w");
#include <sodium.h>
#include <stdio.h>
#include <string.h>
void writeCredentialsBad(FILE *file, const char *cleartextCredentials) {
// BAD: write password to disk in cleartext
fputs(password, file);
// GOOD: encrypt password first
char *encrypted = encrypt(password);
fputs(encrypted, file);
fputs(cleartextCredentials, file);
}
int writeCredentialsGood(FILE *file, const char *cleartextCredentials, const unsigned char *key, const unsigned char *nonce) {
size_t credentialsLen = strlen(cleartextCredentials);
size_t ciphertext_len = crypto_secretbox_MACBYTES + credentialsLen;
unsigned char *ciphertext = malloc(ciphertext_len);
if (!ciphertext) {
logError();
return -1;
}
// encrypt the password first
if (crypto_secretbox_easy(ciphertext, (const unsigned char *)cleartextCredentials, credentialsLen, nonce, key) != 0) {
free(ciphertext);
logError();
return -1;
}
// GOOD: write encrypted password to disk
fwrite(ciphertext, 1, ciphertext_len, file);
free(ciphertext);
return 0;
}

View File

@@ -19,15 +19,20 @@ cleartext.</p>
<example>
<p>The following example shows two ways of storing user credentials in a file. In the 'BAD' case,
the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
storing them.</p>
<sample src="CleartextStorage.c" />
<p>Note that for the 'GOOD' example to work we need to link against an encryption library (in this case libsodium),
initialize it with a call to <code>sodium_init</code>, and create the key and nonce with
<code>crypto_secretbox_keygen</code> and <code>randombytes_buf</code> respectively. We also need to store those
details securely so they can be used for decryption.</p>
</example>
<references>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>

View File

@@ -1,6 +1,6 @@
void bad(void) {
char *password = "cleartext password";
const char *password = "cleartext password";
sqlite3 *credentialsDB;
sqlite3_stmt *stmt;
@@ -16,14 +16,15 @@ void bad(void) {
}
}
void good(void) {
char *password = "cleartext password";
void good(const char *secretKey) {
const char *password = "cleartext password";
sqlite3 *credentialsDB;
sqlite3_stmt *stmt;
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
// GOOD: database encryption enabled:
sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL);
std::string setKeyString = std::string("PRAGMA key = '") + secretKey + "'";
sqlite3_exec(credentialsDB, setKeyString.c_str(), NULL, NULL, NULL);
sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL);
if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
@@ -33,4 +34,3 @@ void good(void) {
}
}
}

View File

@@ -20,10 +20,12 @@ In the 'GOOD' case, the database (and thus the credentials) are encrypted.</p>
<sample src="CleartextSqliteDatabase.c" />
<p>Note that for the 'GOOD' example to work we need to provide a secret key. Secure key generation and storage is required.</p>
</example>
<references>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>

View File

@@ -232,6 +232,7 @@ predicate nullCheckInThrowingNew(NewOrNewArrayExpr newExpr, GuardCondition guard
from NewOrNewArrayExpr newExpr, Element element, string msg, string elementString
where
not newExpr.isFromUninstantiatedTemplate(_) and
not newExpr.isFromTemplateInstantiation(_) and
(
noThrowInTryBlock(newExpr, element) and
msg = "This allocation cannot throw. $@ is unnecessary." and

View File

@@ -0,0 +1,4 @@
---
category: queryMetadata
---
* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query no longer produces occasional false positive results inside template instantiations.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/suspicious-allocation-size` ("Not enough memory allocated for array of pointer type") query no longer produces false positives on "variable size" `struct`s.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/incorrectly-checked-scanf` ("Incorrect return-value check for a 'scanf'-like function") query now produces fewer false positive results.

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.1.0
version: 1.1.1-dev
groups:
- cpp
- queries

View File

@@ -1,7 +1,12 @@
// semmle-extractor-options: -std=c++17
// semmle-extractor-options: -std=c++20
typedef unsigned long size_t;
namespace std {
enum class align_val_t : size_t {};
struct destroying_delete_t {
explicit destroying_delete_t() = default;
};
inline constexpr destroying_delete_t destroying_delete{};
}
void* operator new(size_t, float);
@@ -37,6 +42,11 @@ struct SizedDealloc {
void operator delete[](void*, size_t);
};
struct DestroyingDealloc {
void* operator new(size_t);
void operator delete(DestroyingDealloc*, std::destroying_delete_t);
};
struct alignas(128) Overaligned {
char a[256];
};
@@ -59,6 +69,7 @@ void OperatorDelete() {
delete static_cast<int*>(nullptr); // No destructor
delete static_cast<String*>(nullptr); // Non-virtual destructor, with size.
delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
delete static_cast<DestroyingDealloc*>(nullptr); // No destructor, with destroying delete.
delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
delete static_cast<const String*>(nullptr); // Pointer to const
@@ -103,11 +114,20 @@ struct alignas(128) FailedInitOveraligned {
void operator delete[](void*, std::align_val_t, float); // Aligned placement
};
struct alignas(128) FailedInitDestroyingDelete {
FailedInitDestroyingDelete();
~FailedInitDestroyingDelete();
void* operator new(size_t); // Non-placement
void operator delete(FailedInitDestroyingDelete*, std::destroying_delete_t); // Destroying delete
};
void TestFailedInit(int n) {
new FailedInit();
new FailedInit[n];
new(1.0f) FailedInitOveraligned();
new(1.0f) FailedInitOveraligned[10];
new FailedInitDestroyingDelete();
}
// --- non-allocating placement new ---

View File

@@ -1,118 +1,123 @@
newExprs
| allocators.cpp:49:3:49:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:50:3:50:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | |
| allocators.cpp:51:3:51:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:52:3:52:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | |
| allocators.cpp:53:3:53:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | |
| allocators.cpp:54:3:54:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | |
| allocators.cpp:55:3:55:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | |
| allocators.cpp:107:3:107:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | |
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | |
| allocators.cpp:129:3:129:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... |
| allocators.cpp:135:3:135:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | |
| allocators.cpp:59:3:59:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:60:3:60:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | |
| allocators.cpp:61:3:61:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:62:3:62:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | |
| allocators.cpp:63:3:63:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | |
| allocators.cpp:64:3:64:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | |
| allocators.cpp:65:3:65:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | |
| allocators.cpp:126:3:126:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | |
| allocators.cpp:128:3:128:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | |
| allocators.cpp:130:3:130:34 | new | FailedInitDestroyingDelete | void* FailedInitDestroyingDelete::operator new(size_t) | 128 | 128 | | |
| allocators.cpp:149:3:149:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... |
| allocators.cpp:155:3:155:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | |
newArrayExprs
| allocators.cpp:68:3:68:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | |
| allocators.cpp:69:3:69:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | |
| allocators.cpp:70:3:70:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | |
| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | |
| allocators.cpp:72:3:72:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | |
| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | |
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | |
| allocators.cpp:132:3:132:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf |
| allocators.cpp:136:3:136:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | |
| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | |
| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | |
| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | |
| allocators.cpp:79:3:79:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | |
| allocators.cpp:80:3:80:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | |
| allocators.cpp:81:3:81:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | |
| allocators.cpp:82:3:82:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | |
| allocators.cpp:83:3:83:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | |
| allocators.cpp:127:3:127:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | |
| allocators.cpp:129:3:129:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | |
| allocators.cpp:152:3:152:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf |
| allocators.cpp:156:3:156:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | |
| allocators.cpp:162:13:162:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | |
| allocators.cpp:163:13:163:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | |
| allocators.cpp:164:13:164:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | |
newExprDeallocators
| allocators.cpp:52:3:52:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:53:3:53:27 | new | String | void operator delete(void*, float) | 8 | 8 | |
| allocators.cpp:107:3:107:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized |
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned |
| allocators.cpp:62:3:62:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:63:3:63:27 | new | String | void operator delete(void*, float) | 8 | 8 | |
| allocators.cpp:126:3:126:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized |
| allocators.cpp:128:3:128:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned |
| allocators.cpp:130:3:130:34 | new | FailedInitDestroyingDelete | void FailedInitDestroyingDelete::operator delete(FailedInitDestroyingDelete*, std::destroying_delete_t) | 128 | 128 | destroying |
newArrayExprDeallocators
| allocators.cpp:70:3:70:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:72:3:72:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:108:3:108:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized |
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned |
| allocators.cpp:81:3:81:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:83:3:83:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:127:3:127:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized |
| allocators.cpp:129:3:129:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned |
deleteExprs
| allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | false |
| allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
| allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | true |
| allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | false |
| allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
| allocators.cpp:69:3:69:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | false |
| allocators.cpp:70:3:70:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
| allocators.cpp:71:3:71:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | true |
| allocators.cpp:72:3:72:49 | delete | DestroyingDealloc | void DestroyingDealloc::operator delete(DestroyingDealloc*, std::destroying_delete_t) | 1 | 1 | destroying | true |
| allocators.cpp:73:3:73:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | false |
| allocators.cpp:75:3:75:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
deleteArrayExprs
| allocators.cpp:78:3:78:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
| allocators.cpp:79:3:79:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized |
| allocators.cpp:81:3:81:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:83:3:83:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
| allocators.cpp:89:3:89:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
| allocators.cpp:90:3:90:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:91:3:91:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized |
| allocators.cpp:92:3:92:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
| allocators.cpp:93:3:93:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:94:3:94:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
allocationFunctions
| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:121:7:121:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 |
| allocators.cpp:122:7:122:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 |
| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:153:7:153:12 | malloc | getSizeArg = 0, requiresDealloc |
| allocators.cpp:12:7:12:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:13:7:13:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:14:7:14:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:15:7:15:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:141:7:141:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 |
| allocators.cpp:142:7:142:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 |
| allocators.cpp:143:7:143:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:144:7:144:20 | operator new[] | getSizeArg = 0, requiresDealloc |
| allocators.cpp:173:7:173:12 | malloc | getSizeArg = 0, requiresDealloc |
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
allocationExprs
| allocators.cpp:49:3:49:9 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:50:3:50:15 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:51:3:51:11 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:52:3:52:14 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:53:3:53:27 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:54:3:54:17 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
| allocators.cpp:55:3:55:25 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
| allocators.cpp:68:3:68:12 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
| allocators.cpp:69:3:69:18 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
| allocators.cpp:70:3:70:15 | new[] | getAllocatedElementType = String, getSizeExpr = n, getSizeMult = 8, requiresDealloc |
| allocators.cpp:71:3:71:20 | new[] | getAllocatedElementType = Overaligned, getSizeExpr = n, getSizeMult = 256, requiresDealloc |
| allocators.cpp:72:3:72:16 | new[] | getAllocatedElementType = String, getSizeBytes = 80, requiresDealloc |
| allocators.cpp:107:3:107:18 | new | getAllocatedElementType = FailedInit, getSizeBytes = 1, requiresDealloc |
| allocators.cpp:108:3:108:19 | new[] | getAllocatedElementType = FailedInit, getSizeExpr = n, getSizeMult = 1, requiresDealloc |
| allocators.cpp:109:3:109:35 | new | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 128, requiresDealloc |
| allocators.cpp:110:3:110:37 | new[] | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 1280, requiresDealloc |
| allocators.cpp:129:3:129:21 | new | getAllocatedElementType = int, getSizeBytes = 4 |
| allocators.cpp:132:3:132:17 | new[] | getAllocatedElementType = int, getSizeBytes = 4 |
| allocators.cpp:135:3:135:26 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:136:3:136:26 | new[] | getAllocatedElementType = int, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:142:13:142:27 | new[] | getAllocatedElementType = char[10], getSizeExpr = x, getSizeMult = 10, requiresDealloc |
| allocators.cpp:143:13:143:28 | new[] | getAllocatedElementType = char[20], getSizeBytes = 400, requiresDealloc |
| allocators.cpp:144:13:144:31 | new[] | getAllocatedElementType = char[30][30], getSizeExpr = x, getSizeMult = 900, requiresDealloc |
| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
| allocators.cpp:157:50:157:55 | call to malloc | getAllocatedElementType = const volatile int, getSizeBytes = 5, getSizeExpr = 5, getSizeMult = 1, requiresDealloc |
| allocators.cpp:158:26:158:31 | call to malloc | getAllocatedElementType = int, getSizeBytes = 20, getSizeExpr = 5, getSizeMult = 4, requiresDealloc |
| allocators.cpp:159:31:159:36 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 1, requiresDealloc |
| allocators.cpp:160:16:160:21 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 4, requiresDealloc |
| allocators.cpp:161:34:161:39 | call to malloc | getAllocatedElementType = const char, getSizeExpr = ... + ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:162:23:162:28 | call to malloc | getSizeExpr = count, getSizeMult = 8, requiresDealloc |
| allocators.cpp:163:3:163:8 | call to malloc | getSizeBytes = 32, getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:59:3:59:9 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:60:3:60:15 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:61:3:61:11 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:62:3:62:14 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:63:3:63:27 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:64:3:64:17 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
| allocators.cpp:65:3:65:25 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
| allocators.cpp:79:3:79:12 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
| allocators.cpp:80:3:80:18 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
| allocators.cpp:81:3:81:15 | new[] | getAllocatedElementType = String, getSizeExpr = n, getSizeMult = 8, requiresDealloc |
| allocators.cpp:82:3:82:20 | new[] | getAllocatedElementType = Overaligned, getSizeExpr = n, getSizeMult = 256, requiresDealloc |
| allocators.cpp:83:3:83:16 | new[] | getAllocatedElementType = String, getSizeBytes = 80, requiresDealloc |
| allocators.cpp:126:3:126:18 | new | getAllocatedElementType = FailedInit, getSizeBytes = 1, requiresDealloc |
| allocators.cpp:127:3:127:19 | new[] | getAllocatedElementType = FailedInit, getSizeExpr = n, getSizeMult = 1, requiresDealloc |
| allocators.cpp:128:3:128:35 | new | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 128, requiresDealloc |
| allocators.cpp:129:3:129:37 | new[] | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 1280, requiresDealloc |
| allocators.cpp:130:3:130:34 | new | getAllocatedElementType = FailedInitDestroyingDelete, getSizeBytes = 128, requiresDealloc |
| allocators.cpp:149:3:149:21 | new | getAllocatedElementType = int, getSizeBytes = 4 |
| allocators.cpp:152:3:152:17 | new[] | getAllocatedElementType = int, getSizeBytes = 4 |
| allocators.cpp:155:3:155:26 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
| allocators.cpp:156:3:156:26 | new[] | getAllocatedElementType = int, getSizeBytes = 8, requiresDealloc |
| allocators.cpp:162:13:162:27 | new[] | getAllocatedElementType = char[10], getSizeExpr = x, getSizeMult = 10, requiresDealloc |
| allocators.cpp:163:13:163:28 | new[] | getAllocatedElementType = char[20], getSizeBytes = 400, requiresDealloc |
| allocators.cpp:164:13:164:31 | new[] | getAllocatedElementType = char[30][30], getSizeExpr = x, getSizeMult = 900, requiresDealloc |
| allocators.cpp:169:8:169:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
| allocators.cpp:177:50:177:55 | call to malloc | getAllocatedElementType = const volatile int, getSizeBytes = 5, getSizeExpr = 5, getSizeMult = 1, requiresDealloc |
| allocators.cpp:178:26:178:31 | call to malloc | getAllocatedElementType = int, getSizeBytes = 20, getSizeExpr = 5, getSizeMult = 4, requiresDealloc |
| allocators.cpp:179:31:179:36 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 1, requiresDealloc |
| allocators.cpp:180:16:180:21 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 4, requiresDealloc |
| allocators.cpp:181:34:181:39 | call to malloc | getAllocatedElementType = const char, getSizeExpr = ... + ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:182:23:182:28 | call to malloc | getSizeExpr = count, getSizeMult = 8, requiresDealloc |
| allocators.cpp:183:3:183:8 | call to malloc | getSizeBytes = 32, getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
deallocationFunctions
| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 |
| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 |
| allocators.cpp:13:6:13:20 | operator delete | getFreedArg = 0 |
| allocators.cpp:14:6:14:22 | operator delete[] | getFreedArg = 0 |
| allocators.cpp:16:6:16:20 | operator delete | getFreedArg = 0 |
| allocators.cpp:17:6:17:22 | operator delete[] | getFreedArg = 0 |
| allocators.cpp:18:6:18:20 | operator delete | getFreedArg = 0 |
| allocators.cpp:19:6:19:22 | operator delete[] | getFreedArg = 0 |
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
deallocationExprs
| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 |
| allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 |
| allocators.cpp:61:3:61:44 | delete | getFreedExpr = 0 |
| allocators.cpp:62:3:62:43 | delete | getFreedExpr = 0 |
| allocators.cpp:63:3:63:47 | delete | getFreedExpr = 0 |
| allocators.cpp:64:3:64:44 | delete | getFreedExpr = 0 |
| allocators.cpp:78:3:78:37 | delete[] | getFreedExpr = 0 |
| allocators.cpp:79:3:79:40 | delete[] | getFreedExpr = 0 |
| allocators.cpp:80:3:80:46 | delete[] | getFreedExpr = 0 |
| allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 |
| allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 |
| allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer |
| allocators.cpp:150:2:150:16 | call to operator delete | getFreedExpr = ptr |
| allocators.cpp:69:3:69:35 | delete | getFreedExpr = 0 |
| allocators.cpp:70:3:70:38 | delete | getFreedExpr = 0 |
| allocators.cpp:71:3:71:44 | delete | getFreedExpr = 0 |
| allocators.cpp:72:3:72:49 | delete | getFreedExpr = 0 |
| allocators.cpp:73:3:73:43 | delete | getFreedExpr = 0 |
| allocators.cpp:74:3:74:47 | delete | getFreedExpr = 0 |
| allocators.cpp:75:3:75:44 | delete | getFreedExpr = 0 |
| allocators.cpp:89:3:89:37 | delete[] | getFreedExpr = 0 |
| allocators.cpp:90:3:90:40 | delete[] | getFreedExpr = 0 |
| allocators.cpp:91:3:91:46 | delete[] | getFreedExpr = 0 |
| allocators.cpp:92:3:92:45 | delete[] | getFreedExpr = 0 |
| allocators.cpp:93:3:93:49 | delete[] | getFreedExpr = 0 |
| allocators.cpp:94:3:94:23 | delete[] | getFreedExpr = call to GetPointer |
| allocators.cpp:170:2:170:16 | call to operator delete | getFreedExpr = ptr |

View File

@@ -50,10 +50,11 @@ query predicate newExprDeallocators(
type = allocatedType.toString() and
size = allocatedType.getSize() and
alignment = allocatedType.getAlignment() and
exists(string sized, string aligned |
exists(string sized, string aligned, string destroying |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
form = sized + " " + aligned + " " + destroying
)
)
}
@@ -68,10 +69,11 @@ query predicate newArrayExprDeallocators(
type = elementType.toString() and
size = elementType.getSize() and
alignment = elementType.getAlignment() and
exists(string sized, string aligned |
exists(string sized, string aligned, string destroying |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
form = sized + " " + aligned + " " + destroying
)
)
}
@@ -87,10 +89,11 @@ query predicate deleteExprs(
type = deletedType.toString() and
size = deletedType.getSize() and
alignment = deletedType.getAlignment() and
exists(string sized, string aligned |
exists(string sized, string aligned, string destroying |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
form = sized + " " + aligned + " " + destroying
) and
if exists(expr.getDeallocatorCall())
then hasDeallocatorCall = true
@@ -108,10 +111,11 @@ query predicate deleteArrayExprs(
type = elementType.toString() and
size = elementType.getSize() and
alignment = elementType.getAlignment() and
exists(string sized, string aligned |
exists(string sized, string aligned, string destroying |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
form = sized + " " + aligned + " " + destroying
)
)
}

View File

@@ -1,7 +1,5 @@
| declspec.cpp:4:23:4:43 | Use fatal() instead | declspec.cpp:4:59:4:62 | exit | declspec.cpp:4:12:4:21 | deprecated | Use fatal() instead |
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
| routine_attributes.c:3:53:3:59 | dummy | routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref | dummy |
| routine_attributes.c:4:62:4:68 | dummy | routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:55:4:59 | alias | dummy |

View File

@@ -19,8 +19,6 @@
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllexport |
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllimport |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
| routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref |
| routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:46:4:52 | weakref |

View File

@@ -1,6 +1,5 @@
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility | type_attributes2.cpp:5:7:5:12 | hidden |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
| type_attributes_ms.cpp:4:67:4:75 | IDispatch | type_attributes_ms.cpp:4:19:4:22 | uuid | type_attributes_ms.cpp:4:24:4:63 | {00020400-0000-0000-c000-000000000046} |
| type_attributes_ms.cpp:5:30:5:33 | Str1 | type_attributes_ms.cpp:5:12:5:16 | align | type_attributes_ms.cpp:5:18:5:19 | 32 |
| type_attributes_ms.cpp:6:55:6:62 | IUnknown | type_attributes_ms.cpp:6:2:6:2 | uuid | type_attributes_ms.cpp:6:2:6:2 | 00000000-0000-0000-c000-000000000046 |

View File

@@ -1,7 +1,6 @@
| file://:0:0:0:0 | short __attribute((__may_alias__)) | type_attributes.c:25:30:25:42 | may_alias |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
| type_attributes.c:5:36:5:51 | my_packed_struct | type_attributes.c:5:23:5:32 | packed |
| type_attributes.c:10:54:10:54 | (unnamed class/struct/union) | type_attributes.c:10:30:10:50 | transparent_union |
| type_attributes.c:16:54:16:54 | (unnamed class/struct/union) | type_attributes.c:16:30:16:50 | transparent_union |

View File

@@ -7,8 +7,6 @@
| ms_var_attributes.cpp:20:34:20:37 | pBuf | ms_var_attributes.cpp:20:12:20:12 | SAL_volatile |
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary

View File

@@ -2,7 +2,6 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,4 +7,61 @@ class TestConstexpr {
constexpr int member_const_constexpr() const { return 0; }
};
struct TestExplict {
explicit TestExplict();
};
template<typename T>
struct TestExplicitBool {
explicit(sizeof(T) == 1)
TestExplicitBool(const T);
};
explicit TestExplicitBool(const double) -> TestExplicitBool<int>;
template<typename T>
explicit(sizeof(T) == 4)
TestExplicitBool(const T) -> TestExplicitBool<int>;
void TestExplicitBoolFun() {
new TestExplicitBool<char>(0);
new TestExplicitBool<int>(0);
new TestExplicitBool(0.0f);
new TestExplicitBool(0.0);
}
template<typename T>
struct TestExplicitBool2 {
explicit(sizeof(T) == 1)
TestExplicitBool2(const T);
};
template<typename T>
TestExplicitBool2<T>::TestExplicitBool2(const T) { }
void TestExplicitBoolFun2() {
new TestExplicitBool2<char>(0);
new TestExplicitBool2<int>(0);
}
template<typename T>
struct TestExplicitBool3 {
template<typename U>
explicit(sizeof(T) == 1)
TestExplicitBool3(const T, const U);
};
template<typename T> template<typename U>
TestExplicitBool3<T>::TestExplicitBool3(const T, const U) { }
void TestExplicitBoolFun3() {
new TestExplicitBool3<char>(0, 0);
new TestExplicitBool3<int>(0, 0);
}
struct TestExplicitBool4 {
explicit(sizeof(char) == 1)
TestExplicitBool4(const char);
};
} // namespace cpp20

View File

@@ -0,0 +1,8 @@
| cpp20.cpp:15:8:15:23 | TestExplicitBool<char> | file://:0:0:0:0 | char | cpp20.cpp:17:5:17:20 | TestExplicitBool | explicit, extern, public |
| cpp20.cpp:15:8:15:23 | TestExplicitBool<int> | file://:0:0:0:0 | int | cpp20.cpp:17:5:17:20 | TestExplicitBool | extern, public |
| cpp20.cpp:34:8:34:24 | TestExplicitBool2<char> | file://:0:0:0:0 | char | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | explicit, public |
| cpp20.cpp:34:8:34:24 | TestExplicitBool2<int> | file://:0:0:0:0 | int | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | public |
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<char> | file://:0:0:0:0 | char | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | explicit, public |
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<char> | file://:0:0:0:0 | char | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | explicit, extern, public |
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<int> | file://:0:0:0:0 | int | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | public |
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<int> | file://:0:0:0:0 | int | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | extern, public |

View File

@@ -0,0 +1,7 @@
import cpp
from MemberFunction m, ClassTemplateInstantiation c, string specifiers
where
c.getAMember() = m and
specifiers = concat(string s | s = m.getASpecifier().getName() | s, ", ")
select c, c.getATemplateArgument(), m, specifiers

View File

@@ -1,146 +1,80 @@
| Class | specifiers2pp.cpp:8:7:8:13 | MyClass | MyClass | abstract |
| Class | specifiers2pp.cpp:24:7:24:14 | MyClass2 | MyClass2 | abstract |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | inline |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | is_constexpr |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | private |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | declared_constexpr |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | inline |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | is_constexpr |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | private |
| Function | specifiers2.c:11:6:11:6 | f | f | c_linkage |
| Function | specifiers2.c:11:6:11:6 | f | f | extern |
| Function | specifiers2.c:12:13:12:13 | f | f | c_linkage |
| Function | specifiers2.c:12:13:12:13 | f | f | extern |
| Function | specifiers2.c:13:13:13:13 | f | f | c_linkage |
| Function | specifiers2.c:13:13:13:13 | f | f | extern |
| Function | specifiers2.c:15:13:15:13 | g | g | c_linkage |
| Function | specifiers2.c:15:13:15:13 | g | g | extern |
| Function | specifiers2.c:16:13:16:13 | g | g | c_linkage |
| Function | specifiers2.c:16:13:16:13 | g | g | extern |
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage |
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | extern |
| Function | specifiers2.c:25:12:25:14 | add | add | c_linkage |
| Function | specifiers2.c:25:12:25:14 | add | add | inline |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | public |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | extern |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | public |
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline |
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | extern |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | pure |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | virtual |
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | declared_virtual |
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | extern |
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | public |
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | virtual |
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | inline |
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | private |
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | inline |
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | protected |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | is_constexpr |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | is_constexpr |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | declared_virtual |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | extern |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | override |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | public |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | virtual |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr, inline, is_constexpr, private |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:11:14:11:24 | TestExplict | TestExplict | explicit, extern, public |
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | explicit, extern, public |
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
| Function | cpp20.cpp:24:1:24:16 | TestExplicitBool | TestExplicitBool | has_trailing_return_type |
| Function | cpp20.cpp:40:1:40:39 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | explicit, public |
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | explicit, public |
| Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | public |
| Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | explicit, extern, public |
| Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | extern, public |
| Function | cpp20.cpp:55:1:55:39 | TestExplicitBool3 | TestExplicitBool3 | public |
| Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:64:5:64:21 | TestExplicitBool4 | TestExplicitBool4 | explicit, extern, public |
| Function | file://:0:0:0:0 | operator delete | operator delete | extern |
| Function | file://:0:0:0:0 | operator new | operator new | extern |
| Function | specifiers2.c:11:6:11:6 | f | f | c_linkage, extern |
| Function | specifiers2.c:12:13:12:13 | f | f | c_linkage, extern |
| Function | specifiers2.c:13:13:13:13 | f | f | c_linkage, extern |
| Function | specifiers2.c:15:13:15:13 | g | g | c_linkage, extern |
| Function | specifiers2.c:16:13:16:13 | g | g | c_linkage, extern |
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage, extern |
| Function | specifiers2.c:25:12:25:14 | add | add | c_linkage, inline |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit, extern, public |
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline, public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual, extern, public, pure, virtual |
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | declared_virtual, extern, public, virtual |
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | inline, private |
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | inline, protected |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, public |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | declared_virtual, extern, override, public, virtual |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:33:5:33:18 | fun | fun | public |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:40:12:40:18 | someFun | someFun | extern |
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | c_linkage |
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | extern |
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage |
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | extern |
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage |
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | static |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | declared_constexpr |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | inline |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | is_constexpr |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | private |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | const |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | declared_constexpr |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | inline |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | is_constexpr |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | private |
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | void_param_list |
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | extern |
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | void_param_list |
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | extern |
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | void_param_list |
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | extern |
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | void_param_list |
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | extern |
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | void_param_list |
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | c_linkage, extern |
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage, extern |
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage, static |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| FunctionDeclarationEntry | cpp20.cpp:11:14:11:24 | declaration of TestExplict | TestExplict | explicit |
| FunctionDeclarationEntry | cpp20.cpp:40:23:40:23 | definition of TestExplicitBool2 | TestExplicitBool2 | explicit |
| FunctionDeclarationEntry | cpp20.cpp:51:5:51:5 | definition of TestExplicitBool3 | TestExplicitBool3 | explicit |
| FunctionDeclarationEntry | cpp20.cpp:51:5:51:21 | declaration of TestExplicitBool3 | TestExplicitBool3 | explicit |
| FunctionDeclarationEntry | cpp20.cpp:64:5:64:21 | declaration of TestExplicitBool4 | TestExplicitBool4 | explicit |
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | c_linkage, void_param_list |
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | c_linkage, extern, void_param_list |
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | c_linkage, extern, void_param_list |
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | c_linkage, extern, void_param_list |
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | c_linkage, extern, void_param_list |
| FunctionDeclarationEntry | specifiers2.c:21:6:21:12 | declaration of somefun | somefun | c_linkage |
| FunctionDeclarationEntry | specifiers2.c:25:12:25:14 | definition of add | add | c_linkage |
| FunctionDeclarationEntry | specifiers2pp.cpp:2:6:2:9 | definition of afun | afun | void_param_list |
@@ -154,28 +88,19 @@
| FunctionDeclarationEntry | specifiers2pp.cpp:31:13:31:15 | declaration of fun | fun | void_param_list |
| FunctionDeclarationEntry | specifiers2pp.cpp:33:5:33:18 | definition of fun | fun | void_param_list |
| FunctionDeclarationEntry | specifiers2pp.cpp:40:12:40:18 | declaration of someFun | someFun | extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | c_linkage |
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | c_linkage |
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | c_linkage |
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | static |
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | c_linkage, extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | c_linkage, extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | c_linkage, static |
| TypedefType | file://:0:0:0:0 | Const | Const | const |
| TypedefType | specifiers2.c:27:19:27:26 | constInt | constInt | const |
| TypedefType | specifiers2pp.cpp:47:20:47:32 | const_pointer | const_pointer | const |
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | const |
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | volatile |
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | const |
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | volatile |
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | const |
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | volatile |
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | const |
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | restrict |
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | volatile |
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | const, volatile |
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | const, volatile |
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | const, volatile |
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | const, restrict, volatile |
| TypedefType | specifiers2pp.cpp:56:28:56:32 | Const | Const | const |
| TypedefType | specifiers2pp.cpp:58:7:58:15 | Const_int | Const_int | const |
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | const |
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | volatile |
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | const, volatile |
| Variable | specifiers2.c:8:12:8:12 | j | j | extern |
| Variable | specifiers2.c:9:12:9:12 | j | j | extern |
| Variable | specifiers2.c:18:21:18:23 | svi | svi | static |

View File

@@ -14,16 +14,20 @@ string interesting(Element e) {
e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry"
}
from Element e, string name, string specifier
from Element e, string name, string specifiers
where
(
name = e.(Declaration).getName() or
name = e.(DeclarationEntry).getName() or
name = e.(Type).toString()
) and
(
specifier = e.(Declaration).getASpecifier().toString() or
specifier = e.(DeclarationEntry).getASpecifier() or
specifier = e.(TypedefType).getBaseType().getASpecifier().toString()
)
select interesting(e), e, name, specifier
specifiers =
concat(string s |
s = e.(Declaration).getASpecifier().toString() or
s = e.(DeclarationEntry).getASpecifier() or
s = e.(TypedefType).getBaseType().getASpecifier().toString()
|
s, ", "
) and
specifiers != ""
select interesting(e), e, name, specifiers

View File

@@ -1,3 +1,22 @@
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:24:24:24:24 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| cpp20.cpp:55:47:55:47 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
| cpp20.cpp:55:56:55:56 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
| cpp20.cpp:64:23:64:32 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const double | file://:0:0:0:0 | const |
| specifiers2.c:18:21:18:23 | svi | file://:0:0:0:0 | volatile int | file://:0:0:0:0 | volatile |
| specifiers2.c:19:11:19:12 | ci | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
| specifiers2.c:21:34:21:34 | p | file://:0:0:0:0 | char *__restrict__ | file://:0:0:0:0 | restrict |

View File

@@ -0,0 +1,4 @@
| cpp20.cpp:17:5:17:20 | TestExplicitBool | extern, public |
| cpp20.cpp:40:1:40:39 | TestExplicitBool2 | public |
| cpp20.cpp:40:23:40:23 | TestExplicitBool2 | public |
| cpp20.cpp:55:1:55:39 | TestExplicitBool3 | public |

View File

@@ -0,0 +1,7 @@
import cpp
from MemberFunction m, TemplateClass c, string specifiers
where
c.getAMember() = m and
specifiers = concat(string s | s = m.getASpecifier().getName() | s, ", ")
select m, specifiers

View File

@@ -26,8 +26,11 @@
| test.cpp:128:15:128:16 | v4 |
| test.cpp:185:10:185:12 | cpy |
| test.cpp:199:10:199:12 | cpy |
| test.cpp:208:7:208:7 | a |
| test.cpp:214:7:214:7 | a |
| test.cpp:213:7:213:7 | a |
| test.cpp:219:7:219:7 | a |
| test.cpp:228:14:228:18 | data1 |
| test.cpp:236:14:236:18 | data1 |
| test.cpp:237:14:237:18 | data2 |
| test_free.cpp:11:10:11:10 | a |
| test_free.cpp:14:10:14:10 | a |
| test_free.cpp:16:10:16:10 | a |

View File

@@ -1,6 +1,9 @@
edges
| test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | provenance | |
| test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | provenance | |
| test.cpp:213:7:213:7 | pointer to free output argument | test.cpp:214:2:214:2 | a | provenance | |
| test.cpp:219:7:219:7 | pointer to free output argument | test.cpp:220:2:220:2 | a | provenance | |
| test.cpp:228:12:228:12 | *p [post update] [data1] | test.cpp:229:2:229:2 | *p [data1] | provenance | |
| test.cpp:228:14:228:18 | pointer to operator delete[] output argument | test.cpp:228:12:228:12 | *p [post update] [data1] | provenance | |
| test.cpp:229:2:229:2 | *p [data1] | test.cpp:229:4:229:8 | data1 | provenance | |
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | provenance | |
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | provenance | |
| test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | provenance | |
@@ -33,10 +36,14 @@ edges
| test_free.cpp:322:12:322:12 | pointer to operator delete output argument | test_free.cpp:324:5:324:6 | * ... | provenance | |
| test_free.cpp:331:12:331:12 | pointer to operator delete output argument | test_free.cpp:332:5:332:6 | * ... | provenance | |
nodes
| test.cpp:208:7:208:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:209:2:209:2 | a | semmle.label | a |
| test.cpp:214:7:214:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:215:2:215:2 | a | semmle.label | a |
| test.cpp:213:7:213:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:214:2:214:2 | a | semmle.label | a |
| test.cpp:219:7:219:7 | pointer to free output argument | semmle.label | pointer to free output argument |
| test.cpp:220:2:220:2 | a | semmle.label | a |
| test.cpp:228:12:228:12 | *p [post update] [data1] | semmle.label | *p [post update] [data1] |
| test.cpp:228:14:228:18 | pointer to operator delete[] output argument | semmle.label | pointer to operator delete[] output argument |
| test.cpp:229:2:229:2 | *p [data1] | semmle.label | *p [data1] |
| test.cpp:229:4:229:8 | data1 | semmle.label | data1 |
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
@@ -88,8 +95,9 @@ nodes
| test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... |
subpaths
#select
| test.cpp:209:2:209:2 | a | test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | Memory may have been previously freed by $@. | test.cpp:208:2:208:5 | call to free | call to free |
| test.cpp:215:2:215:2 | a | test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | Memory may have been previously freed by $@. | test.cpp:214:2:214:5 | call to free | call to free |
| test.cpp:214:2:214:2 | a | test.cpp:213:7:213:7 | pointer to free output argument | test.cpp:214:2:214:2 | a | Memory may have been previously freed by $@. | test.cpp:213:2:213:5 | call to free | call to free |
| test.cpp:220:2:220:2 | a | test.cpp:219:7:219:7 | pointer to free output argument | test.cpp:220:2:220:2 | a | Memory may have been previously freed by $@. | test.cpp:219:2:219:5 | call to free | call to free |
| test.cpp:229:4:229:8 | data1 | test.cpp:228:14:228:18 | pointer to operator delete[] output argument | test.cpp:229:4:229:8 | data1 | Memory may have been previously freed by $@. | test.cpp:228:2:228:18 | delete[] | delete[] |
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:13:5:13:6 | * ... | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |

View File

@@ -201,6 +201,11 @@ void test_strndupa_dealloc() {
// ---
struct DataPair {
char *data1;
char *data2;
};
void test_reassignment() {
char *a = (char *)malloc(128);
char *b = (char *)malloc(128);
@@ -213,4 +218,21 @@ void test_reassignment() {
free(a);
a[0] = 0; // BAD
DataPair p;
p.data1 = new char[128];
p.data2 = new char[128];
p.data1[0] = 0; // GOOD
p.data2[0] = 0; // GOOD
delete [] p.data1;
p.data1[0] = 0; // BAD
p.data2[0] = 0; // GOOD
p.data1 = new char[128];
p.data1[0] = 0; // GOOD
p.data2[0] = 0; // GOOD
delete [] p.data1;
delete [] p.data2;
}

View File

@@ -37,6 +37,21 @@ edges
| test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | provenance | |
| test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | provenance | |
| test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | provenance | |
| test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | provenance | |
| test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | provenance | |
| test.cpp:501:25:501:26 | scanf output argument | test.cpp:505:9:505:9 | i | provenance | |
| test.cpp:512:25:512:26 | scanf output argument | test.cpp:516:9:516:9 | i | provenance | |
| test.cpp:525:35:525:36 | sscanf output argument | test.cpp:527:8:527:8 | a | provenance | |
| test.cpp:525:35:525:36 | sscanf output argument | test.cpp:531:8:531:8 | a | provenance | |
| test.cpp:525:39:525:40 | sscanf output argument | test.cpp:528:8:528:8 | b | provenance | |
| test.cpp:525:39:525:40 | sscanf output argument | test.cpp:532:8:532:8 | b | provenance | |
| test.cpp:525:43:525:44 | sscanf output argument | test.cpp:533:8:533:8 | c | provenance | |
| test.cpp:541:35:541:36 | sscanf output argument | test.cpp:543:8:543:8 | d | provenance | |
| test.cpp:541:35:541:36 | sscanf output argument | test.cpp:548:8:548:8 | d | provenance | |
| test.cpp:541:39:541:40 | sscanf output argument | test.cpp:544:8:544:8 | e | provenance | |
| test.cpp:541:39:541:40 | sscanf output argument | test.cpp:549:8:549:8 | e | provenance | |
| test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | provenance | |
| test.cpp:541:43:541:44 | sscanf output argument | test.cpp:550:8:550:8 | f | provenance | |
nodes
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:35:7:35:7 | i | semmle.label | i |
@@ -114,6 +129,31 @@ nodes
| test.cpp:460:6:460:10 | value | semmle.label | value |
| test.cpp:467:20:467:25 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:474:6:474:10 | value | semmle.label | value |
| test.cpp:480:25:480:26 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:484:9:484:9 | i | semmle.label | i |
| test.cpp:491:25:491:26 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:495:8:495:8 | i | semmle.label | i |
| test.cpp:501:25:501:26 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:505:9:505:9 | i | semmle.label | i |
| test.cpp:512:25:512:26 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:516:9:516:9 | i | semmle.label | i |
| test.cpp:525:35:525:36 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:525:39:525:40 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:525:43:525:44 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:527:8:527:8 | a | semmle.label | a |
| test.cpp:528:8:528:8 | b | semmle.label | b |
| test.cpp:531:8:531:8 | a | semmle.label | a |
| test.cpp:532:8:532:8 | b | semmle.label | b |
| test.cpp:533:8:533:8 | c | semmle.label | c |
| test.cpp:541:35:541:36 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:541:39:541:40 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:541:43:541:44 | sscanf output argument | semmle.label | sscanf output argument |
| test.cpp:543:8:543:8 | d | semmle.label | d |
| test.cpp:544:8:544:8 | e | semmle.label | e |
| test.cpp:545:8:545:8 | f | semmle.label | f |
| test.cpp:548:8:548:8 | d | semmle.label | d |
| test.cpp:549:8:549:8 | e | semmle.label | e |
| test.cpp:550:8:550:8 | f | semmle.label | f |
subpaths
#select
| test.cpp:35:7:35:7 | i | test.cpp:34:15:34:16 | scanf output argument | test.cpp:35:7:35:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:34:3:34:7 | call to scanf | call to scanf |
@@ -134,3 +174,6 @@ subpaths
| test.cpp:423:7:423:7 | i | test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
| test.cpp:460:6:460:10 | value | test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:455:12:455:17 | call to sscanf | call to sscanf |
| test.cpp:474:6:474:10 | value | test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:467:8:467:12 | call to scanf | call to scanf |
| test.cpp:484:9:484:9 | i | test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:480:13:480:17 | call to scanf | call to scanf |
| test.cpp:495:8:495:8 | i | test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:491:13:491:17 | call to scanf | call to scanf |
| test.cpp:545:8:545:8 | f | test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 3. | test.cpp:541:10:541:15 | call to sscanf | call to sscanf |

View File

@@ -472,4 +472,84 @@ void check_for_negative_test() {
return;
}
use(value);
}
}
void multiple_checks() {
{
int i;
int res = scanf("%d", &i);
if (res >= 0) {
if (res != 0) {
use(i); // GOOD: checks return value [FALSE POSITIVE]
}
}
}
{
int i;
int res = scanf("%d", &i);
if (res < 0) return;
if (res != 0) {
use(i); // GOOD: checks return value [FALSE POSITIVE]
}
}
{
int i;
int res = scanf("%d", &i);
if (res >= 1) {
if (res != 0) {
use(i); // GOOD: checks return value
}
}
}
{
int i;
int res = scanf("%d", &i);
if (res == 1) {
if (res != 0) {
use(i); // GOOD: checks return value
}
}
}
}
void switch_cases(const char *data) {
float a, b, c;
switch (sscanf(data, "%f %f %f", &a, &b, &c)) {
case 2:
use(a); // GOOD
use(b); // GOOD
break;
case 3:
use(a); // GOOD
use(b); // GOOD
use(c); // GOOD
break;
default:
break;
}
float d, e, f;
switch (sscanf(data, "%f %f %f", &d, &e, &f)) {
case 2:
use(d); // GOOD
use(e); // GOOD
use(f); // BAD
break;
case 3:
use(d); // GOOD
use(e); // GOOD
use(f); // GOOD
break;
default:
break;
}
}

View File

@@ -2,3 +2,4 @@
| test2.c:17:20:17:25 | call to malloc | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:32:23:32:28 | call to malloc | Allocated memory (28 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test2.c:33:20:33:25 | call to malloc | Allocated memory (20 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:85:24:85:29 | call to malloc | Allocated memory (1159 bytes) is not a multiple of the size of 'MyFixedStruct' (1032 bytes). |

View File

@@ -60,7 +60,7 @@ void test_union() {
}
// --- custom allocators ---
void *MyMalloc1(size_t size) { return malloc(size); }
void *MyMalloc2(size_t size);

View File

@@ -44,7 +44,7 @@ void good1(void) {
}
// --- custom allocators ---
void *MyMalloc1(size_t size) { return malloc(size); }
void *MyMalloc2(size_t size);
@@ -53,3 +53,34 @@ void customAllocatorTests()
double *dptr1 = MyMalloc1(33); // BAD -- Not a multiple of sizeof(double) [NOT DETECTED]
double *dptr2 = MyMalloc2(33); // BAD -- Not a multiple of sizeof(double) [NOT DETECTED]
}
// --- variable length data structures ---
typedef unsigned char uint8_t;
typedef struct _MyVarStruct1 {
size_t dataLen;
uint8_t data[0];
} MyVarStruct1;
typedef struct _MyVarStruct2 {
size_t dataLen;
uint8_t data[1];
} MyVarStruct2;
typedef struct _MyVarStruct3 {
size_t dataLen;
uint8_t data[];
} MyVarStruct3;
typedef struct _MyFixedStruct {
size_t dataLen;
uint8_t data[1024];
} MyFixedStruct;
void varStructTests() {
MyVarStruct1 *a = malloc(sizeof(MyVarStruct1) + 127); // GOOD
MyVarStruct2 *b = malloc(sizeof(MyVarStruct2) + 127); // GOOD
MyVarStruct3 *c = malloc(sizeof(MyVarStruct3) + 127); // GOOD
MyFixedStruct *d = malloc(sizeof(MyFixedStruct) + 127); // BAD --- Not a multiple of sizeof(MyFixedStruct)
}

View File

@@ -23,3 +23,4 @@
| test.cpp:424:2:425:2 | for(...;...;...) ... | test.cpp:424:18:424:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:433:2:434:2 | for(...;...;...) ... | test.cpp:433:18:433:22 | 0 | 0 | | { ... } | 0 | return ... |
| test.cpp:559:3:564:3 | while (...) ... | test.cpp:559:9:559:15 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |
| test.cpp:574:3:579:3 | while (...) ... | test.cpp:574:10:574:16 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |

View File

@@ -565,4 +565,31 @@ void test45() {
*rP = NULL;
use(r); // GOOD
}
void test46()
{
LinkedList *r, **rP = &r;
while (getBool())
{
LinkedList *s = nullptr;
*rP = s;
rP = &s->next;
}
*rP = nullptr;
use(r);
}
namespace std {
float remquo(float, float, int*);
}
void test47() {
float x = 1.0f;
float y = 2.0f;
int quo;
std::remquo(x, y, &quo);
use(quo); // GOOD
}

View File

@@ -13,7 +13,7 @@
| test.cpp:92:5:92:31 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:93:15:93:41 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:96:10:96:36 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:151:9:151:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:152:15:152:18 | { ... } | This catch block |
| test.cpp:199:15:199:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:201:16:201:19 | { ... } | This catch block |
| test.cpp:212:14:212:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:213:34:213:36 | { ... } | This catch block |
| test.cpp:246:17:246:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:247:8:247:12 | ! ... | This check |
| test.cpp:160:9:160:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:161:15:161:18 | { ... } | This catch block |
| test.cpp:229:15:229:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:231:16:231:19 | { ... } | This catch block |
| test.cpp:242:14:242:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:243:34:243:36 | { ... } | This catch block |
| test.cpp:276:17:276:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:277:8:277:12 | ! ... | This check |

View File

@@ -136,6 +136,8 @@ void good_new_handles_nullptr() {
return; // GOOD
}
// ---
void* operator new(std::size_t count, void*) noexcept;
void* operator new[](std::size_t count, void*) noexcept;
@@ -146,18 +148,46 @@ struct Foo {
operator bool();
};
struct Bar {
Bar();
operator bool();
};
void bad_placement_new_with_exception_handling() {
char buffer[1024];
try { new (buffer) Foo; } // BAD
try { new (buffer) Foo; } // BAD (placement new should not fail)
catch (...) { }
}
void good_placement_new_with_exception_handling() {
char buffer[1024];
try { new (buffer) Foo(42); } // GOOD: Foo constructor might throw
catch (...) { }
try { new (buffer) Bar; } // GOOD: Bar constructor might throw
catch (...) { }
}
template<typename F> F *test_template_platement_new() {
char buffer[1024];
try {
return new (buffer) F; // GOOD: `F` constructor might throw (when `F` is `Bar`)
} catch (...) {
return 0;
}
}
void test_template_platement_new_caller() {
test_template_platement_new<Foo>();
test_template_platement_new<Bar>();
}
// ---
int unknown_value_without_exceptions() noexcept;
void may_throw() {

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.7.21
version: 1.7.22-dev
groups:
- csharp
- solorigate

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.7.21
version: 1.7.22-dev
groups:
- csharp
- solorigate

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 1.0.4
version: 1.0.5-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -2444,9 +2444,6 @@ DataFlowType getNodeType(Node n) {
] = result.getADelegateCreation()
}
/** Gets a string representation of a `DataFlowType`. */
string ppReprType(DataFlowType t) { result = t.toString() }
private class DataFlowNullType extends Gvn::GvnType {
DataFlowNullType() { this = Gvn::getGlobalValueNumber(any(NullType nt)) }

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 1.0.4
version: 1.0.5-dev
groups:
- csharp
- queries

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