Compare commits

...

333 Commits

Author SHA1 Message Date
Andrew Eisenberg
d79b207eb1 Add deprecation notice on swift+linux 2024-08-01 16:05:08 -07:00
Owen Mansel-Chan
c23938d119 Merge pull request #17113 from owen-mc/go/xmlpath/add-more-package-paths
Go: add more import paths for `xmlpath`
2024-08-01 16:26:33 +01:00
Owen Mansel-Chan
1a697fe993 Merge pull request #17115 from owen-mc/go/update-frameworks
Go: add newly modeled packages to frameworks.csv
2024-08-01 15:13:12 +01:00
Owen Mansel-Chan
3ccdce291a Update test expectations 2024-08-01 15:12:08 +01:00
Owen Mansel-Chan
62adb31ca6 Add more import paths for xmlpath 2024-08-01 14:52:19 +01:00
Owen Mansel-Chan
9d866192a6 Add paths from QL models to MaD models 2024-08-01 14:52:18 +01:00
Owen Mansel-Chan
e051815d96 Merge pull request #17119 from owen-mc/go/finish-converting-tests-to-model-pretty-printing
Go: finish converting tests to model pretty printing
2024-08-01 14:04:02 +01:00
Owen Mansel-Chan
8325c4c69c Updated .expected files 2024-08-01 13:12:21 +01:00
Owen Mansel-Chan
cbe54717f6 Revert "Revert post-processing for 6 queries pending bug fix"
This reverts commit a8236e1545.
2024-08-01 13:10:06 +01:00
Anders Schack-Mulligen
776c01aa8d Merge pull request #17117 from aschackmull/dataflow/qltest-provenance-workaround
Dataflow: Allow printing multiple models for one MaDId.
2024-08-01 13:52:58 +02:00
Anders Schack-Mulligen
90272ddbfa Dataflow: Allow printing multiple models for one MaDId. 2024-08-01 13:04:24 +02:00
Owen Mansel-Chan
d5dc95f1e6 Update frameworks.csv 2024-08-01 11:03:50 +01:00
Anders Schack-Mulligen
377301a55a Merge pull request #17108 from aschackmull/dataflow/flowthrough-provenance
Dataflow: Propagate provenance correctly for flow-through wrappers.
2024-08-01 09:35:56 +02:00
Owen Mansel-Chan
97c9207595 Merge pull request #17104 from owen-mc/go/add-extra-go-jose-package-path
Go: Fix missing `go-jose` package path
2024-08-01 00:14:46 +01:00
yoff
251036c6b4 Merge pull request #17080 from sylwia-budzynska/streamlit
Python: Add Streamlit models
2024-07-31 18:20:11 +02:00
Jami
f9f57e9122 Merge pull request #17023 from jcogs33/jcogs33/java/add-apache-ant-path-inj-sinks
Java: add apache-ant `Property` path injection sinks
2024-07-31 11:04:13 -04:00
Geoffrey White
20672acb74 Merge pull request #17110 from geoffw0/memfree
C++: Improve cpp/memory-may-not-be-freed
2024-07-31 15:59:42 +01:00
Mathias Vorreiter Pedersen
06a4f907ef Merge pull request #17109 from MathiasVP/constexpr-if-unevaluated
C++: Mark `constexpr if` as unevaluated
2024-07-31 15:34:29 +01:00
Owen Mansel-Chan
6280ed2a6b Merge pull request #13555 from am0o0/amammad-java-bombs
Java: Decompression Bombs
2024-07-31 14:55:28 +01:00
Geoffrey White
c172b946a1 C++: Change note. 2024-07-31 14:55:15 +01:00
Geoffrey White
4aea4c0323 C++: Simple fix. 2024-07-31 14:46:25 +01:00
Geoffrey White
c04428dedc C++: Add test cases for the memory freed queries. 2024-07-31 14:03:56 +01:00
Anders Schack-Mulligen
9724516c84 C#/Go/Java/Python/Ruby: Accept qltest .expected changes. 2024-07-31 14:45:10 +02:00
Anders Schack-Mulligen
af06763c42 Dataflow: Propagate provenance correctly for flow-through wrappers. 2024-07-31 14:37:13 +02:00
Jami
4fb29c4473 Merge branch 'main' into jcogs33/java/add-apache-ant-path-inj-sinks 2024-07-31 08:15:07 -04:00
Mathias Vorreiter Pedersen
61eda0df9d C++: Add change note. 2024-07-31 13:13:19 +01:00
Jami
05b0a3f41c Merge pull request #17093 from jcogs33/jcogs33/java/provenance-postprocess-qltest-remaining-lib-tests
Java: Add support for post-process provenance pretty-printing in `.ql` library-tests
2024-07-31 08:11:15 -04:00
Mathias Vorreiter Pedersen
fe575df325 C++: Mark constexpr if as unevalauted. 2024-07-31 13:09:12 +01:00
Mathias Vorreiter Pedersen
4e62dc81d2 C++: Add constexpr if testcase. 2024-07-31 13:08:49 +01:00
yoff
123dcc75d1 Merge pull request #16971 from RasmusWL/mad-dict-source
Python: Add MaD support for DictionaryElement/DictionaryElementAny for sources
2024-07-31 13:40:07 +02:00
Sylwia Budzynska
9bd00c9e1e Change Gradio rfs test to use shared rfs test module 2024-07-31 13:25:32 +02:00
Sylwia Budzynska
2a6ad00a2f Fix typo 2024-07-31 13:22:27 +02:00
Sylwia Budzynska
72e7b6c872 Update python/ql/lib/semmle/python/frameworks/Streamlit.qll
Co-authored-by: yoff <lerchedahl@gmail.com>
2024-07-31 13:20:01 +02:00
Owen Mansel-Chan
01c6dbaa27 Accept provenance numbering changes 2024-07-31 12:19:18 +01:00
Owen Mansel-Chan
8901b1fd14 Merge pull request #17100 from owen-mc/java/sensitive-log/ignore-tokenizer
Java: whitelist variable names containing "tokenizer" for `java/sensitive-log`
2024-07-31 12:16:03 +01:00
Owen Mansel-Chan
59e22f6cd9 Merge pull request #17101 from owen-mc/java/dead-ref-types-junit-4-5
Java: Fix FPs in `java/unused-reference-type` for JUnit 4-style tests
2024-07-31 11:11:35 +01:00
Owen Mansel-Chan
e4cd29efc6 Fix missing go-jose package path 2024-07-31 11:09:53 +01:00
Cornelius Riemenschneider
d75da82528 Merge pull request #17102 from github/criemen/installer-ripunzip
Bazel installer: Retry ripunzip step.
2024-07-31 12:04:20 +02:00
Owen Mansel-Chan
f953249692 Merge pull request #17103 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-31 10:47:08 +01:00
Cornelius Riemenschneider
de47838c36 Remove unused exception class. 2024-07-31 11:31:11 +02:00
Owen Mansel-Chan
f8e8b362ab Merge branch 'main' into workflow/coverage/update 2024-07-31 10:07:35 +01:00
Owen Mansel-Chan
3ece3ec50f Merge pull request #17092 from owen-mc/go/provenance-postprocess-qltest
Go: Add support for provenance pretty-printing
2024-07-31 09:54:28 +01:00
Cornelius Riemenschneider
1ce15ae2fd Fix exit code when ripunzip isn't called. 2024-07-31 08:09:53 +02:00
github-actions[bot]
d0c2b4a60f Add changed framework coverage reports 2024-07-31 00:15:22 +00:00
Edward Minnix III
bae0ea5599 Merge pull request #17042 from github/workflow/coverage/update
Update CSV framework coverage reports
2024-07-30 20:04:23 -04:00
Cornelius Riemenschneider
fa6d61809e Fix hang for targets without ripunzip. 2024-07-31 00:38:50 +02:00
Jami
d04dc9afe0 Merge pull request #17087 from jcogs33/jcogs33/java/provenance-postprocess-qltest
Java: Add support for provenance pretty-printing as a qltest postprocess step
2024-07-30 16:55:26 -04:00
Jeroen Ketema
f986484813 Merge pull request #17098 from jketema/deduction
C++: Update tests after extractor changes
2024-07-30 21:08:40 +02:00
Cornelius Riemenschneider
674a5bb9b4 Bazel installer: Retry ripunzip step.
Ripunzip is great, but occasionally bugs out due to a parallelism issue.
As we don't want this to fail CI, retry the entire ripunzip/installation step
up to 3 times.
We need to clean up the working directory as ripunzip doesn't support overwriting
files. I've not been able to test this with the original issue (it doesn't seem
to reproduce locally for me), but I injected another error and got 3 retries
of installation.
2024-07-30 18:20:19 +02:00
Jami Cogswell
2db07bdbf3 Java: add missing models to experimental expected files 2024-07-30 12:13:18 -04:00
am0o0
40eef25133 use more specefic Classes instead of Call 2024-07-30 18:07:03 +02:00
am0o0
591b1b4f07 use $ SPURIOUS: instead of "this test gives a FP" 2024-07-30 17:53:23 +02:00
Sylwia Budzynska
81f3609c4b Formatting 2024-07-30 17:49:20 +02:00
Sylwia Budzynska
dfc51922ba Change regex 2024-07-30 17:39:34 +02:00
Sylwia Budzynska
ef2b225144 Fix PascalCase 2024-07-30 17:36:55 +02:00
Owen Mansel-Chan
1cb5f35c56 Add change note 2024-07-30 16:29:38 +01:00
Owen Mansel-Chan
cd0af0fc57 Ignore types with methods which have annotations
The motivation is test classes in JUnit 4 and 5 are currently FPs for this. They have methods with `@Test`, so this should fix the FPs.
2024-07-30 16:29:35 +01:00
Owen Mansel-Chan
050dcb1370 Add some tests for java/unused-reference-type 2024-07-30 16:29:11 +01:00
Sylwia Budzynska
f796efe470 Add Streamlit SQLAlchemy models 2024-07-30 17:20:52 +02:00
Sylwia Budzynska
9741ddb926 Add remoteflowsoucre test 2024-07-30 17:20:14 +02:00
Mathias Vorreiter Pedersen
31f68d2da8 Merge pull request #17095 from MathiasVP/mad-free-functions
C++: Proper MaD support for free functions
2024-07-30 16:00:31 +01:00
Jami
2c8f3a58b3 Merge branch 'main' into jcogs33/java/provenance-postprocess-qltest 2024-07-30 10:53:52 -04:00
Owen Mansel-Chan
44b6309e07 Add change note 2024-07-30 15:44:00 +01:00
Owen Mansel-Chan
e259b25428 Add "tokenizer" to sensitive variable name FPs 2024-07-30 15:38:32 +01:00
Owen Mansel-Chan
0704946324 Factor out matching sensitive variable name FPs 2024-07-30 15:37:54 +01:00
Owen Mansel-Chan
bdff0fdcc5 Add test for "tokenizer" 2024-07-30 15:37:46 +01:00
Owen Mansel-Chan
0d71072f94 Make test more compact 2024-07-30 15:36:59 +01:00
Mathias Vorreiter Pedersen
6d8a83fc1f C++: Take out the 'Element' content from std::format model. 2024-07-30 15:31:18 +01:00
Arthur Baars
0d469536ae Merge pull request #17065 from github/aibaars/proxy-tests
Java: integration tests with proxy server
2024-07-30 15:53:45 +02:00
Mathias Vorreiter Pedersen
ef0370b64e C++: Respond to review comments. 2024-07-30 13:19:02 +01:00
Owen Mansel-Chan
a8236e1545 Revert post-processing for 6 queries pending bug fix
This commit will be reverted when a bug is fixed which is currently
stopping these tests from working with post-processing.
2024-07-30 12:58:01 +01:00
Owen Mansel-Chan
ffeb86c1f5 Update .expected files 2024-07-30 12:54:42 +01:00
Jeroen Ketema
5455a365d1 C++: Update tests after extractor changes 2024-07-30 13:52:23 +02:00
Anders Schack-Mulligen
5073f4f7dd Merge pull request #17096 from aschackmull/java/pp-experimental-models
Java: Pretty-print experimental models for qltest.
2024-07-30 13:31:15 +02:00
am0o0
9662950405 add comments for FPs 2024-07-30 13:24:46 +02:00
Sylwia Budzynska
bfd2e4350b Add StreamlitConnection model
Co-authored-by: yoff <lerchedahl@gmail.com>
2024-07-30 12:58:49 +02:00
Mathias Vorreiter Pedersen
afc0d0a078 C++: Accept test changes. 2024-07-30 11:54:20 +01:00
Owen Mansel-Chan
5c8f21d596 Use post-process provenance pretty-printing in ql tests 2024-07-30 11:35:10 +01:00
Owen Mansel-Chan
94f290411f Use post-process provenance pretty-printing in qlref tests 2024-07-30 11:35:09 +01:00
Owen Mansel-Chan
1347f55d89 Merge pull request #17072 from owen-mc/go/mad/convert-sinks
Go: convert request-forgery, xpath-injection and credentials sinks to MaD
2024-07-30 11:18:37 +01:00
Mathias Vorreiter Pedersen
42ee501b96 C++: Use the name without args 2024-07-30 11:18:24 +01:00
Mathias Vorreiter Pedersen
f932e515a7 C++: Accept test changes. 2024-07-30 11:11:38 +01:00
Mathias Vorreiter Pedersen
68a972d578 C++: Delete code that's now dead. 2024-07-30 11:11:37 +01:00
Mathias Vorreiter Pedersen
6b37cb0718 C++: Use the same 'template expansion mechanism' for free functions that we use for member functions. 2024-07-30 11:11:36 +01:00
Anders Schack-Mulligen
da5250d3a7 Java: Pretty-print experimental models for qltest. 2024-07-30 11:43:44 +02:00
Mathias Vorreiter Pedersen
8edf19adc0 C++: Add MaD model for 'std::format'. 2024-07-30 10:15:39 +01:00
Mathias Vorreiter Pedersen
ff788c93c0 C++: Add a model for 'std::format' and a failing test. 2024-07-30 10:13:39 +01:00
Owen Mansel-Chan
9cb01d4573 Merge branch 'main' into go/mad/convert-sinks 2024-07-30 08:03:18 +01:00
github-actions[bot]
d39609254c Add changed framework coverage reports 2024-07-30 00:18:23 +00:00
Alexandre Boulgakov
c989e01197 Merge pull request #17091 from github/sashabu/packs
C++: Update MaD tests with correct template parameter counting in the presence of packs.
2024-07-29 21:06:00 +01:00
am0o0
4dc1a10f71 update tests for zip4j, add aditional flow steps for zip4j, remove BombTypeInputStream class since we don't need it anymore, add a predicate which was for testing porpose and was junk 2024-07-29 18:10:04 +02:00
Jami Cogswell
e226da4f04 Java: use post-process provenance pretty-printing in .ql library-tests 2024-07-29 11:46:28 -04: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
Alexandre Boulgakov
2396c3c798 C++: Update MaD tests with correct template parameter counting in the presence of packs. 2024-07-29 14:59:49 +01: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
Jami Cogswell
bab89c46b6 Java: use post-process provenance pretty-printing in library-tests 2024-07-28 18:13:58 -04:00
Jami Cogswell
0a382bf0cf Java: use post-process provenance pretty-printing in experimental/query-tests 2024-07-28 18:13:20 -04:00
Jami Cogswell
c70d39539e Java: use post-process provenance pretty-printing in query-tests 2024-07-28 18:12:17 -04: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
am0o0
c8749ff82e Merge branch 'amammad-java-bombs' of https://github.com/am0o0/codeql into amammad-java-bombs 2024-07-28 12:15:23 +02:00
am0o0
209fa1a10a update tests 2024-07-28 12:15:07 +02:00
am0o0
0593eaad52 we don't need ConstructorCall for ZipFile anymore since we have a more accurate sink for this 2024-07-28 12:12:07 +02:00
am0o0
cc752113af we don't need TypeInputStreamConstructorArgumentSink anymore 2024-07-28 12:09:52 +02:00
am0o0
7689db7d42 change apache commons sink 2024-07-28 12:09:33 +02:00
am0o0
1b97804f45 update tests 2024-07-28 11:45:48 +02:00
Jeroen Ketema
e1329dff72 Merge pull request #16947 from github/calumgrant/attributes
C++: Update attributes test output
2024-07-26 21:05:46 +02:00
Florin Coada
b6aea3cde1 Merge pull request #17083 from github/changedocs/2.18.1
Update codeql changelog to version 2.18.1
2024-07-26 18:23:16 +01:00
Florin Coada
d189526283 Update docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.18.1.rst
Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com>
2024-07-26 18:16:12 +01:00
Florin Coada
707acdef08 Update codeql-cli-2.18.1.rst 2024-07-26 17:25:58 +01:00
Florin Coada
450137d2cf Update codeql changelog to version 2.18.1 2024-07-26 17:15:23 +01:00
Jami
0ba5a74f6a Merge pull request #17074 from jcogs33/jcogs33/java/fix-regex-use-comments
Java: fix comments about use of sink kind `regex-use`
2024-07-26 08:57:39 -04:00
Sylwia Budzynska
a05266c236 Formatting 2024-07-26 14:55:58 +02:00
Jami
ff9093f2de Merge branch 'main' into jcogs33/java/add-apache-ant-path-inj-sinks 2024-07-26 08:54:27 -04:00
Sylwia Budzynska
358a1b3a20 Fix tests 2024-07-26 14:19:06 +02:00
Sylwia Budzynska
6d1c00742f Add tests and change note 2024-07-26 14:15:43 +02:00
Sylwia Budzynska
221c18934c Add models 2024-07-26 13:23:39 +02: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
Arthur Baars
b34b589005 Merge branch 'main' into aibaars/proxy-tests 2024-07-26 09:24:54 +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
Arthur Baars
9d6260b334 Copy os.environment
Prevents cryptic "OSError: [WinError 10106] The requested service provider could not be loaded or initialized" error from Python subprocess call
2024-07-25 17:59:11 +02: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
Owen Mansel-Chan
1aa63c3f2e Accept model numbering changes 2024-07-25 14:55:50 +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
Owen Mansel-Chan
a6cb511ed7 Convert XPath injection sinks to MaD 2024-07-25 12:56:06 +01:00
Owen Mansel-Chan
f3069c8fbb Improve XPath injection test (incl extra sinks)
Currently the extra sinks are not detected. This will be fixed in the
next commit.
2024-07-25 12:55:05 +01:00
Owen Mansel-Chan
78b66abad3 Convert existing credentials sinks to MaD
I checked that the tests failed when I removed the classes and passed
again when I add the MaD models.
2024-07-25 12:53:16 +01:00
Owen Mansel-Chan
93c9910e6f Convert go/request-forgery sinks to MaD 2024-07-25 12:53:15 +01:00
Owen Mansel-Chan
f7d681516a Allow MaD sinks for go/request-forgery
Request forgery sinks which have `getRequest` different from the sink
itself cannot be modeled using models-as-data.
2024-07-25 12:53:14 +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
Arthur Baars
8e7e7c0188 Update exepected output 2024-07-25 10:50:18 +02:00
Arthur Baars
9478139390 Java: buildless: proxy test with gradle 2024-07-25 08:34:11 +02:00
Arthur Baars
5a1adc51c1 Java: buildless: proxy test with maven 2024-07-25 08:32:48 +02:00
Arthur Baars
a35be08d18 Java: buildess proxy tests: add mitm_proxy.py
A mock implementation of an https man-in-the-middle proxy
2024-07-25 08:32:02 +02: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
Jami Cogswell
d6d2a213e7 Java: add change note 2024-07-19 18:19:37 -04:00
Jami Cogswell
f3e5b55cc4 Java: add path injection sinks for Property.setFile and Property.setResource 2024-07-19 18:04:17 -04: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
Owen Mansel-Chan
9a66e66d66 Merge branch 'main' into amammad-java-bombs 2024-07-18 21:28:23 +01:00
am0o0
7bb7d83b26 remove duplicate sinks
replace some RefType with DecompressionBomb::BombTypeInputStream
2024-07-18 20:55:59 +02:00
am0o0
aef0a03ab6 remove favorites.json 2024-07-18 20:46:40 +02:00
Anders Schack-Mulligen
94078e851c Shared: Add support for provenance pretty-printing as a qltest postprocess step. 2024-07-18 15:34:30 +02:00
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
am0o0
d8e2d355df categorize the new stubs 2024-07-13 17:25:38 +02:00
am0o0
025aa77e79 add the snappy missed sink 2024-07-13 11:15:45 +02:00
am0o0
8c106964ec remove duplicate parts thanks to @owen-mc 2024-07-13 11:11:07 +02:00
am0o0
3868b386f3 update inline tests 2024-07-13 10:47:42 +02:00
am0o0
0165696a1e update tests 2024-07-13 10:33:35 +02:00
am0o0
8ba48e801a fix examples 2024-07-13 10:28:19 +02:00
am0o0
dd3cc33298 move DecompressionBombsFlow::PathGraph to DecompressionBomb.ql 2024-07-13 10:24:07 +02:00
am0o0
c824aa4e45 delete pom.xml 2024-07-13 10:21:53 +02:00
Am
a3b5d2a28d Update java/ql/src/experimental/Security/CWE/CWE-522-DecompressionBombs/DecompressionBomb.qhelp
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-07-13 10:20:43 +02:00
Am
4fbf76008e Update java/ql/src/experimental/Security/CWE/CWE-522-DecompressionBombs/DecompressionBomb.qhelp
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2024-07-13 10:20:25 +02:00
Rasmus Wriedt Larsen
efcd4e297e Add change-note 2024-07-12 15:21:51 +02:00
Rasmus Wriedt Larsen
db8a5306cf Python: Add MaD support for DictionaryElement/DictionaryElementAny for sources 2024-07-12 15:19:40 +02:00
Rasmus Wriedt Larsen
eed8b3e87b Python: Add more tests for MaD sources 2024-07-12 15:10:23 +02:00
am0o0
dd4bce8e30 finilize tests 2024-07-09 19:48:58 +02:00
am0o0
7a5838f1a2 MethodAccess => MethodCall 2024-07-09 19:43:22 +02:00
am0o0
e87d2fe922 remove redundent imports 2024-07-09 19:41:06 +02: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
am0o0
fe1103d997 add stubs, upgrade test to inline test, update test files 2024-07-04 15:25:36 +02:00
am0o0
7df59ffe6c update tests, is not completed yet :) 2024-07-01 18:22:27 +02:00
am0o0
a6833945c1 remove additional taint steps and flow states 2024-07-01 16:07:44 +02:00
am0o0
d31711bd89 merge all ne flow sources into one by extending current abstract class 2024-07-01 15:16:44 +02:00
am0o0
f1324a413a update qlhelp 2024-07-01 15:09:56 +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
am0o0
02b0b402d6 remove useless predicate
add missed FlowState
2024-05-12 19:29:37 +02:00
am0o0
484923e706 update test files 2024-05-12 18:21:17 +02:00
am0o0
be03e582c6 remove isBarrier 2024-05-12 18:17:47 +02:00
am0o0
9fffd7846a remove empty predicates, fix FP for zipFile 2024-05-12 18:16:57 +02:00
am0o0
c9daf914cb remove unused predicate 2024-05-12 14:09:55 +02:00
am0o0
3eb5778543 upgrade FlowState to new DecompressionState 2024-05-12 14:08:52 +02:00
am0o0
e23cbeda24 update to MethodCall 2024-05-12 13:54:21 +02:00
am0o0
4b68dd2315 add new additional taint steps, fix some comments 2024-05-12 13:51:08 +02:00
Am
9946e07f36 Merge branch 'github:main' into amammad-java-bombs 2024-05-12 13:17:02 +02:00
amammad
59fb479895 update tests 2023-10-14 12:28:58 +02:00
amammad
e34cc42441 fix a mistake 2023-10-14 12:18:13 +02:00
amammad
7fcf39277d modularize 2023-10-14 12:04:25 +02:00
amammad
863fa364e2 remove CLI sources Library file & unused file system sinks 2023-09-30 20:11:14 +10:00
amammad
bb8063c0f4 remove CLI sources & unused imports 2023-09-30 06:07:44 +10:00
amammad
2ab10262fc V3: better sinks, replace sinks arguments to sinks method accesses 2023-09-30 06:06:34 +10:00
amammad
83cffea1a1 v3 2023-09-30 05:56:39 +10:00
amammad
3e9c3e6987 remove inputStream and its subclasses module which has no impact on query now! 2023-09-30 04:28:37 +10:00
amammad
c1b9310ec2 add comments for modules & remote local sources 2023-09-30 04:28:02 +10:00
amammad
9877294b1c V2, this version is really better than V1 2023-09-06 07:08:01 +10:00
amammad
193693565c add Inflater 2023-08-31 23:21:33 +10:00
amammad
45499b03d2 change qury file name same as qhelp name 2023-06-26 21:23:22 +10:00
amammad
21b5571bff V1.1 add additional steps for read methods which I can summarize every single declared sanitizer on the sink whitin isSink predicate 2023-06-25 00:35:37 +10:00
amammad
7354db873a V1 Bombs 2023-06-24 08:57:57 +10:00
616 changed files with 103927 additions and 12006 deletions

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

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*1]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*2]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*3]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*4]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*5]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*6]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*7]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*8]", "ReturnValue", "taint", "manual"]

View File

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

View File

@@ -156,7 +156,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
* A C++ `using` directive or `using` declaration. * A C++ `using` directive or `using` declaration.
*/ */
class UsingEntry extends Locatable, @using { 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 { class UsingDeclarationEntry extends UsingEntry {
UsingDeclarationEntry() { UsingDeclarationEntry() { usings(underlyingElement(this), _, _, 1) }
not exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
}
/** /**
* Gets the declaration that is referenced by this using declaration. For * Gets the declaration that is referenced by this using declaration. For
* example, `std::string` in `using std::string`. * 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() } override string toString() { result = "using " + this.getDeclaration().getDescription() }
} }
@@ -186,19 +184,36 @@ class UsingDeclarationEntry extends UsingEntry {
* ``` * ```
*/ */
class UsingDirectiveEntry extends UsingEntry { class UsingDirectiveEntry extends UsingEntry {
UsingDirectiveEntry() { UsingDirectiveEntry() { usings(underlyingElement(this), _, _, 2) }
exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
}
/** /**
* Gets the namespace that is referenced by this using directive. For * Gets the namespace that is referenced by this using directive. For
* example, `std` in `using namespace std`. * 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() } 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 * Holds if `g` is an instance of `GlobalNamespace`. This predicate
* is used suppress a warning in `GlobalNamespace.getADeclaration()` * is used suppress a warning in `GlobalNamespace.getADeclaration()`

View File

@@ -435,12 +435,17 @@ private predicate elementSpec(
} }
/** Gets the fully templated version of `f`. */ /** Gets the fully templated version of `f`. */
private Function getFullyTemplatedMemberFunction(Function f) { private Function getFullyTemplatedFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and not f.isFromUninstantiatedTemplate(_) and
exists(Class c, Class templateClass, int i | (
c.isConstructedFrom(templateClass) and exists(Class c, Class templateClass, int i |
f = c.getAMember(i) and c.isConstructedFrom(templateClass) and
result = templateClass.getCanonicalMember(i) f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
or
not exists(f.getDeclaringType()) and
f.isConstructedFrom(result)
) )
} }
@@ -464,14 +469,14 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
*/ */
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) { private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction | exists(Function templateFunction |
templateFunction = getFullyTemplatedMemberFunction(f) and templateFunction = getFullyTemplatedFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and remaining = templateFunction.getNumberOfTemplateArguments() and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n) result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
) )
or or
exists(string mid, TemplateParameter tp, Function templateFunction | exists(string mid, TemplateParameter tp, Function templateFunction |
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
templateFunction = getFullyTemplatedMemberFunction(f) and templateFunction = getFullyTemplatedFunction(f) and
tp = templateFunction.getTemplateArgument(remaining) and tp = templateFunction.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString()) result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
) )
@@ -482,12 +487,18 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
* with `class:N` (where `N` is the index of the template). * with `class:N` (where `N` is the index of the template).
*/ */
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) { private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
// If there is a declaring type then we start by expanding the function templates
exists(Class template | exists(Class template |
f.getDeclaringType().isConstructedFrom(template) and f.getDeclaringType().isConstructedFrom(template) and
remaining = template.getNumberOfTemplateArguments() and remaining = template.getNumberOfTemplateArguments() and
result = getTypeNameWithoutFunctionTemplates(f, n, 0) result = getTypeNameWithoutFunctionTemplates(f, n, 0)
) )
or or
// If there is no declaring type we're done after expanding the function templates
not exists(f.getDeclaringType()) and
remaining = 0 and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
or
exists(string mid, TemplateParameter tp, Class template | exists(string mid, TemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
f.getDeclaringType().isConstructedFrom(template) and f.getDeclaringType().isConstructedFrom(template) and
@@ -570,38 +581,6 @@ private string getSignatureWithoutFunctionTemplateNames(
) )
} }
private string paramsStringPart(Function c, int i) {
not c.isFromUninstantiatedTemplate(_) and
(
i = -1 and result = "(" and exists(c)
or
exists(int n, string p | getParameterTypeName(c, n) = p |
i = 2 * n and result = p
or
i = 2 * n - 1 and result = "," and n != 0
)
or
i = 2 * c.getNumberOfParameters() and result = ")"
)
}
/**
* Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
*
* Returns the empty string if the callable has no parameters.
* Parameter types are represented by their type erasure.
*/
cached
private string paramsString(Function c) {
result = concat(int i | | paramsStringPart(c, i) order by i)
}
bindingset[func]
private predicate matchesSignature(Function func, string signature) {
signature = "" or
paramsString(func) = signature
}
/** /**
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and * Holds if `elementSpec(_, type, _, name, signature, _)` holds and
* - `typeArgs` represents the named template parameters supplied to `type`, and * - `typeArgs` represents the named template parameters supplied to `type`, and
@@ -750,17 +729,17 @@ private predicate elementSpecWithArguments0(
/** /**
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and * Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
* `method`'s signature matches `signature`. * `func`'s signature matches `signature`.
* *
* `signature` may contain template parameter names that are bound by `type` and `name`. * `signature` may contain template parameter names that are bound by `type` and `name`.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate elementSpecMatchesSignature( private predicate elementSpecMatchesSignature(
Function method, string namespace, string type, boolean subtypes, string name, string signature Function func, string namespace, string type, boolean subtypes, string name, string signature
) { ) {
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name), elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
pragma[only_bind_into](signature), _) and pragma[only_bind_into](signature), _) and
signatureMatches(method, signature, type, name, 0) signatureMatches(func, signature, type, name, 0)
} }
/** /**
@@ -776,13 +755,22 @@ private predicate hasClassAndName(Class classWithMethod, Function method, string
) )
} }
bindingset[name]
pragma[inline_late]
private predicate funcHasQualifiedName(Function func, string namespace, string name) {
exists(string nameWithoutArgs |
parseAngles(name, nameWithoutArgs, _, "") and
func.hasQualifiedName(namespace, nameWithoutArgs)
)
}
/** /**
* Holds if `namedClass` is in namespace `namespace` and has * Holds if `namedClass` is in namespace `namespace` and has
* name `type` (excluding any template parameters). * name `type` (excluding any template parameters).
*/ */
bindingset[type, namespace] bindingset[type, namespace]
pragma[inline_late] pragma[inline_late]
private predicate hasQualifiedName(Class namedClass, string namespace, string type) { private predicate classHasQualifiedName(Class namedClass, string namespace, string type) {
exists(string typeWithoutArgs | exists(string typeWithoutArgs |
parseAngles(type, typeWithoutArgs, _, "") and parseAngles(type, typeWithoutArgs, _, "") and
namedClass.hasQualifiedName(namespace, typeWithoutArgs) namedClass.hasQualifiedName(namespace, typeWithoutArgs)
@@ -804,15 +792,16 @@ private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature string namespace, string type, boolean subtypes, string name, string signature
) { ) {
( (
elementSpec(namespace, type, subtypes, name, signature, _) and
// Non-member functions // Non-member functions
exists(Function func | elementSpec(namespace, type, subtypes, name, signature, _) and
func.hasQualifiedName(namespace, name) and subtypes = false and
type = "" and type = "" and
matchesSignature(func, signature) and (
subtypes = false and elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
not exists(func.getDeclaringType()) and or
result = func signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
funcHasQualifiedName(result, namespace, name)
) )
or or
// Member functions // Member functions
@@ -825,7 +814,7 @@ private Element interpretElement0(
elementSpec(namespace, type, subtypes, name, "", _) and elementSpec(namespace, type, subtypes, name, "", _) and
hasClassAndName(classWithMethod, result, name) hasClassAndName(classWithMethod, result, name)
) and ) and
hasQualifiedName(namedClass, namespace, type) and classHasQualifiedName(namedClass, namespace, type) and
( (
// member declared in the named type or a subtype of it // member declared in the named type or a subtype of it
subtypes = true and subtypes = true and

View File

@@ -215,19 +215,16 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
predicate localMustFlowStep(Node node1, Node node2) { none() } predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */ /** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) { DataFlowType getNodeType(Node n) {
exists(n) and exists(n) and
result instanceof VoidType // stub implementation 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 * 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`. * 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 t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
} }
@@ -243,7 +240,11 @@ class DataFlowCallable extends Function { }
class DataFlowExpr = Expr; 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. */ /** A function call relevant for data flow. */
class DataFlowCall extends Expr instanceof Call { class DataFlowCall extends Expr instanceof Call {

View File

@@ -307,6 +307,10 @@ class Expr extends StmtParent, @expr {
) )
or or
exists(Decltype d | d.getExpr() = this.getParentWithConversions*()) exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
or
exists(ConstexprIfStmt constIf |
constIf.getControllingExpr() = this.getParentWithConversions*()
)
} }
/** /**
@@ -855,6 +859,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. * Gets the type that is being allocated.
* *
@@ -1025,6 +1039,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. * Gets the object or array being deleted.
*/ */

View File

@@ -994,9 +994,6 @@ DataFlowType getNodeType(Node n) {
result instanceof VoidType // stub implementation 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 * 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`. * a node of type `t1` to a node of type `t2`.
@@ -1097,7 +1094,11 @@ class SummarizedCallable extends DataFlowCallable, TSummarizedCallable {
class DataFlowExpr = Expr; class DataFlowExpr = Expr;
class DataFlowType = Type; final private class TypeFinal = Type;
class DataFlowType extends TypeFinal {
string toString() { result = "" }
}
cached cached
private newtype TDataFlowCall = private newtype TDataFlowCall =

View File

@@ -338,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled() 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 * 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 * 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) { predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes() allocation.alwaysEscapes()
or or
exists(IREscapeAnalysisConfiguration config | exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction()) resultEscapesNonReturn(allocation.getABaseInstruction())
or
operandConsumesEscaped(allocation)
) )
or or
Configuration::phaseNeedsSoundEscapeAnalysis() and 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() } 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.IntegerConstant as Ints
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
private import semmle.code.cpp.ir.implementation.internal.OperandTag private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import AliasConfiguration import AliasConfiguration
private import codeql.util.Boolean private import codeql.util.Boolean
private class IntValue = Ints::IntValue; private class IntValue = Ints::IntValue;
@@ -227,13 +227,15 @@ private newtype TMemoryLocation =
TAllAliasedMemory(IRFunction irFunc, Boolean isMayAccess) 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: * one of the following:
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is * - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
* unknown. * unknown.
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`. * - `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() { final string toString() {
if this.isMayAccess() if this.isMayAccess()
then result = "?" + this.toStringInternal() then result = "?" + this.toStringInternal()
@@ -294,9 +296,9 @@ abstract class MemoryLocation extends TMemoryLocation {
* represented by a `MemoryLocation` that totally overlaps all other * represented by a `MemoryLocation` that totally overlaps all other
* `MemoryLocations` in the set. * `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; Allocation var;
boolean isMayAccess; boolean isMayAccess;
@@ -424,7 +426,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
* `{a, b}` into a memory location that represents _all_ of the allocations * `{a, b}` into a memory location that represents _all_ of the allocations
* in the set. * in the set.
*/ */
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation { class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation0 {
VariableGroup vg; VariableGroup vg;
boolean isMayAccess; boolean isMayAccess;
boolean isAll; 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`. * 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; IRFunction irFunc;
boolean isMayAccess; 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 * 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. * not access memory on the current function's stack frame.
*/ */
class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation { class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation0 {
IRFunction irFunc; IRFunction irFunc;
boolean isMayAccess; boolean isMayAccess;
@@ -589,7 +591,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
/** /**
* An access to all aliased memory. * An access to all aliased memory.
*/ */
class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation { class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation0 {
IRFunction irFunc; IRFunction irFunc;
boolean isMayAccess; 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`. * 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 | exists(Overlap overlap |
// Compute the overlap based only on the extent. // Compute the overlap based only on the extent.
overlap = getExtentOverlap(def, use) and 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 * based only on the set of memory locations accessed. Handling of "may" accesses and read-only
* locations occurs in `getOverlap()`. * 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. // 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. // AllAliasedMemory must totally overlap any location within the same virtual variable.
@@ -861,6 +863,40 @@ predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMem
bindingset[result, b] bindingset[result, b]
private boolean unbindBool(boolean b) { result != b.booleanNot() } 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) { MemoryLocation getResultMemoryLocation(Instruction instr) {
not canReuseSsaForOldResult(instr) and not canReuseSsaForOldResult(instr) and
exists(MemoryAccessKind kind, boolean isMayAccess | 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 not canReuseSsaForOldResult(operand.getAnyDef()) and
exists(MemoryAccessKind kind, boolean isMayAccess | exists(MemoryAccessKind kind |
kind = operand.getMemoryAccess() and kind = operand.getMemoryAccess() and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) 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. */ /** Gets the start bit offset of a `MemoryLocation`, if any. */
int getStartBitOffset(VariableMemoryLocation location) { int getStartBitOffset(VariableMemoryLocation location) {
result = location.getStartBitOffset() and Ints::hasValue(result) result = location.getStartBitOffset() and Ints::hasValue(result)

View File

@@ -933,11 +933,15 @@ module DefUse {
bindingset[index, block] bindingset[index, block]
pragma[inline_late] pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) { 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 if
getNewBlock(block) = func.getEntryBlock() and block = entryBlock and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and not i instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction not i instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func)) then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index else result = 2 * index
) )

View File

@@ -338,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled() 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 * 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 * 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) { predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes() allocation.alwaysEscapes()
or or
exists(IREscapeAnalysisConfiguration config | exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction()) resultEscapesNonReturn(allocation.getABaseInstruction())
or
operandConsumesEscaped(allocation)
) )
or or
Configuration::phaseNeedsSoundEscapeAnalysis() and Configuration::phaseNeedsSoundEscapeAnalysis() and
resultEscapesNonReturn(allocation.getABaseInstruction()) (resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
} }
/** /**

View File

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

View File

@@ -933,11 +933,15 @@ module DefUse {
bindingset[index, block] bindingset[index, block]
pragma[inline_late] pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) { 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 if
getNewBlock(block) = func.getEntryBlock() and block = entryBlock and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and not i instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction not i instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func)) then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index else result = 2 * index
) )

View File

@@ -1,7 +1,7 @@
import AliasAnalysis import AliasAnalysis
private import SimpleSSAImports private import SimpleSSAImports
import SimpleSSAPublicImports import SimpleSSAPublicImports
private import AliasConfiguration import AliasConfiguration
private import codeql.util.Unit private import codeql.util.Unit
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) { 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.StdMap
private import implementations.StdSet private import implementations.StdSet
private import implementations.StdString 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.Swap
private import implementations.GetDelim private import implementations.GetDelim
private import implementations.SmartPointer 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() } 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 * Gets the `FunctionInput` corresponding to an iterator parameter to
* user-defined operator `op`, at `index`. * user-defined operator `op`, at `index`.
@@ -579,23 +614,43 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 } 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. * A `begin` member function, or a related function, that returns an iterator.
*/ */
class BeginFunction extends MemberFunction { class BeginFunction extends Function {
BeginFunction() { BeginFunction() {
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and this.getUnspecifiedType() instanceof Iterator and
this.getType().getUnspecifiedType() instanceof Iterator (
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. * An `end` member function, or a related function, that returns an iterator.
*/ */
class EndFunction extends MemberFunction { class EndFunction extends Function {
EndFunction() { EndFunction() {
this.hasName(["end", "cend", "rend", "crend"]) and this.getUnspecifiedType() instanceof Iterator and
this.getType().getUnspecifiedType() instanceof Iterator (
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 * A `begin` or `end` member function, or a related member function, that
* returns an iterator. * returns an iterator.
*/ */
class BeginOrEndFunction extends MemberFunction { class BeginOrEndFunction extends Function {
BeginOrEndFunction() { BeginOrEndFunction() {
this instanceof BeginFunction or this instanceof BeginFunction or
this instanceof EndFunction this instanceof EndFunction

View File

@@ -7,6 +7,7 @@
import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/** /**
* The standard functions `printf`, `wprintf` and their glib variants. * The standard functions `printf`, `wprintf` and their glib variants.
@@ -96,7 +97,7 @@ private class Sprintf extends FormattingFunction {
/** /**
* Implements `Snprintf`. * Implements `Snprintf`.
*/ */
private class SnprintfImpl extends Snprintf { private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
SnprintfImpl() { SnprintfImpl() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
@@ -143,6 +144,26 @@ private class SnprintfImpl extends Snprintf {
} }
override int getSizeParameterIndex() { result = 1 } 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.FlowSource
import semmle.code.cpp.models.interfaces.Iterator 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 * 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`. * The standard container functions `push_back` and `push_front`.
*/ */
class StdSequenceContainerPush extends MemberFunction { class StdSequenceContainerPush extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerPush() { StdSequenceContainerPush() {
this.getClassAndName("push_back") instanceof Vector or this.getClassAndName("push_back") instanceof Vector or
this.getClassAndName(["push_back", "push_front"]) instanceof Deque 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.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>` 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`. * The standard container functions `insert` and `insert_after`.
*/ */
class StdSequenceContainerInsert extends MemberFunction { class StdSequenceContainerInsert extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerInsert() { StdSequenceContainerInsert() {
this.getClassAndName("insert") instanceof Deque or this.getClassAndName("insert") instanceof Deque or
this.getClassAndName("insert") instanceof List 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. * Gets the index of a parameter to this function that is an iterator.
*/ */
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof 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[]`. * The standard container functions `at` and `operator[]`.
*/ */
class StdSequenceContainerAt extends MemberFunction { class StdSequenceContainerAt extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerAt() { StdSequenceContainerAt() {
this.getClassAndName(["at", "operator[]"]) instanceof Array or this.getClassAndName(["at", "operator[]"]) instanceof Array or
this.getClassAndName(["at", "operator[]"]) instanceof Deque or this.getClassAndName(["at", "operator[]"]) instanceof Deque or
this.getClassAndName(["at", "operator[]"]) instanceof Vector 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 } 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. * 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.Taint
import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator 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. * 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. * 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 } StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
/** /**
@@ -35,6 +39,23 @@ private class StdMapConstructor extends Constructor, TaintFunction {
output.isQualifierObject() 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 } 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value // flow from qualifier to referenced return value
input.isQualifierObject() and input.isQualifierObject() and
@@ -144,6 +165,18 @@ private class StdMapAtModels extends StdMapAt, TaintFunction {
output.isQualifierObject() 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() } override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
} }
@@ -187,3 +220,63 @@ private class StdMapEqualRange extends TaintFunction {
output.isReturnValue() 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.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/** /**
* An instantiation of `std::pair<T1, T2>`. * An instantiation of `std::pair<T1, T2>`.
@@ -37,7 +39,9 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
/** /**
* Additional model for `std::pair` constructors. * 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 } StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
/** /**
@@ -59,4 +63,77 @@ private class StdPairConstructor extends Constructor, TaintFunction {
output.isQualifierObject() 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.Taint
import semmle.code.cpp.models.interfaces.Iterator import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.DataFlow 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. * The `std::basic_string` template class instantiations.
@@ -78,7 +80,9 @@ abstract private class StdStringTaintFunction extends TaintFunction {
* std::string b(a.begin(), a.end()); * 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 } StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -94,6 +98,42 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
output.isQualifierObject() 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+`. * The (non-member) `std::string` function `operator+`.
*/ */
private class StdStringPlus extends StdStringTaintFunction { private class StdStringPlus extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringPlus() { StdStringPlus() {
this.hasQualifiedName(["std", "bsl"], "operator+") and this.hasQualifiedName(["std", "bsl"], "operator+") and
this.getUnspecifiedType() instanceof StdBasicString this.getUnspecifiedType() instanceof StdBasicString
@@ -178,6 +218,22 @@ private class StdStringPlus extends StdStringTaintFunction {
) and ) and
output.isReturnValue() 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 * All of these functions combine the existing string with a new
* string (or character) from one of the arguments. * string (or character) from one of the arguments.
*/ */
private class StdStringAppend extends StdStringTaintFunction { private class StdStringAppend extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringAppend() { StdStringAppend() {
this.getClassAndName(["operator+=", "append", "replace"]) instanceof StdBasicString 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 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[]`. * 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 } StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { 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 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") } 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). * 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") } 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), * The `std::ostream` functions `operator<<` (defined as a member function),
* `put` and `write`. * `put` and `write`.

View File

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

@@ -39,7 +39,7 @@ predicate allocCallOrIndirect(Expr e) {
allocCallOrIndirect(rtn.getExpr()) allocCallOrIndirect(rtn.getExpr())
or or
// return variable assigned with alloc // return variable assigned with alloc
exists(Variable v | exists(StackVariable v |
v = rtn.getExpr().(VariableAccess).getTarget() and v = rtn.getExpr().(VariableAccess).getTarget() and
allocCallOrIndirect(v.getAnAssignedValue()) and allocCallOrIndirect(v.getAnAssignedValue()) and
not assignedToFieldOrGlobal(v, _) not assignedToFieldOrGlobal(v, _)

View File

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

View File

@@ -15,6 +15,7 @@
import cpp import cpp
import semmle.code.cpp.models.Models import semmle.code.cpp.models.Models
import semmle.code.cpp.commons.Buffer
predicate baseType(AllocationExpr alloc, Type base) { predicate baseType(AllocationExpr alloc, Type base) {
exists(PointerType pointer | exists(PointerType pointer |
@@ -30,7 +31,8 @@ predicate baseType(AllocationExpr alloc, Type base) {
} }
predicate decideOnSize(Type t, int size) { 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()) size = min(t.getSize())
} }
@@ -45,7 +47,8 @@ where
size = 0 or size = 0 or
(allocated / size) * size = allocated (allocated / size) * size = allocated
) and ) 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, select alloc,
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" + "Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
base.getName() + "' (" + basesize.toString() + " bytes)." base.getName() + "' (" + basesize.toString() + " bytes)."

View File

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

View File

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

View File

@@ -1,12 +1,31 @@
void writeCredentials() { #include <sodium.h>
char *password = "cleartext password"; #include <stdio.h>
FILE* file = fopen("credentials.txt", "w"); #include <string.h>
void writeCredentialsBad(FILE *file, const char *cleartextCredentials) {
// BAD: write password to disk in cleartext // BAD: write password to disk in cleartext
fputs(password, file); fputs(cleartextCredentials, file);
// GOOD: encrypt password first
char *encrypted = encrypt(password);
fputs(encrypted, 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

@@ -24,6 +24,11 @@ storing them.</p>
<sample src="CleartextStorage.c" /> <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> </example>
<references> <references>

View File

@@ -1,6 +1,6 @@
void bad(void) { void bad(void) {
char *password = "cleartext password"; const char *password = "cleartext password";
sqlite3 *credentialsDB; sqlite3 *credentialsDB;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
@@ -16,14 +16,15 @@ void bad(void) {
} }
} }
void good(void) { void good(const char *secretKey) {
char *password = "cleartext password"; const char *password = "cleartext password";
sqlite3 *credentialsDB; sqlite3 *credentialsDB;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) { if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
// GOOD: database encryption enabled: // 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); 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) { if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
@@ -33,4 +34,3 @@ void good(void) {
} }
} }
} }

View File

@@ -20,6 +20,8 @@ In the 'GOOD' case, the database (and thus the credentials) are encrypted.</p>
<sample src="CleartextSqliteDatabase.c" /> <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> </example>
<references> <references>

View File

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

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Fixed false positives in the `cpp/memory-may-not-be-freed` ("Memory may not be freed") query involving class methods that returned an allocated field of that class being misidentified as allocators.

View File

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

View File

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

View File

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

View File

@@ -16,6 +16,7 @@
| Dubious signature "(const_iterator,size_type,const T &)" in summary model. | | Dubious signature "(const_iterator,size_type,const T &)" in summary model. |
| Dubious signature "(deque &&)" in summary model. | | Dubious signature "(deque &&)" in summary model. |
| Dubious signature "(deque &&,const Allocator &)" in summary model. | | Dubious signature "(deque &&,const Allocator &)" in summary model. |
| Dubious signature "(format_string,Args &&)" in summary model. |
| Dubious signature "(forward_list &&)" in summary model. | | Dubious signature "(forward_list &&)" in summary model. |
| Dubious signature "(forward_list &&,const Allocator &)" in summary model. | | Dubious signature "(forward_list &&,const Allocator &)" in summary model. |
| Dubious signature "(list &&)" in summary model. | | Dubious signature "(list &&)" in summary model. |

View File

@@ -1,4 +1,4 @@
#include "stl.h"
typedef unsigned long size_t; typedef unsigned long size_t;
typedef struct {} FILE; typedef struct {} FILE;
@@ -157,3 +157,11 @@ void test2()
sink(s[strlen(s) - 1]); // $ ast,ir sink(s[strlen(s) - 1]); // $ ast,ir
sink(ws + (wcslen(ws) / 2)); // $ ast,ir sink(ws + (wcslen(ws) / 2)); // $ ast,ir
} }
void test_format() {
auto s = std::format("{}", string::source());
sink(s); // $ ir MISSING: ast
auto s2 = std::format(string::source());
sink(s2); // $ ir MISSING: ast
}

View File

@@ -447,6 +447,10 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT | | format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT |
| format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT | | format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT |
| format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT | | format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT |
| format.cpp:162:12:162:22 | call to format | format.cpp:163:8:163:8 | s | |
| format.cpp:162:24:162:27 | {} | format.cpp:162:24:162:27 | call to basic_format_string | TAINT |
| format.cpp:165:13:165:23 | call to format | format.cpp:166:8:166:9 | s2 | |
| format.cpp:165:25:165:38 | call to source | format.cpp:165:25:165:40 | call to basic_format_string | TAINT |
| map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | | | map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | |
| map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | | | map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | |
| map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | | | map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | |

View File

@@ -642,3 +642,38 @@ namespace std {
pair<const_iterator, const_iterator> equal_range(const key_type& k) const; pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
}; };
} }
// --- string view ---
namespace std {
template<class CharT, class Traits = char_traits<CharT>>
class basic_string_view {
public:
using size_type = size_t;
basic_string_view() noexcept;
basic_string_view(const basic_string_view&) noexcept;
basic_string_view(const CharT*, size_type);
basic_string_view(const CharT*);
template<class It, class End> basic_string_view(It, End);
template<class R> explicit basic_string_view(R&&);
basic_string_view& operator=(const basic_string_view&) noexcept;
};
using string_view = basic_string_view<char>;
}
// --- format ---
namespace std {
template<class CharT /* class... Args */>
struct basic_format_string {
public:
template<class T> basic_format_string(const T&);
basic_string_view<CharT> get() const noexcept;
};
using format_string = basic_format_string<char>; // simplified from `char, std::type_identity_t<Args>...`
template<class... Args> string format( format_string fmt, Args&&... args );
}

View File

@@ -27,6 +27,10 @@ signatureMatches
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 0 | | stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 0 |
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 | | stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 | | stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | deque | insert<InputIt> | 2 |
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | forward_list | insert_after<InputIt> | 2 |
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | list | insert<InputIt> | 2 |
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
@@ -175,6 +179,7 @@ signatureMatches
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 | | stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 | | stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 | | stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
| stl.h:335:37:335:43 | emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 | | stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
@@ -215,6 +220,19 @@ signatureMatches
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | | stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | | stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | | stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
| stl.h:440:36:440:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:440:36:440:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:448:48:448:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:448:48:448:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:452:42:452:57 | insert_or_assign | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:508:36:508:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:508:36:508:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:520:42:520:57 | insert_or_assign | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 0 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 1 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
@@ -223,6 +241,8 @@ signatureMatches
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | list | assign<InputIt> | 1 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | list | assign<InputIt> | 1 |
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 0 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 1 | | stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
| stl.h:569:36:569:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:569:36:569:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
@@ -231,6 +251,8 @@ signatureMatches
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 | | stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
| stl.h:623:36:623:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:623:36:623:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
@@ -239,6 +261,10 @@ signatureMatches
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 | | stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 0 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 0 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
getSignatureParameterName getSignatureParameterName
| (InputIt,InputIt) | deque | assign<InputIt> | 0 | func:0 | | (InputIt,InputIt) | deque | assign<InputIt> | 0 | func:0 |
| (InputIt,InputIt) | deque | assign<InputIt> | 1 | func:0 | | (InputIt,InputIt) | deque | assign<InputIt> | 1 | func:0 |
@@ -315,6 +341,8 @@ getSignatureParameterName
| (deque &&) | deque | deque | 0 | deque && | | (deque &&) | deque | deque | 0 | deque && |
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 0 | deque && | | (deque &&,const Allocator &) | deque<T,Allocator> | deque | 0 | deque && |
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 1 | const class:1 & | | (deque &&,const Allocator &) | deque<T,Allocator> | deque | 1 | const class:1 & |
| (format_string,Args &&) | | format<Args> | 0 | format_string |
| (format_string,Args &&) | | format<Args> | 1 | func:0 && |
| (forward_list &&) | forward_list | forward_list | 0 | forward_list && | | (forward_list &&) | forward_list | forward_list | 0 | forward_list && |
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 0 | forward_list && | | (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 0 | forward_list && |
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 1 | const class:1 & | | (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 1 | const class:1 & |
@@ -345,6 +373,14 @@ getSignatureParameterName
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 0 | vector && | | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 0 | vector && |
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | const class:1 & | | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | const class:1 & |
getParameterTypeName getParameterTypeName
| smart_pointer.cpp:7:27:7:30 | sink | 0 | shared_ptr & |
| smart_pointer.cpp:7:27:7:30 | sink | 0 | shared_ptr & |
| smart_pointer.cpp:8:27:8:30 | sink | 0 | unique_ptr & |
| smart_pointer.cpp:8:27:8:30 | sink | 0 | unique_ptr & |
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
| stl.h:49:3:49:10 | iterator | 0 | const iterator & | | stl.h:49:3:49:10 | iterator | 0 | const iterator & |
| stl.h:49:3:49:10 | iterator | 0 | const iterator & | | stl.h:49:3:49:10 | iterator | 0 | const iterator & |
| stl.h:49:3:49:10 | iterator | 0 | const iterator & | | stl.h:49:3:49:10 | iterator | 0 | const iterator & |
@@ -377,6 +413,8 @@ getParameterTypeName
| stl.h:88:25:88:33 | operator= | 0 | value_type && | | stl.h:88:25:88:33 | operator= | 0 | value_type && |
| stl.h:91:24:91:33 | operator++ | 0 | int | | stl.h:91:24:91:33 | operator++ | 0 | int |
| stl.h:91:24:91:33 | operator++ | 0 | int | | stl.h:91:24:91:33 | operator++ | 0 | int |
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & | | stl.h:148:3:148:14 | basic_string | 0 | const class:2 & |
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * | | stl.h:149:33:149:44 | basic_string | 0 | const class:0 * |
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & | | stl.h:149:33:149:44 | basic_string | 1 | const class:2 & |
@@ -425,6 +463,10 @@ getParameterTypeName
| stl.h:193:8:193:12 | clear | 2 | size_type | | stl.h:193:8:193:12 | clear | 2 | size_type |
| stl.h:195:8:195:11 | swap | 0 | size_type | | stl.h:195:8:195:11 | swap | 0 | size_type |
| stl.h:195:8:195:11 | swap | 1 | size_type | | stl.h:195:8:195:11 | swap | 1 | size_type |
| stl.h:198:94:198:102 | operator+ | 0 | const basic_string & |
| stl.h:198:94:198:102 | operator+ | 1 | const basic_string & |
| stl.h:199:94:199:102 | operator+ | 0 | const basic_string & |
| stl.h:199:94:199:102 | operator+ | 1 | const func:0 * |
| stl.h:214:33:214:42 | operator>> | 0 | int & | | stl.h:214:33:214:42 | operator>> | 0 | int & |
| stl.h:217:33:217:35 | get | 0 | char_type & | | stl.h:217:33:217:35 | get | 0 | char_type & |
| stl.h:218:33:218:35 | get | 0 | char_type * | | stl.h:218:33:218:35 | get | 0 | char_type * |
@@ -439,10 +481,23 @@ getParameterTypeName
| stl.h:226:32:226:38 | getline | 0 | char_type * | | stl.h:226:32:226:38 | getline | 0 | char_type * |
| stl.h:226:32:226:38 | getline | 1 | streamsize | | stl.h:226:32:226:38 | getline | 1 | streamsize |
| stl.h:226:32:226:38 | getline | 2 | char_type | | stl.h:226:32:226:38 | getline | 2 | char_type |
| stl.h:229:68:229:77 | operator>> | 0 | basic_istream & |
| stl.h:229:68:229:77 | operator>> | 1 | func:0 * |
| stl.h:230:85:230:94 | operator>> | 0 | basic_istream & |
| stl.h:230:85:230:94 | operator>> | 1 | basic_string & |
| stl.h:232:84:232:90 | getline | 0 | basic_istream & |
| stl.h:232:84:232:90 | getline | 1 | basic_string & |
| stl.h:232:84:232:90 | getline | 2 | func:0 |
| stl.h:233:84:233:90 | getline | 0 | basic_istream & |
| stl.h:233:84:233:90 | getline | 1 | basic_string & |
| stl.h:240:33:240:42 | operator<< | 0 | int | | stl.h:240:33:240:42 | operator<< | 0 | int |
| stl.h:242:33:242:35 | put | 0 | char_type | | stl.h:242:33:242:35 | put | 0 | char_type |
| stl.h:243:33:243:37 | write | 0 | const char_type * | | stl.h:243:33:243:37 | write | 0 | const char_type * |
| stl.h:243:33:243:37 | write | 1 | streamsize | | stl.h:243:33:243:37 | write | 1 | streamsize |
| stl.h:247:67:247:76 | operator<< | 0 | basic_ostream & |
| stl.h:247:67:247:76 | operator<< | 1 | const func:0 * |
| stl.h:248:85:248:94 | operator<< | 0 | basic_ostream & |
| stl.h:248:85:248:94 | operator<< | 1 | const basic_string & |
| stl.h:259:12:259:29 | basic_stringstream | 0 | const basic_string & | | stl.h:259:12:259:29 | basic_stringstream | 0 | const basic_string & |
| stl.h:263:23:263:31 | operator= | 0 | basic_stringstream && | | stl.h:263:23:263:31 | operator= | 0 | basic_stringstream && |
| stl.h:265:8:265:11 | swap | 0 | basic_stringstream & | | stl.h:265:8:265:11 | swap | 0 | basic_stringstream & |
@@ -496,11 +551,20 @@ getParameterTypeName
| stl.h:333:42:333:47 | insert | 1 | func:0 | | stl.h:333:42:333:47 | insert | 1 | func:0 |
| stl.h:333:42:333:47 | insert | 2 | func:0 | | stl.h:333:42:333:47 | insert | 2 | func:0 |
| stl.h:333:42:333:47 | insert | 2 | func:0 | | stl.h:333:42:333:47 | insert | 2 | func:0 |
| stl.h:335:37:335:43 | emplace | 0 | const_iterator |
| stl.h:335:37:335:43 | emplace | 1 | func:0 && |
| stl.h:336:33:336:44 | emplace_back | 0 | func:0 && |
| stl.h:338:8:338:11 | swap | 0 | vector & | | stl.h:338:8:338:11 | swap | 0 | vector & |
| stl.h:351:12:351:21 | shared_ptr | 0 | class:0 * | | stl.h:351:12:351:21 | shared_ptr | 0 | class:0 * |
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & | | stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & | | stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
| stl.h:369:12:369:21 | unique_ptr | 0 | class:0 * | | stl.h:369:12:369:21 | unique_ptr | 0 | class:0 * |
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
| stl.h:396:3:396:3 | pair | 0 | const class:0 & | | stl.h:396:3:396:3 | pair | 0 | const class:0 & |
| stl.h:396:3:396:3 | pair | 0 | const class:0 & | | stl.h:396:3:396:3 | pair | 0 | const class:0 & |
| stl.h:396:3:396:3 | pair | 0 | const class:0 & | | stl.h:396:3:396:3 | pair | 0 | const class:0 & |
@@ -524,14 +588,42 @@ getParameterTypeName
| stl.h:397:30:397:33 | pair | 0 | const pair & | | stl.h:397:30:397:33 | pair | 0 | const pair & |
| stl.h:397:30:397:33 | pair | 0 | const pair & | | stl.h:397:30:397:33 | pair | 0 | const pair & |
| stl.h:399:8:399:11 | swap | 0 | pair & | | stl.h:399:8:399:11 | swap | 0 | pair & |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
| stl.h:422:3:422:5 | map | 0 | const map & | | stl.h:422:3:422:5 | map | 0 | const map & |
| stl.h:426:8:426:16 | operator= | 0 | const map & | | stl.h:426:8:426:16 | operator= | 0 | const map & |
| stl.h:435:6:435:15 | operator[] | 0 | key_type && | | stl.h:435:6:435:15 | operator[] | 0 | key_type && |
| stl.h:435:6:435:15 | operator[] | 0 | key_type && | | stl.h:435:6:435:15 | operator[] | 0 | key_type && |
| stl.h:436:6:436:7 | at | 0 | const key_type & | | stl.h:436:6:436:7 | at | 0 | const key_type & |
| stl.h:439:48:439:54 | emplace | 0 | func:0 && |
| stl.h:439:48:439:54 | emplace | 0 | func:0 && |
| stl.h:440:36:440:47 | emplace_hint | 0 | const_iterator |
| stl.h:440:36:440:47 | emplace_hint | 0 | const_iterator |
| stl.h:440:36:440:47 | emplace_hint | 1 | func:0 && |
| stl.h:440:36:440:47 | emplace_hint | 1 | func:0 && |
| stl.h:443:24:443:29 | insert | 0 | value_type && | | stl.h:443:24:443:29 | insert | 0 | value_type && |
| stl.h:445:12:445:17 | insert | 0 | const_iterator | | stl.h:445:12:445:17 | insert | 0 | const_iterator |
| stl.h:445:12:445:17 | insert | 1 | value_type && | | stl.h:445:12:445:17 | insert | 1 | value_type && |
| stl.h:448:48:448:58 | try_emplace | 0 | key_type && |
| stl.h:448:48:448:58 | try_emplace | 0 | key_type && |
| stl.h:448:48:448:58 | try_emplace | 1 | func:0 && |
| stl.h:448:48:448:58 | try_emplace | 1 | func:0 && |
| stl.h:450:36:450:46 | try_emplace | 0 | const_iterator |
| stl.h:450:36:450:46 | try_emplace | 0 | const_iterator |
| stl.h:450:36:450:46 | try_emplace | 1 | key_type && |
| stl.h:450:36:450:46 | try_emplace | 1 | key_type && |
| stl.h:450:36:450:46 | try_emplace | 2 | func:0 && |
| stl.h:450:36:450:46 | try_emplace | 2 | func:0 && |
| stl.h:452:42:452:57 | insert_or_assign | 0 | key_type && | | stl.h:452:42:452:57 | insert_or_assign | 0 | key_type && |
| stl.h:452:42:452:57 | insert_or_assign | 1 | func:0 && | | stl.h:452:42:452:57 | insert_or_assign | 1 | func:0 && |
| stl.h:454:30:454:45 | insert_or_assign | 0 | const_iterator | | stl.h:454:30:454:45 | insert_or_assign | 0 | const_iterator |
@@ -550,9 +642,34 @@ getParameterTypeName
| stl.h:503:16:503:25 | operator[] | 0 | key_type && | | stl.h:503:16:503:25 | operator[] | 0 | key_type && |
| stl.h:503:16:503:25 | operator[] | 0 | key_type && | | stl.h:503:16:503:25 | operator[] | 0 | key_type && |
| stl.h:504:16:504:17 | at | 0 | const key_type & | | stl.h:504:16:504:17 | at | 0 | const key_type & |
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
| stl.h:508:36:508:47 | emplace_hint | 0 | const_iterator |
| stl.h:508:36:508:47 | emplace_hint | 0 | const_iterator |
| stl.h:508:36:508:47 | emplace_hint | 1 | func:0 && |
| stl.h:508:36:508:47 | emplace_hint | 1 | func:0 && |
| stl.h:511:24:511:29 | insert | 0 | value_type && | | stl.h:511:24:511:29 | insert | 0 | value_type && |
| stl.h:513:12:513:17 | insert | 0 | const_iterator | | stl.h:513:12:513:17 | insert | 0 | const_iterator |
| stl.h:513:12:513:17 | insert | 1 | value_type && | | stl.h:513:12:513:17 | insert | 1 | value_type && |
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
| stl.h:518:36:518:46 | try_emplace | 0 | const_iterator |
| stl.h:518:36:518:46 | try_emplace | 0 | const_iterator |
| stl.h:518:36:518:46 | try_emplace | 1 | key_type && |
| stl.h:518:36:518:46 | try_emplace | 1 | key_type && |
| stl.h:518:36:518:46 | try_emplace | 2 | func:0 && |
| stl.h:518:36:518:46 | try_emplace | 2 | func:0 && |
| stl.h:520:42:520:57 | insert_or_assign | 0 | key_type && | | stl.h:520:42:520:57 | insert_or_assign | 0 | key_type && |
| stl.h:520:42:520:57 | insert_or_assign | 1 | func:0 && | | stl.h:520:42:520:57 | insert_or_assign | 1 | func:0 && |
| stl.h:522:30:522:45 | insert_or_assign | 0 | const_iterator | | stl.h:522:30:522:45 | insert_or_assign | 0 | const_iterator |
@@ -567,6 +684,12 @@ getParameterTypeName
| stl.h:557:33:557:35 | set | 0 | func:0 | | stl.h:557:33:557:35 | set | 0 | func:0 |
| stl.h:557:33:557:35 | set | 1 | func:0 | | stl.h:557:33:557:35 | set | 1 | func:0 |
| stl.h:560:8:560:16 | operator= | 0 | const set & | | stl.h:560:8:560:16 | operator= | 0 | const set & |
| stl.h:568:48:568:54 | emplace | 0 | func:0 && |
| stl.h:568:48:568:54 | emplace | 0 | func:0 && |
| stl.h:569:36:569:47 | emplace_hint | 0 | const_iterator |
| stl.h:569:36:569:47 | emplace_hint | 0 | const_iterator |
| stl.h:569:36:569:47 | emplace_hint | 1 | func:0 && |
| stl.h:569:36:569:47 | emplace_hint | 1 | func:0 && |
| stl.h:571:23:571:28 | insert | 0 | value_type && | | stl.h:571:23:571:28 | insert | 0 | value_type && |
| stl.h:573:12:573:17 | insert | 0 | const_iterator | | stl.h:573:12:573:17 | insert | 0 | const_iterator |
| stl.h:573:12:573:17 | insert | 1 | value_type && | | stl.h:573:12:573:17 | insert | 1 | value_type && |
@@ -584,6 +707,12 @@ getParameterTypeName
| stl.h:611:33:611:45 | unordered_set | 1 | func:0 | | stl.h:611:33:611:45 | unordered_set | 1 | func:0 |
| stl.h:611:33:611:45 | unordered_set | 2 | size_type | | stl.h:611:33:611:45 | unordered_set | 2 | size_type |
| stl.h:614:18:614:26 | operator= | 0 | const unordered_set & | | stl.h:614:18:614:26 | operator= | 0 | const unordered_set & |
| stl.h:622:48:622:54 | emplace | 0 | func:0 && |
| stl.h:622:48:622:54 | emplace | 0 | func:0 && |
| stl.h:623:36:623:47 | emplace_hint | 0 | const_iterator |
| stl.h:623:36:623:47 | emplace_hint | 0 | const_iterator |
| stl.h:623:36:623:47 | emplace_hint | 1 | func:0 && |
| stl.h:623:36:623:47 | emplace_hint | 1 | func:0 && |
| stl.h:625:24:625:29 | insert | 0 | value_type && | | stl.h:625:24:625:29 | insert | 0 | value_type && |
| stl.h:627:12:627:17 | insert | 0 | const_iterator | | stl.h:627:12:627:17 | insert | 0 | const_iterator |
| stl.h:627:12:627:17 | insert | 1 | value_type && | | stl.h:627:12:627:17 | insert | 1 | value_type && |
@@ -594,3 +723,18 @@ getParameterTypeName
| stl.h:636:37:636:41 | merge | 0 | unordered_set & | | stl.h:636:37:636:41 | merge | 0 | unordered_set & |
| stl.h:639:12:639:15 | find | 0 | const key_type & | | stl.h:639:12:639:15 | find | 0 | const key_type & |
| stl.h:641:28:641:38 | equal_range | 0 | const key_type & | | stl.h:641:28:641:38 | equal_range | 0 | const key_type & |
| stl.h:671:21:671:39 | basic_format_string | 0 | const func:0 & |
| stl.h:671:21:671:39 | basic_format_string | 0 | const func:0 & |
| stl.h:678:33:678:38 | format | 0 | format_string |
| stl.h:678:33:678:38 | format | 0 | format_string |
| stl.h:678:33:678:38 | format | 1 | func:0 && |
| stl.h:678:33:678:38 | format | 1 | func:0 && |
| stringstream.cpp:18:6:18:9 | sink | 0 | const basic_ostream> & |
| stringstream.cpp:21:6:21:9 | sink | 0 | const basic_istream> & |
| stringstream.cpp:24:6:24:9 | sink | 0 | const basic_iostream> & |
| swap1.cpp:14:9:14:9 | move | 0 | func:0 & |
| swap2.cpp:14:9:14:9 | move | 0 | func:0 & |
| swap.h:4:20:4:23 | swap | 0 | func:0 & |
| swap.h:4:20:4:23 | swap | 1 | func:0 & |
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |

View File

@@ -62,3 +62,9 @@ Virtual getAVirtual();
void test9() { void test9() {
typeid(getAVirtual()); // unevaluated typeid(getAVirtual()); // unevaluated
} }
void constExprIf() {
if constexpr(sizeof(int) == 4) { } // unevaluated
}
// semmle-extractor-options: -std=c++20

View File

@@ -14,3 +14,7 @@
| test.cpp:57:9:57:9 | 4 | | test.cpp:57:9:57:9 | 4 |
| test.cpp:63:9:63:19 | call to getAVirtual | | test.cpp:63:9:63:19 | call to getAVirtual |
| test.cpp:63:9:63:21 | temporary object | | test.cpp:63:9:63:21 | temporary object |
| test.cpp:67:16:67:26 | sizeof(int) |
| test.cpp:67:16:67:31 | ... == ... |
| test.cpp:67:31:67:31 | 4 |
| test.cpp:67:31:67:31 | (unsigned long)... |

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 unexpectedOperand
duplicateOperand duplicateOperand
missingPhiOperand 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 missingOperandType
duplicateChiOperand duplicateChiOperand
sideEffectWithoutPrimary sideEffectWithoutPrimary

View File

@@ -2,7 +2,6 @@ missingOperand
unexpectedOperand unexpectedOperand
duplicateOperand duplicateOperand
missingPhiOperand 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 missingOperandType
duplicateChiOperand duplicateChiOperand
sideEffectWithoutPrimary 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; } 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 } // 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,81 @@
| Class | specifiers2pp.cpp:8:7:8:13 | MyClass | MyClass | abstract | | Class | specifiers2pp.cpp:8:7:8:13 | MyClass | MyClass | abstract |
| Class | specifiers2pp.cpp:24:7:24:14 | MyClass2 | MyClass2 | 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, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern | | Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline | | Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr, inline, is_constexpr, private |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline | | Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr | | Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr | | Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public | | Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public | | Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr | | Function | cpp20.cpp:11:14:11:24 | TestExplict | TestExplict | explicit, extern, public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | inline | | Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | explicit, extern, public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | is_constexpr | | Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | private | | Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const | | Function | cpp20.cpp:24:1:24:16 | TestExplicitBool | TestExplicitBool | has_trailing_return_type |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | declared_constexpr | | Function | cpp20.cpp:40:1:40:39 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | inline | | Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | explicit, public |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | is_constexpr | | Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | private | | Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
| Function | specifiers2.c:11:6:11:6 | f | f | c_linkage | | Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | explicit, public |
| Function | specifiers2.c:11:6:11:6 | f | f | extern | | Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | public |
| Function | specifiers2.c:12:13:12:13 | f | f | c_linkage | | Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | explicit, extern, public |
| Function | specifiers2.c:12:13:12:13 | f | f | extern | | Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | extern, public |
| Function | specifiers2.c:13:13:13:13 | f | f | c_linkage | | Function | cpp20.cpp:55:1:55:39 | TestExplicitBool3 | TestExplicitBool3 | public |
| Function | specifiers2.c:13:13:13:13 | f | f | extern | | Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
| Function | specifiers2.c:15:13:15:13 | g | g | c_linkage | | Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
| Function | specifiers2.c:15:13:15:13 | g | g | extern | | Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2.c:16:13:16:13 | g | g | c_linkage | | Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2.c:16:13:16:13 | g | g | extern | | Function | cpp20.cpp:64:5:64:21 | TestExplicitBool4 | TestExplicitBool4 | explicit, extern, public |
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage | | Function | file://:0:0:0:0 | TestExplicitBool | TestExplicitBool | explicit, has_trailing_return_type |
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | extern | | Function | file://:0:0:0:0 | operator delete | operator delete | extern |
| Function | specifiers2.c:25:12:25:14 | add | add | c_linkage | | Function | file://:0:0:0:0 | operator new | operator new | extern |
| Function | specifiers2.c:25:12:25:14 | add | add | inline | | Function | specifiers2.c:11:6:11:6 | f | f | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern | | Function | specifiers2.c:12:13:12:13 | f | f | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern | | Function | specifiers2.c:13:13:13:13 | f | f | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline | | Function | specifiers2.c:15:13:15:13 | g | g | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline | | Function | specifiers2.c:16:13:16:13 | g | g | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr | | Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage, extern |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr | | Function | specifiers2.c:25:12:25:14 | add | add | c_linkage, inline |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | public | | Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | 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 | | Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern | | Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline | | Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit, extern, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline | | Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline, public |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public | | Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual, extern, public, pure, virtual |
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public | | Function | specifiers2pp.cpp:14:21:14:21 | f | f | declared_virtual, extern, public, virtual |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit | | Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | inline, private |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | extern | | Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | inline, protected |
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | public | | Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline | | Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | public | | Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual | | Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | extern | | Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | public | | Function | specifiers2pp.cpp:26:21:26:21 | f | f | declared_virtual, extern, override, public, virtual |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | pure | | Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | virtual | | Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
| 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 | specifiers2pp.cpp:33:5:33:18 | fun | fun | 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, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern | | Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern, inline, is_constexpr, public |
| 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:40:12:40:18 | someFun | someFun | extern | | 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 | c_linkage, extern |
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | extern | | Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage, extern |
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage | | Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage, static |
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | extern | | Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage | | Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | static | | Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern | | Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern | | FunctionDeclarationEntry | cpp20.cpp:11:14:11:24 | declaration of TestExplict | TestExplict | explicit |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline | | FunctionDeclarationEntry | cpp20.cpp:40:23:40:23 | definition of TestExplicitBool2 | TestExplicitBool2 | explicit |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline | | FunctionDeclarationEntry | cpp20.cpp:51:5:51:5 | definition of TestExplicitBool3 | TestExplicitBool3 | explicit |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr | | FunctionDeclarationEntry | cpp20.cpp:51:5:51:21 | declaration of TestExplicitBool3 | TestExplicitBool3 | explicit |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr | | FunctionDeclarationEntry | cpp20.cpp:64:5:64:21 | declaration of TestExplicitBool4 | TestExplicitBool4 | explicit |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public | | FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | c_linkage, void_param_list |
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public | | FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | c_linkage, extern, void_param_list |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const | | FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | c_linkage, extern, void_param_list |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | declared_constexpr | | FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | c_linkage, extern, void_param_list |
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | inline | | FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | c_linkage, extern, void_param_list |
| 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 |
| FunctionDeclarationEntry | specifiers2.c:21:6:21:12 | declaration of somefun | somefun | c_linkage | | 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 | 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 | | FunctionDeclarationEntry | specifiers2pp.cpp:2:6:2:9 | definition of afun | afun | void_param_list |
@@ -154,28 +89,19 @@
| FunctionDeclarationEntry | specifiers2pp.cpp:31:13:31:15 | declaration of fun | fun | void_param_list | | 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: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: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 | c_linkage, extern |
| 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, extern |
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | c_linkage | | FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | c_linkage, static |
| 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 |
| TypedefType | file://:0:0:0:0 | Const | Const | const | | TypedefType | file://:0:0:0:0 | Const | Const | const |
| TypedefType | specifiers2.c:27:19:27:26 | constInt | constInt | 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: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 | const, volatile |
| 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, volatile |
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | const | | TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | const, volatile |
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | volatile | | TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | const, restrict, 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:56:28:56:32 | Const | Const | const | | 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: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 | const, volatile |
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | volatile |
| Variable | specifiers2.c:8:12:8:12 | j | j | extern | | Variable | specifiers2.c:8:12:8:12 | j | j | extern |
| Variable | specifiers2.c:9:12:9:12 | j | j | extern | | Variable | specifiers2.c:9:12:9:12 | j | j | extern |
| Variable | specifiers2.c:18:21:18:23 | svi | svi | static | | 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" e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry"
} }
from Element e, string name, string specifier from Element e, string name, string specifiers
where where
( (
name = e.(Declaration).getName() or name = e.(Declaration).getName() or
name = e.(DeclarationEntry).getName() or name = e.(DeclarationEntry).getName() or
name = e.(Type).toString() name = e.(Type).toString()
) and ) and
( specifiers =
specifier = e.(Declaration).getASpecifier().toString() or concat(string s |
specifier = e.(DeclarationEntry).getASpecifier() or s = e.(Declaration).getASpecifier().toString() or
specifier = e.(TypedefType).getBaseType().getASpecifier().toString() s = e.(DeclarationEntry).getASpecifier() or
) s = e.(TypedefType).getBaseType().getASpecifier().toString()
select interesting(e), e, name, specifier |
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: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: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 | | 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:128:15:128:16 | v4 |
| test.cpp:185:10:185:12 | cpy | | test.cpp:185:10:185:12 | cpy |
| test.cpp:199:10:199:12 | cpy | | test.cpp:199:10:199:12 | cpy |
| test.cpp:208:7:208:7 | a | | test.cpp:213:7:213:7 | a |
| test.cpp:214:7:214: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:11:10:11:10 | a |
| test_free.cpp:14:10:14:10 | a | | test_free.cpp:14:10:14:10 | a |
| test_free.cpp:16:10:16:10 | a | | test_free.cpp:16:10:16:10 | a |
@@ -117,6 +120,12 @@
| test_free.cpp:346:26:346:28 | ptr | | test_free.cpp:346:26:346:28 | ptr |
| test_free.cpp:356:19:356:19 | a | | test_free.cpp:356:19:356:19 | a |
| test_free.cpp:357:19:357:19 | a | | test_free.cpp:357:19:357:19 | a |
| test_free.cpp:370:10:370:10 | a |
| test_free.cpp:373:10:373:10 | e |
| test_free.cpp:382:10:382:10 | i |
| test_free.cpp:383:10:383:10 | s |
| test_free.cpp:395:14:395:19 | buffer |
| test_free.cpp:424:10:424:16 | buffer2 |
| virtual.cpp:18:10:18:10 | a | | virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c | | virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b | | virtual.cpp:38:10:38:10 | b |

View File

@@ -14,3 +14,5 @@
| test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. | | test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. |
| test_free.cpp:253:14:253:19 | call to malloc | This memory is never freed. | | test_free.cpp:253:14:253:19 | call to malloc | This memory is never freed. |
| test_free.cpp:261:6:261:12 | new | This memory is never freed. | | test_free.cpp:261:6:261:12 | new | This memory is never freed. |
| test_free.cpp:365:21:365:26 | call to malloc | This memory is never freed. |
| test_free.cpp:368:31:368:36 | call to malloc | This memory is never freed. |

View File

@@ -1,6 +1,9 @@
edges edges
| test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | provenance | | | test.cpp:213:7:213:7 | pointer to free output argument | test.cpp:214:2:214:2 | a | provenance | |
| test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215: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: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: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 | | | 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: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 | | | test_free.cpp:331:12:331:12 | pointer to operator delete output argument | test_free.cpp:332:5:332:6 | * ... | provenance | |
nodes nodes
| test.cpp:208:7:208:7 | pointer to free output argument | semmle.label | pointer to free output argument | | test.cpp:213:7:213: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:2:214: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:219:7:219: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: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: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:12:5:12:5 | a | semmle.label | a |
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... | | test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
@@ -88,8 +95,9 @@ nodes
| test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... | | test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... |
subpaths subpaths
#select #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: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: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: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: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: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 | | 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() { void test_reassignment() {
char *a = (char *)malloc(128); char *a = (char *)malloc(128);
char *b = (char *)malloc(128); char *b = (char *)malloc(128);
@@ -213,4 +218,21 @@ void test_reassignment() {
free(a); free(a);
a[0] = 0; // BAD 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

@@ -356,3 +356,73 @@ void test(E* e) {
free(e->ec[0].a); free(e->ec[0].a);
free(e->ec[1].a); // GOOD free(e->ec[1].a); // GOOD
} }
// ---
void test_return_by_parameter(int **out_i, MyStruct **out_ms) {
int *a = (int *)malloc(sizeof(int)); // GOOD (freed)
int *b = (int *)malloc(sizeof(int)); // GOOD (out parameter)
int *d = (int *)malloc(sizeof(int)); // BAD (not freed)
MyStruct *e = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD (freed)
MyStruct *f = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD (out parameter)
MyStruct *h = (MyStruct *)malloc(sizeof(MyStruct)); // BAD (not freed)
free(a);
*out_i = b;
free(e);
*out_ms = f;
}
void test_return_by_parameter_caller() {
int *i;
MyStruct *s;
test_return_by_parameter(&i, &s);
free(i);
free(s);
}
// ---
class HasGetterAndFree {
public:
HasGetterAndFree() {
buffer = malloc(1024);
}
~HasGetterAndFree() {
free(buffer);
}
void *getBuffer() {
return buffer;
}
void *buffer;
};
class HasGetterNoFree {
public:
HasGetterNoFree() {
buffer = malloc(1024);
}
void *getBuffer() {
return buffer;
}
void *buffer;
};
void testHasGetter() {
HasGetterAndFree hg;
void *buffer = hg.getBuffer(); // GOOD (freed in destructor)
HasGetterNoFree hg2;
void *buffer2 = hg2.getBuffer(); // GOOD (freed below)
free(buffer2);
HasGetterNoFree hg3;
void *buffer3 = hg3.getBuffer(); // BAD (not freed) [NOT DETECTED]
}

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: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: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: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 nodes
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument | | test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:35:7:35:7 | i | semmle.label | i | | 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:460:6:460:10 | value | semmle.label | value |
| test.cpp:467:20:467:25 | scanf output argument | semmle.label | scanf output argument | | 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: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 subpaths
#select #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 | | 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: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: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: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

@@ -473,3 +473,83 @@ void check_for_negative_test() {
} }
use(value); 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;
}
}

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