Compare commits

...

400 Commits

Author SHA1 Message Date
Andrew Eisenberg
0e53ad33f6 Actions: Add permissions block to code scanning workflow 2021-04-26 10:53:29 -07:00
Andrew Eisenberg
3670c729c0 Actions: Use the main branch of the codeql action
This commit switches to the bleeding edge, main branch of the
codeql action. This helps us test the action before merging all
of the new changes into main, which occurs roughly once a week.

If there are commits that introduce bugs in codeql-action, then
we will be more likely to catch it before releasing to the world
if we are using it in this extension.
2021-04-26 08:43:28 -07:00
Shati Patel
a09c12acfe Merge pull request #5537 from alexet/ambig-super
Docs: Update the language specification for changes to super.
2021-04-26 13:34:50 +01:00
Tamás Vajk
a7030c7fed Merge pull request #5308 from tamasvajk/feature/flow-sources-sinks
C#: Add Console.Read* to local flow sources
2021-04-23 16:36:16 +02:00
Tamás Vajk
c3058f4744 Merge pull request #5749 from tamasvajk/feature/fix-fromsource
C#: Adjust 'fromSource' to hold only on files passed to the compiler as a source file
2021-04-23 16:35:40 +02:00
Shati Patel
6f2103f312 Merge pull request #5722 from github/tamasvajk-patch-1
C#: Add Dapper to supported frameworks
2021-04-23 14:32:22 +01:00
Jonas Jensen
9b5bb95766 Merge pull request #5696 from jbj/reapply-inconsistency-workaround
Revert "Revert "C++: Work around extractor issue CPP-383""
2021-04-23 14:49:32 +02:00
Anders Schack-Mulligen
bc8c55836a Merge pull request #5743 from aschackmull/java/flow-summary-tweaks
Java/C#: Move a couple of flow summary tweaks to the shared implementation.
2021-04-23 13:46:04 +02:00
Tamas Vajk
1b4c3c7415 Fix code review findings 2021-04-23 13:44:34 +02:00
Tamás Vajk
819be43ce7 Fix alphabetical order of supported frameworks 2021-04-23 13:41:59 +02:00
Tamás Vajk
43dc9bbc94 Merge pull request #5744 from tamasvajk/feature/java-loc
Java: Introduce LoC summary metric query
2021-04-23 11:39:42 +02:00
Jonas Jensen
6de5b3021e C++: Replace Jira ticket reference with GH issue 2021-04-23 09:58:39 +02:00
Jonas Jensen
6e059ea002 C++: Remove reference to obsolete issue CPP-383 2021-04-23 09:58:15 +02:00
Shati Patel
96a4d91a6c Merge pull request #5731 from shati-patel/docs/unbind-pragmas
Docs: New "directional binding" pragmas
2021-04-23 08:37:02 +01:00
CodeQL CI
635fb4c25a Merge pull request #5685 from erik-krogh/markdownIt
Approved by asgerf
2021-04-22 14:55:31 -07:00
Taus
3e4ff9e472 Merge pull request #5742 from RasmusWL/django-3.2
Python: Add support for new features in Django 3.2
2021-04-22 17:39:02 +02:00
CodeQL CI
bdb41423e2 Merge pull request #5748 from asgerf/js/rate-limiting-fixes
Approved by erik-krogh
2021-04-22 05:56:50 -07:00
Tamas Vajk
ed42c878b0 Adjust 'fromSource' to hold only on '.cs' files 2021-04-22 14:17:16 +02:00
Tamas Vajk
b36d35bf1e Revert "C#: Adjust 'fromSource' to hold only on files passed to the compiler as a source file"
This reverts commit 1dab1590ea.
2021-04-22 14:16:10 +02:00
Mathias Vorreiter Pedersen
2b8afe55e8 Merge pull request #5747 from rdmarsh2/rdmarsh2/cpp/deprecate-return-stack-allocated-object
C++: deprecate cpp/return-stack-allocated-object
2021-04-22 11:37:07 +02:00
Owen Mansel-Chan
fea9f5f431 Merge pull request #5746 from owen-mc/java/refactor-exec-tainted
Make ExecTainted easier to extend
2021-04-22 10:14:28 +01:00
Tamas Vajk
a8a920c8f0 Add change note 2021-04-22 11:01:12 +02:00
Owen Mansel-Chan
8a01799fb8 Make imports private
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-04-22 09:46:49 +01:00
Owen Mansel-Chan
4b8d4f5bbd Update docs 2021-04-22 09:30:50 +01:00
Owen Mansel-Chan
e448dcb725 Avoid bad join order
We want to avoid joining on `i` first.
2021-04-22 09:30:49 +01:00
Owen Mansel-Chan
9f1704560b Include constructors in abstract class 2021-04-22 09:30:48 +01:00
Tamas Vajk
1dab1590ea C#: Adjust 'fromSource' to hold only on files passed to the compiler as a source file 2021-04-22 10:21:28 +02:00
Tamás Vajk
9c936867fa Exclude code from XML files
Co-authored-by: yo-h <55373593+yo-h@users.noreply.github.com>
2021-04-22 09:00:31 +02:00
Tamás Vajk
a7cc9f98ef Merge pull request #5745 from tamasvajk/feature/fix-arg-default
C#: Fix special case of default argument value extraction
2021-04-22 08:58:13 +02:00
Robert Marsh
cac1bef6ea C++: deprecate cpp/return-stack-allocated-object 2021-04-21 15:17:31 -07:00
Asger Feldthaus
fe8deeaf6b JS: Autoformat 2021-04-21 23:13:57 +01:00
Asger Feldthaus
e98bfe921e JS: QLDoc 2021-04-21 22:14:50 +01:00
Asger Feldthaus
bb7934b381 JS: Change note 2021-04-21 21:20:12 +01:00
Asger Feldthaus
c113cfd8b7 JS: Autoformat 2021-04-21 21:13:07 +01:00
Rasmus Wriedt Larsen
5a9e27c6fc Merge branch 'main' into django-3.2 2021-04-21 17:15:47 +02:00
Chris Smowton
94f0a1532d Merge pull request #5682 from smowton/smowton/docs/fix-has-modifier-comment
Fix documentation of Modifier.qll
2021-04-21 15:41:29 +01:00
Tamas Vajk
a0f5e45ae9 C#: Fix special case of default argument value extraction 2021-04-21 16:34:29 +02:00
Geoffrey White
ba335089c4 Merge pull request #5601 from ihsinme/ihsinme-patch-259
CPP: Add query for CWE-691 Insufficient Control Flow Management After Refactoring The Code
2021-04-21 15:13:38 +01:00
Owen Mansel-Chan
9c72e73a82 Make ExecTainted easier to extend
To add a method that executes a command, you can now define a class
extending ExecMethod.
2021-04-21 14:55:37 +01:00
CodeQL CI
30d7f0dc98 Merge pull request #5687 from RasmusWL/inline-taint-tests
Approved by yoff
2021-04-21 06:24:12 -07:00
Asger Feldthaus
2c9a6e7bef JS: Cache function-wrapping steps in type-tracking stage 2021-04-21 13:45:58 +01:00
Tamas Vajk
e25305e3cc Java: Introduce LoC summary metric query 2021-04-21 14:27:00 +02:00
Anders Schack-Mulligen
f9599da32d Java/C#: Move a couple of flow summary tweaks to the shared implementation. 2021-04-21 14:24:15 +02:00
Rasmus Wriedt Larsen
be9cbd79d6 Python: Add change-note for Django 3.2 support 2021-04-21 13:58:34 +02:00
Rasmus Wriedt Larsen
59c6f76457 Python: Add test for new response.headers in Django
See https://docs.djangoproject.com/en/3.2/ref/request-response/#setting-header-fields
2021-04-21 13:55:22 +02:00
Rasmus Wriedt Larsen
2302c8d5fa Python: Model new alias method on django QuerySets 2021-04-21 13:52:38 +02:00
yoff
a19373ab54 Merge pull request #5727 from tausbn/python-use-localsource-in-stepsummary
Python: Use `LocalSourceNode` in `StepSummary::step`
2021-04-21 13:50:31 +02:00
Tamás Vajk
205469316c Merge pull request #5738 from tamasvajk/feature/loc
C# Add line of code metric query
2021-04-21 13:49:32 +02:00
Tamas Vajk
2a6f979ce6 C# Add line of code metric query 2021-04-21 10:42:06 +02:00
Anders Schack-Mulligen
9362ae0687 Merge pull request #5422 from tamasvajk/feature/sink-migration-ldap
Java: Migrate LDAP injection sinks to CSV format
2021-04-21 10:05:28 +02:00
Rasmus Wriedt Larsen
63a2657aef Merge branch 'main' into inline-taint-tests 2021-04-21 10:02:55 +02:00
Tom Hvitved
7080b256fb Merge pull request #5715 from hvitved/csharp/ssa/perf-tweaks
C#: A few minor SSA performance tweaks
2021-04-21 09:59:12 +02:00
Tom Hvitved
def62e8c22 Merge pull request #5718 from hvitved/csharp/hardcoded-cred-remove-cp
C#: Remove CP from `HardcodedCredentials::getCredentialSink`
2021-04-21 09:58:56 +02:00
Tom Hvitved
1ed11b297b Merge pull request #5725 from hvitved/csharp/dataflow/performance
C#: Various data-flow performance tweaks
2021-04-21 09:46:15 +02:00
yoff
ef0ea247c4 Merge pull request #5679 from tausbn/python-fix-bad-points-to-joins
Python: Fix bad points-to joins
2021-04-20 21:19:32 +02:00
Tom Hvitved
3eba5b0aac Merge pull request #5676 from hvitved/csharp/dispatch/get-a-viable-overrider-perf
C#: Speedup `DispatchMethodOrAccessorCall::getAViableOverrider()`
2021-04-20 19:57:59 +02:00
Erik Krogh Kristensen
357e1c0802 Update javascript/ql/src/semmle/javascript/frameworks/Markdown.qll
Co-authored-by: Asger F <asgerf@github.com>
2021-04-20 19:57:47 +02:00
yo-h
00137f2905 Merge pull request #5721 from github/yo-h/java-diagnostic-queries
Java: add extractor `diagnostic` queries
2021-04-20 13:36:49 -04:00
Shati Patel
98a0959784 Docs: New "directional binding" pragmas 2021-04-20 18:12:35 +01:00
Taus
890f96d9b5 Python: Prevent bad joins in TypeBackTracker
Perhaps unsurprisingly, the join orderer was eager and willing to find
the wrong join order in this predicate as well. Applying a similar
fix to the one used in `TypeTracker::step` fixes the problem.
2021-04-20 15:01:04 +00:00
Taus
c0569da65c Python: Move track/backtrack to LocalSourceNode
This is merely making explicit what was implicitly enforced. The move
to change the return type of `step` already meant that `this` and
`result` had to be `LocalSourceNode`. By moving these methods to their
rightful place, we should hopefully avoid a bit of suprising behaviour.
2021-04-20 14:39:56 +00:00
Taus
2a07441c19 Python: ModuleVariableNodes are not API uses
This caused some suprising test changes, where suddenly we had flow from
a `ModuleVariableNode` (as a `RemoteFlowSource`) to a sink. This of
course makes little sense, so instead we simply exclude these nodes as
uses in the first place.
2021-04-20 14:33:42 +00:00
Taus
7581cbade6 Python: Fix forgotten type tracker
This was the last remaining type tracker that did not use
`LocalSourceNode`.
2021-04-20 14:32:56 +00:00
Tamas Vajk
583513bafd Fix review findings 2021-04-20 16:28:47 +02:00
Asger Feldthaus
43ca8ea5f7 JS: Fix perf issue in forwardsParameter 2021-04-20 15:15:12 +01:00
Chris Smowton
a5cfdd2cfe Merge pull request #5467 from p0wn4j/groovy-execute
[Java] CWE-094: Query to detect Groovy Code Injections
2021-04-20 14:49:56 +01:00
Erik Krogh Kristensen
62dfd1fa7d improve the markdown-it model 2021-04-20 15:23:03 +02:00
Taus
38548c9acd Python: Simplify charpred for LocalSourceNode
The somewhat convoluted `comes_from_cfgnode` was originally introduced
in order to have local sources for instances of global variables. This
was needed because global variables have an implicit "scope entry" SSA
definition that flows to the first actual use of the variable (and so
would not fit the strict "has no incoming flow" definition of a local
source node).

However, a subsequent change means that we include all global variable
reads anyway, and so the old definition is no longer needed.

(See commit 3fafb47b16 for further
context.)
2021-04-20 13:19:36 +00:00
Taus
038bf612be Python: Add change note 2021-04-20 13:06:30 +00:00
Jonas Jensen
f02c86cb22 Merge pull request #5726 from MathiasVP/fix-false-positive-in-return-stack-allocated-memory-2
C++: Fix false positive in return stack allocated memory (second attempt)
2021-04-20 15:05:11 +02:00
Taus
a55b43b67e Python: Use LocalSourceNode throughout step
This commit does a lot of stuff all at once, so here are the main
highlights:

In `TypeTracker.qll`, we change `StepSummary::step` to step only between
source nodes. Because reads and writes of global variables happen in two
different (jump) steps, this requires the intermediate
`ModuleVariableNode` to _also_ be a `LocalSourceNode`, and we therefore
modify the charpred for that class accordingly. (This also means
changing a few of the tests to account for these new source nodes.)

In addition, we change `TypeTracker::step` to likewise step between
local source nodes.

Next, to enable the use of the `track` convenience method on nodes, we
add some pragmas to `TypeTracker::step` that prevent bad joins from
occurring. With this, we can eliminate all of the manual type tracker
join predicates.

Next, we observe that because `StepSummary::step` now uses `flowsTo`, it
automatically encapsulates all local-flow steps. In particular this
means we do not have to use `typePreservingStep` in `smallstep`, but can
use `jumpStep` directly. A similar observation applies to
`TypeTracker::smallstep`.

Having done this, we no longer need `typePreservingStep`, so we get rid
of it.
2021-04-20 12:59:33 +00:00
Taus
31bd701bd5 Python: Final LocalSourceNode fixes 2021-04-20 12:59:33 +00:00
Chris Smowton
9bfb0d93ca Autoformat QL 2021-04-20 13:59:09 +01:00
Rasmus Wriedt Larsen
897105de02 Merge pull request #5717 from tausbn/python-use-api-graphs-in-django
Python: Use API graphs in Django model
2021-04-20 14:57:55 +02:00
Erik Krogh Kristensen
19c5889775 use mayHaveBooleanValue 2021-04-20 14:39:54 +02:00
Erik Krogh Kristensen
13d915927b add change note 2021-04-20 14:39:54 +02:00
Erik Krogh Kristensen
7046f1a902 add taint-step for markdown-it when the HTML flag is set 2021-04-20 14:39:54 +02:00
Taus
76700d17d6 Merge pull request #5684 from RasmusWL/flask-more-taint-tests
Python: Add taint tests for .get() in flask
2021-04-20 14:08:08 +02:00
Asger Feldthaus
f8d428cb2d JS: Use function-forwarding steps when tracking rate limiters 2021-04-20 13:00:42 +01:00
Mathias Vorreiter Pedersen
93e55e2631 C++: Fix FP in cpp/return-stack-allocated-memory. 2021-04-20 13:58:12 +02:00
Mathias Vorreiter Pedersen
1797b6c7f9 C++: Add FP test from the work on smart pointers in dataflow. 2021-04-20 13:54:57 +02:00
Asger Feldthaus
581f4ed757 JS: Generalize handling of route handler wrapper functions 2021-04-20 12:46:40 +01:00
Chris Smowton
0ec3ee29e4 Style last use of SecureASTCustomizer 2021-04-20 12:44:49 +01:00
Hayk Andriasyan
bb58a50503 Update GroovyInjection.qhelp 2021-04-20 15:41:58 +04:00
p0wn4j
f2de440886 [Java] CWE-094: Query to detect Groovy Code Injections 2021-04-20 19:18:24 +04:00
Jonas Jensen
d4fdd50e2c Merge pull request #5723 from MathiasVP/cleanup-smart-ptr-model
C++: Simplify smart pointer model
2021-04-20 13:25:02 +02:00
Tom Hvitved
dd1bb18938 C#: Various data-flow performance tweaks
- Cache `DataFlowCall::getEnclosingCallable()`.
- Cache `ParameterNode`.
- Cache `ArgumentNode`.
- Force proper join-orders for uses of `getNodeType()`.
- Inline `localFlow` to prevent calculating full TC.
2021-04-20 11:56:25 +02:00
Tom Hvitved
1f9239089f Merge pull request #5695 from hvitved/csharp/dispose-not-called-on-exc-perf
C#: Improve performance of `DisposeNotCalledOnException.ql`
2021-04-20 11:52:18 +02:00
Tom Hvitved
b2a7a3ed30 Merge pull request #5674 from hvitved/csharp/ssa/call-graph-perf
C#: Improve performance of `SsaImpl::CallGraph::SimpleDelegateAnalysis`
2021-04-20 11:51:52 +02:00
Geoffrey White
2b7e599dc4 Merge pull request #5703 from MathiasVP/improve-access-of-memory-location-after-end-of-buffer-using-strncat
C++: Improve cpp/access-memory-location-after-end-buffer-strncat
2021-04-20 10:44:24 +01:00
Mathias Vorreiter Pedersen
61d4d17225 C++: Simplify smart pointer model and accept test changes. 2021-04-20 09:57:58 +02:00
Tamás Vajk
408954e4d8 C#: Add Dapper to supported frameworks 2021-04-20 09:30:47 +02:00
yo-h
87cd72496c Java: add extractor diagnostic queries 2021-04-19 15:34:16 -04:00
yo-h
cb524b6c19 Merge pull request #5611 from github/yo-h/java16
Java: adjust test `options` for JDK 16 upgrade
2021-04-19 15:12:23 -04:00
Taus
bc6685aa3f Python: Fix typo
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-04-19 19:57:35 +02:00
Anders Schack-Mulligen
5458c02cc2 Merge pull request #5456 from aschackmull/java/adopt-flow-summary
Java: Use shared flow summary library for CSV models.
2021-04-19 16:21:10 +02:00
Anders Schack-Mulligen
33db0c13cd Merge pull request #5689 from github/aeisenberg/rework-staleness
Actions: Change staleness calculation
2021-04-19 15:57:41 +02:00
Tom Hvitved
9128ec72ad C#: A few minor SSA performance tweaks 2021-04-19 15:51:14 +02:00
Anders Schack-Mulligen
80eb0a2df6 Apply suggestions from code review
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-19 15:45:58 +02:00
CodeQL CI
437bba1e3c Merge pull request #5716 from erik-krogh/vscodeRegress
Approved by esbena
2021-04-19 06:30:02 -07:00
Tom Hvitved
15e4b7f95d C#: Remove CP from HardcodedCredentials::getCredentialSink 2021-04-19 15:03:11 +02:00
Rasmus Wriedt Larsen
d607c13ab6 Python: Taint tests: include elment for forgotten MISSING 2021-04-19 15:01:42 +02:00
Rasmus Wriedt Larsen
9585390941 Python: Taint tests, report error location first
To better match the standard output from inline expectation tests
2021-04-19 14:59:47 +02:00
Rasmus Wriedt Larsen
b2cb284ff2 Python: Add more examples of what is ok with new taint tests 2021-04-19 14:56:20 +02:00
Anders Schack-Mulligen
7d84cfacef Java: Add MapKeyContent and MapValueContent. 2021-04-19 14:06:27 +02:00
Anders Schack-Mulligen
39862740e0 Java: Convert support for fluent interfaces. 2021-04-19 14:06:27 +02:00
Anders Schack-Mulligen
579c955892 Java: Adjust some tests. 2021-04-19 14:06:27 +02:00
Anders Schack-Mulligen
175c71221a Java: Adjust some test output with more edges/nodes. 2021-04-19 14:06:27 +02:00
Anders Schack-Mulligen
60965b0d8c Java: Adjust some csv models. 2021-04-19 14:02:19 +02:00
Anders Schack-Mulligen
a27dac029f Java: Use shared flow summary library for csv models. 2021-04-19 14:02:19 +02:00
Chris Smowton
36abf8733e Merge pull request #5714 from aschackmull/java/add-misc-qltests
Java: Add a few qltests
2021-04-19 13:00:10 +01:00
Taus
9acc71a7cb Python: Get rid of all _attr methods in Django.qll 2021-04-19 11:54:10 +00:00
Erik Krogh Kristensen
9e6f28e335 fix bad join order in Xss.qll 2021-04-19 13:17:49 +02:00
Anders Schack-Mulligen
29aec0d770 Java: Adjust expected output. 2021-04-19 13:16:46 +02:00
Anders Schack-Mulligen
c5193cf03f Apply suggestions from code review 2021-04-19 13:14:56 +02:00
Anders Schack-Mulligen
06514159be Java: Add XXE tests. 2021-04-19 10:58:21 +02:00
Anders Schack-Mulligen
daad62c4e0 Java: Add TaintedPath test. 2021-04-19 10:07:03 +02:00
Jonas Jensen
1ab75eb6f4 Merge pull request #5708 from github/fix-id-in-JsonpInjection-1
Java: Fix id in experimental JsonpInjection.ql query
2021-04-19 08:23:34 +02:00
yoff
118840dad4 Merge pull request #5690 from tausbn/python-disallow-post-update-nodes-as-local-source-nodes
Python: Disallow `PostUpdateNode` as `LocalSourceNode`
2021-04-19 06:56:11 +02:00
ihsinme
c2d97b98e2 Merge branch 'main' into ihsinme-patch-259 2021-04-18 21:01:56 +03:00
Mathias Vorreiter Pedersen
e36b42a03f Java: Fix invalid id in experimental query
The invalid id broke CI here: https://github.com/github/codeql/pull/5703 (see https://github.slack.com/archives/CPSEA0G22/p1618602834224600)
2021-04-17 09:47:15 +02:00
Taus
f3661c34ee Python: Clean up Django models using API graphs
First sweep. Takes care of most of the models.
2021-04-16 19:53:36 +00:00
Mathias Vorreiter Pedersen
95742aec69 C++: Accept test changes for the other experimental query in the directory. This is only a change in line numbers. 2021-04-16 21:29:17 +02:00
Mathias Vorreiter Pedersen
64f8316a6d C++: Tidy up the ql file and accept test changes. 2021-04-16 21:22:13 +02:00
Mathias Vorreiter Pedersen
1e327289b2 C++: Add false negative test. 2021-04-16 18:38:51 +02:00
Mathias Vorreiter Pedersen
50abb6e3a1 C++: Cleanup test.c 2021-04-16 17:32:44 +02:00
Shati Patel
5c2bf68a05 Merge pull request #5692 from tamasvajk/feature/doc-cs9
Update supported C#/.NET versions
2021-04-16 16:22:06 +01:00
Jonas Jensen
f8d45f04ed Revert "Revert "C++: Work around extractor issue CPP-383""
**Revert the revert** of the workaround for CFG issues when a
`FunctionCall` has a `getTarget` that does not exist. While we've fixed
the main cause of the problem, it can apparently still happen in rare
cases as a result of extractor crashes.

This reverts commit ee5eaef5e4.
2021-04-16 16:44:58 +02:00
Tom Hvitved
40b74167e0 C#: Improve performance of DisposeNotCalledOnException.ql 2021-04-16 14:34:16 +02:00
Rasmus Wriedt Larsen
3c8ea167c4 Merge pull request #5668 from tausbn/python-use-api-graphs-in-fabric
Python: Use API graphs in Fabric model
2021-04-16 14:27:55 +02:00
Rasmus Wriedt Larsen
6ed1016bb8 Merge pull request #5669 from tausbn/python-use-api-graphs-for-invoke
Python: Use API graphs for Invoke
2021-04-16 14:27:19 +02:00
Taus
92b4eb7f02 Python: Cleanup and more explanation
Goes into some detail about the intended semantics of local source nodes
and `flowsTo`.
2021-04-16 11:54:20 +00:00
Geoffrey White
e1028a2765 Merge pull request #5667 from MathiasVP/use-range-analysis-in-overflow
C++: Use range analysis in Overflow.qll
2021-04-16 12:00:28 +01:00
Taus
5c79ad2412 Python: Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-04-16 11:38:29 +02:00
Taus
af0c32c01d Python: Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-04-16 11:35:12 +02:00
Anders Schack-Mulligen
605f28f741 Merge pull request #5686 from smowton/haby0/JsonHijacking
Java: JSONP Injection w/cleanups
2021-04-16 11:09:17 +02:00
Tom Hvitved
946fcf1c82 C#: Speedup DispatchMethodOrAccessorCall::getAViableOverrider()
In addition to improved performance, the analysis no longer applies a closed-world
assumption to type parameters. That is, if the type of a receiver is a type parameter,
then the call may target any method of a compatible receiver type, not just the
types that actually instantiate the type parameter.
2021-04-16 10:43:17 +02:00
Tamas Vajk
b0975bb3ea Update supported C#/.NET versions 2021-04-16 09:15:43 +02:00
Taus
451d36dc97 Python: Allow _some_ PostUpdateNodes
Specifically, allow the ones arising from calls, but not reads or
writes. This should fix the tests.
2021-04-15 21:26:12 +00:00
Taus
c9c8259ed0 Python: Disallow PostUpdateNode as LocalSourceNode
Previously, in cases like

```python
def foo(x):
    x.bar()
    x.baz()
    x.quux()
```

we would have flow from the first `x` to each use _and_ flow from the
post-update node for each method call to each subsequent use, and all
of these would be `LocalSourceNode`s. For large functions with the above
pattern, this would lead to a quadratic blowup in `hasLocalSource`.

With this commit, only the first of these will count as a
`LocalSourceNode`, and the blowup disappears.
2021-04-15 17:56:14 +00:00
Andrew Eisenberg
5d827b6fc8 Actions: Change staleness calculation
Calculate staleness on issues that have the
`Stale` label. Leave all other issues untouched.
2021-04-15 10:14:13 -07:00
Rasmus Wriedt Larsen
3e7dc12246 Python: Port taint tests to use inline expectations
The meat of this PR is described in the new python/ql/test/experimental/meta/InlineTaintTest.qll file:

> Defines a InlineExpectationsTest for checking whether any arguments in
> `ensure_tainted` and `ensure_not_tainted` calls are tainted.
>
> Also defines query predicates to ensure that:
> - if any arguments to `ensure_not_tainted` are tainted, their annotation is marked with `SPURIOUS`.
> - if any arguments to `ensure_tainted` are not tainted, their annotation is marked with `MISSING`.
>
> The functionality of this module is tested in `ql/test/experimental/meta/inline-taint-test-demo`.
2021-04-15 18:00:33 +02:00
Chris Smowton
c37994089c Revert changes to unrelated query 2021-04-15 16:24:29 +01:00
Chris Smowton
254de76078 Remove unnecessary stubs 2021-04-15 16:20:27 +01:00
haby0
dedf765542 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-15 22:59:22 +08:00
Rasmus Wriedt Larsen
b359205d17 Python: Add taint tests for .get() in flask 2021-04-15 14:53:44 +02:00
CodeQL CI
578ce1e512 Merge pull request #5683 from asgerf/js/typescript-template-literal-type-crash
Approved by erik-krogh
2021-04-15 05:11:11 -07:00
Mathias Vorreiter Pedersen
7fbc62358e C++: Accept test changes after making the exprMightOverFlow predicates more sound. 2021-04-15 13:57:44 +02:00
haby0
0e183ab4a4 Finish comment 2021-04-15 19:49:06 +08:00
Chris Smowton
fa36ba901a Merge pull request #5471 from artem-smotrakov/el-injection
Java: Query for detecting Jakarta Expression Language injections
2021-04-15 12:39:34 +01:00
haby0
d269a7e717 CWE-598 reduction 2021-04-15 19:33:15 +08:00
haby0
216f204438 delete FilterClass 2021-04-15 19:28:25 +08:00
haby0
583d0889e2 delete tomcat-embed-core stub, update the ServletGetMethod class 2021-04-15 17:40:51 +08:00
haby0
5d05e4d224 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-15 17:28:53 +08:00
Tom Hvitved
0f24db8759 C#: Improve performance of SsaImpl::CallGraph::SimpleDelegateAnalysis 2021-04-15 11:25:27 +02:00
Asger Feldthaus
f8570bb293 JS: Update TRAP 2021-04-15 10:16:46 +01:00
Asger Feldthaus
cb736c8c82 JS: Change note 2021-04-15 09:37:57 +01:00
Tom Hvitved
972cc47f67 Merge pull request #5673 from hvitved/csharp/customizations
C#: Add `Customizations.qll`
2021-04-15 10:24:29 +02:00
Asger Feldthaus
b4a2a9db25 JS: Fix extraction of non-substitution template literal types 2021-04-15 09:23:45 +01:00
Chris Smowton
bd3b3178ba Fix documentation of Modifier.qll 2021-04-15 09:16:51 +01:00
haby0
b3bdf89fc2 rm VerificationMethodFlowConfig, use springframework-5.2.3 stub 2021-04-15 10:25:40 +08:00
CodeQL CI
4be183c7f6 Merge pull request #5675 from erik-krogh/libXss
Approved by esbena
2021-04-14 14:34:23 -07:00
ihsinme
b30ae3980c Update InsufficientControlFlowManagementAfterRefactoringTheCode.ql 2021-04-14 20:48:20 +03:00
Robert Marsh
fe57876fd8 Merge pull request #5643 from dbartol/smart-pointers/side-effect-refactor
C++: Refactor some side effect generation code
2021-04-14 09:59:41 -07:00
Taus
897d12420b Python: Prevent bad join in isinstanceEvaluatesTo
In some cases, we were joining the result of `val.getClass()` against
the first argument of `Types::improperSubclass` before filtering out the
vast majority of tuples by the call to `isinstance_call`.

To fix this, we let `isinstance_call` take care of figuring out the
class of the value being tested. As a bonus, this cleans up the only
other place where `isinstance_call` is used, where we _also_ want to
know the class of the value being tested in the `isinstance` call.
2021-04-14 16:49:12 +00:00
Artem Smotrakov
97186b3d30 Added comments for tests 2021-04-14 19:30:58 +03:00
Andrew Eisenberg
56ba0f080a Merge pull request #5659 from github/aeisenberg/mark-as-stale
Actions: Add workflow for marking stale questions
2021-04-14 08:37:55 -07:00
Taus
a7fcf52267 Python: Fix bad join in total_cost
The recent change to `appliesTo` lead to a perturbation in the join
order of this predicate, which resulted in a cartesian product between
`call` and `ctx` being created (before being filtered by `appliesTo`).

By splitting the intermediate result into its own helper predicate,
suitably marked to prevent inlining/magic, we prevent this from
happening again.
2021-04-14 15:36:01 +00:00
Andrew Eisenberg
392adf2a25 Workflows: Remove dry-run flag for labeller 2021-04-14 08:25:34 -07:00
Dave Bartolomeo
b29f35f564 Fix formatting 2021-04-14 11:15:16 -04:00
Geoffrey White
64fed4cb10 Merge pull request #5677 from MathiasVP/fix-duplicate-ids-in-experimental
C++: Fix duplicate names in experimental queries
2021-04-14 15:58:49 +01:00
Jonas Jensen
b4f01c9afa Merge pull request #5578 from MathiasVP/ast-flow-smart-pointers
C++: AST dataflow through smart pointers
2021-04-14 16:39:05 +02:00
Mathias Vorreiter Pedersen
53a320a810 C++: Fix duplicate names. 2021-04-14 16:33:18 +02:00
Mathias Vorreiter Pedersen
bb447d7174 C++: Make sure missingGuardAgainstOverflow (and underflow) holds when range analysis fails to deduce a bound. 2021-04-14 16:30:43 +02:00
yoff
447f339857 Merge pull request #5641 from tausbn/python-use-localsourcenode-in-typetrackers
Python: Use API graphs in PEP249 support
2021-04-14 15:39:49 +02:00
Mathias Vorreiter Pedersen
92508beb82 Merge pull request #5600 from ihsinme/ihsinme-patch-258
CPP: Add query for CWE-691 Insufficient Control Flow Management When Using Bit Operations
2021-04-14 14:55:30 +02:00
Anders Schack-Mulligen
f43d427875 Merge pull request #5645 from Marcono1234/marcono1234/primary-ql-class
Java: Override getAPrimaryQlClass() for more classes
2021-04-14 14:51:29 +02:00
Mathias Vorreiter Pedersen
bc7cc2f7ce C++: Remove rule that wasn't needed. 2021-04-14 14:50:27 +02:00
Mathias Vorreiter Pedersen
da36508714 Revert "C++: As response to the review comments this commit adds a reference-to-pointer state to AddressFlow. A call to an unwrapper function now adds a pointer -> reference-to-pointer transition, and a ReferenceDereference adds a reference-to-pointer -> pointer transition."
This reverts commit 5aeaab7c6d.
2021-04-14 14:41:22 +02:00
Chris Smowton
591ac38c31 Merge pull request #5591 from Marcono1234/marcono1234/member-nested-type
Java: Add MemberType
2021-04-14 12:29:54 +01:00
Taus
54c79bff74 Merge pull request #5666 from RasmusWL/django-refactor
Python: Refactoring and exposing of Django views/fields/forms
2021-04-14 13:07:20 +02:00
Mathias Vorreiter Pedersen
2e40d01397 Update cpp/ql/src/semmle/code/cpp/security/Overflow.qll
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2021-04-14 13:01:31 +02:00
Rasmus Wriedt Larsen
44d2bf42d7 Merge pull request #5671 from tausbn/python-use-api-graphs-in-werkzeug
Python: Use API graphs in Werkzeug
2021-04-14 12:57:58 +02:00
Erik Krogh Kristensen
fd23e0bdda use more API nodes in XmlParsers, and recognize more results from parsing XML 2021-04-14 11:48:31 +02:00
Anders Schack-Mulligen
3b6cd0f681 Merge pull request #5661 from smowton/smowton/cleanup/call-is-exprparent
Make Call a subclass of ExprParent.
2021-04-14 10:49:33 +02:00
Rasmus Wriedt Larsen
9de8085571 Merge pull request #5665 from tausbn/python-use-api-graphs-in-tornado
Python: Tornado cleanup using API graphs
2021-04-14 10:22:21 +02:00
Rasmus Wriedt Larsen
2d0c9b6bf2 Merge pull request #5670 from tausbn/python-use-api-graphs-in-dill
Python: Use API graphs in Dill model
2021-04-14 10:08:02 +02:00
Rasmus Wriedt Larsen
55723618a9 Python: Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-04-14 10:05:50 +02:00
Chris Smowton
2965a1f204 Use Thread$State as an inner-class example
Map<>$Entry currently has odd generic notation that may be about to change.
2021-04-14 08:43:05 +01:00
Chris Smowton
5158e7964e Add change note 2021-04-14 08:25:12 +01:00
Tom Hvitved
36fe72246b C#: Add change note 2021-04-14 09:22:16 +02:00
Tom Hvitved
4810308b16 C#: Add Customizations.qll 2021-04-14 09:16:31 +02:00
haby0
77208bcc91 Fix the error that there is no VerificationMethodToIfFlowConfig 2021-04-14 13:14:43 +08:00
haby0
e2ed0d02b0 Delete existsFilterVerificationMethod and existsServletVerificationMethod, add from get handler to filter 2021-04-14 12:34:52 +08:00
haby0
37dae67a0d Fix RequestResponseFlowConfig.isSink error 2021-04-14 09:55:24 +08:00
Robert Marsh
419d25cbcf Merge pull request #5325 from ihsinme/ihsinme-patch-245
CPP: Add query for CWE-783 Operator Precedence Logic Error When Use Bool Type
2021-04-13 13:24:39 -07:00
Taus
981c5deb57 Merge pull request #5639 from tausbn/python-api-graphs-missing-builtins
Python: Add missing builtins to `API::builtin`
2021-04-13 21:27:52 +02:00
Marcono1234
d853f0c400 Java: Add MemberType 2021-04-13 18:55:20 +02:00
Taus
a6bb9ebb9f Python: Re-introduce abstract toString
This seems like the easier solution in the short run.
2021-04-13 16:08:41 +00:00
Taus
079c7e089d Python: Autoformat 2021-04-13 16:05:45 +00:00
Taus
273e8ce4ef Python: Add change note 2021-04-13 16:04:07 +00:00
haby0
00235ed3b3 Update java/ql/src/semmle/code/java/frameworks/Servlets.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-13 23:58:52 +08:00
haby0
25b012db48 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.ql
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-13 23:58:28 +08:00
Taus
5f7d3d0d36 Python: Use API graphs in Werkzeug 2021-04-13 15:57:21 +00:00
haby0
7be45e7c5e Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.ql
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-13 23:56:17 +08:00
haby0
6e73d13670 Update java/ql/src/semmle/code/java/frameworks/Servlets.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-13 23:48:45 +08:00
Taus
2890fe6d61 Python: Use API graphs in Dill model
If only all rewrites were this smooth...
2021-04-13 15:26:54 +00:00
Taus
7ed09904b4 Python: Use API graphs for Invoke
A few stragglers remain, as they are modelling the use of decorators.

They will be dealt with at a later date.
2021-04-13 15:21:19 +00:00
Mathias Vorreiter Pedersen
aa52585120 C++: Add change-note. 2021-04-13 17:17:05 +02:00
Marcono1234
89a5acf6e8 Java: Revert overriding XMLFile.getAPrimaryQlClass()
Library file has to be kept in sync with the other languages, however except
cpp none of them have the getAPrimaryQlClass() predicate declared in a
superclass. Therefore for simplicity revert the change for Java.
2021-04-13 17:09:15 +02:00
Taus
7f131c1f35 Python: Get rid of _attr predicates 2021-04-13 14:55:44 +00:00
Taus
1008411594 Python: Use API graphs in Fabric model 2021-04-13 14:49:44 +00:00
Mathias Vorreiter Pedersen
d1457995dd C++: Use range analysis in Overflow.qll 2021-04-13 16:39:28 +02:00
Taus
a404faa302 Python: Use American English in change note
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
2021-04-13 15:05:44 +02:00
Taus
7825a2cdfc Python: Add change note 2021-04-13 12:48:45 +00:00
Taus
1a4845f417 Python: Restrict types a bit
The `CallCfgNode` restrictions are familiar and useful.

Restricting `InstanceSource` to extend `LocalSourceNode` is novel, but I
think it makes sense. It will act as a good reminder to anyone extending
`InstanceSource` that the node in question is a `LocalSourceNode`, which
will be enforced by the return type of the internal type tracker anyway.
2021-04-13 12:28:38 +00:00
Taus
f93b68d4dc Python: Get rid of _attr methods 2021-04-13 12:25:38 +00:00
Taus
98d936d8b3 Python: Tornado cleanup using API graphs
I wasn't able to roll out API graphs as widely in Tornado as I had
hoped, since we're lacking the "def" part. This means most of the
`InstanceSource` machinery will have to stay.
2021-04-13 12:25:38 +00:00
CodeQL CI
f341d5010d Merge pull request #5662 from asgerf/js/simpler-json-api
Approved by erik-krogh
2021-04-13 04:37:56 -07:00
Tom Hvitved
9b0ef2fe21 Merge pull request #5654 from hvitved/csharp/autobuilder/pwsh
C#: First try `pwsh` and then `powershell` when calling `dotnet-install.ps1`
2021-04-13 13:15:01 +02:00
Chris Smowton
58d198261e Merge pull request #5663 from smowton/luchua/java/sensitive-cookie-not-httponly
Java: CWE-1004 Query to check sensitive cookies without the HttpOnly flag set w/minor corrections
2021-04-13 12:08:53 +01:00
CodeQL CI
646639bc73 Merge pull request #5460 from erik-krogh/forgery-2
Approved by asgerf
2021-04-13 03:57:04 -07:00
Chris Smowton
f22b11881e Minimise stubs
By removing all business logic from the stubs, we better test that our analysis treats them as opaque and does not rely on their internal structure
2021-04-13 10:36:28 +01:00
Chris Smowton
45e1a61d7b Mark test as bad-but-missed
This test ought ideally to be caught, but isn't by the current version of the query.
2021-04-13 10:36:27 +01:00
Asger Feldthaus
e77117f902 JS: Autoformat 2021-04-13 10:29:14 +01:00
Asger Feldthaus
929d9da4b4 JS: Migrate to new JSON API 2021-04-13 10:29:13 +01:00
Asger Feldthaus
7c13163413 JS: Lift JSON accessors to JSONValue 2021-04-13 10:29:13 +01:00
Tom Hvitved
15c103e42d C#: Remove code duplication in BuildScripts.cs 2021-04-13 10:57:15 +02:00
Chris Smowton
dee974ff2d Make Call a subclass of ExprParent. All of its subclasses are in any case (via Expr or Stmt) 2021-04-13 09:13:47 +01:00
Marcono1234
c37dbb2e68 Java: Override getAPrimaryQlClass() for more classes 2021-04-13 08:46:01 +01:00
Mathias Vorreiter Pedersen
3cfd30ef6f Merge pull request #5629 from hvitved/cpp/remove-unique
C++: Remove `unique` wrapper from `DataFlow::Node::getEnclosingCallable`
2021-04-13 09:42:34 +02:00
haby0
be39883166 Change the class name and comment,Use .(CompileTimeConstantExpr).getStringValue() 2021-04-13 14:10:10 +08:00
Dave Bartolomeo
afd2f58f9f C++: Fix PR feedback 2021-04-12 18:21:05 -04:00
Dave Bartolomeo
697b2dcde8 C++: Add missing store step for single-field struct use
We have special code to handle field flow for single-field structs, but that special case was too specific. Some `Store`s to single-field structs have no `Chi` instruction, which is the case that we handled already. However, it is possible for the `Store` to have a `Chi` instruction (e.g. for `{AllAliased}`), but still have a use of the result of the `Store` directly. We now add a `PostUpdateNode` for the result of the `Store` itself in those cases, just like we already did if the `Store` had no `Chi`.
2021-04-12 18:11:41 -04:00
Robert Marsh
0102d68f38 Merge pull request #5658 from MathiasVP/fix-partial-def-diff-test
C++: Fix performance in test
2021-04-12 13:08:30 -07:00
Andrew Eisenberg
e0fcb15739 Actions: Add workflow for marking stale questions
This PR adds a workflow for marking and closing issues as stale. Issues must be labeled as _question_. PRs are never marked as stale.
2021-04-12 13:05:53 -07:00
Artem Smotrakov
b96b665262 Renaming in java/ql/src/experimental/Security/CWE/CWE-094 2021-04-12 21:40:49 +03:00
Mathias Vorreiter Pedersen
037e6369ce C++: Ensure all values are bound in both disjunctions. 2021-04-12 18:27:21 +02:00
luchua-bc
d7f26dfc18 Update stub classes and qldoc 2021-04-12 16:19:23 +00:00
Taus
fda750ef26 Merge pull request #5642 from tausbn/python-use-api-graphs-in-stdlib
Python: Use API graphs in `Stdlib.qll`
2021-04-12 18:05:38 +02:00
Chris Smowton
423ff32d04 Merge pull request #5384 from luchua-bc/java/insecure-spring-actuator-config
Java: CWE-016 Query to detect insecure configuration of Spring Boot Actuator
2021-04-12 17:04:47 +01:00
Taus
6d4ddc0329 Merge pull request #5614 from tausbn/python-allow-absolute-imports-from-source-directory
Python: Allow absolute imports from source directory
2021-04-12 18:02:00 +02:00
CodeQL CI
bc56d16c18 Merge pull request #5485 from RasmusWL/django-queryset-chains
Approved by tausbn
2021-04-12 08:49:31 -07:00
Tom Hvitved
dfc91b8331 C#: Simplify dotnet-install.ps1 invocation
Using the pattern from https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
2021-04-12 17:33:33 +02:00
Chris Smowton
bb23866cec Add missing doc comments 2021-04-12 16:33:01 +01:00
Tom Hvitved
d35a501121 Merge pull request #5583 from lcartey/cs/restrict-jump-to-def
C#: Exclude jump-to-def information for elements with too many locations
2021-04-12 16:52:20 +02:00
ihsinme
a43698802f Update InsufficientControlFlowManagementWhenUsingBitOperations.ql 2021-04-12 17:36:50 +03:00
CodeQL CI
310a2c8bb3 Merge pull request #5655 from erik-krogh/cert
Approved by esbena
2021-04-12 07:31:04 -07:00
Chris Smowton
2656a52880 Merge pull request #5538 from luchua-bc/java/credentials-in-properties
Java: CWE-555 Query to detect plaintext credentials in Java properties files
2021-04-12 15:22:21 +01:00
Chris Smowton
abeefcaced Merge pull request #4947 from porcupineyhairs/DexLoading
Java : add query to detect insecure loading of Dex File
2021-04-12 15:22:12 +01:00
Mathias Vorreiter Pedersen
5aeaab7c6d C++: As response to the review comments this commit adds a reference-to-pointer state to AddressFlow. A call to an unwrapper function now adds a pointer -> reference-to-pointer transition, and a ReferenceDereference adds a reference-to-pointer -> pointer transition. 2021-04-12 16:01:01 +02:00
ihsinme
58d5ad48d5 Update InsufficientControlFlowManagementAfterRefactoringTheCode.ql 2021-04-12 17:00:34 +03:00
ihsinme
d7c14775bf Update InsufficientControlFlowManagementAfterRefactoringTheCode.qhelp 2021-04-12 16:56:48 +03:00
Chris Smowton
11bf982728 Remove superfluous linebreaks in qhelp file 2021-04-12 14:36:42 +01:00
Erik Krogh Kristensen
32737a17fb add change note 2021-04-12 15:09:13 +02:00
Erik Krogh Kristensen
172d6139e2 support all ClientRequests in js/disabling-certificate-validation 2021-04-12 15:06:10 +02:00
luchua-bc
c281e54d22 Remove unused files and update qldoc 2021-04-12 13:05:01 +00:00
Tom Hvitved
57016ddbde C++: Remove unique wrapper from DataFlow::Node::getEnclosingCallable() 2021-04-12 14:41:52 +02:00
Tom Hvitved
7d2a60e910 Merge pull request #5640 from hvitved/dataflow/path-step-perf
Data flow: Prevent bad join-order in `pathStep`
2021-04-12 14:40:46 +02:00
Tamas Vajk
b4d35b52c3 C#: Add Console.Read* to local flow sources 2021-04-12 14:19:17 +02:00
Tom Hvitved
5446532e1d C#: Update auto-builder tests 2021-04-12 14:01:55 +02:00
Anders Schack-Mulligen
acd4cf2878 Merge pull request #5636 from aschackmull/java/shared-flow-summaries
Java: Adopt shared flow summaries
2021-04-12 13:35:31 +02:00
CodeQL CI
e8d835b422 Merge pull request #5638 from erik-krogh/smartInliner
Approved by esbena
2021-04-12 04:17:25 -07:00
Tom Hvitved
c7686b1838 C#: First try pwsh and then powershell when calling dotnet-install.ps1 2021-04-12 13:01:14 +02:00
Tom Hvitved
cf5f838b13 Data flow: Remove recommendation to use unique in Node::getEnclosingCallable() 2021-04-12 12:04:23 +02:00
Anders Schack-Mulligen
e003b04061 Merge pull request #5637 from Marcono1234/marcono1234/toString-method
Java: Add ToStringMethod
2021-04-12 11:43:55 +02:00
Max Schaefer
cd57e61f65 Rename MkHasUnderlyingType to MkTypeUse. 2021-04-12 11:30:15 +02:00
Erik Krogh Kristensen
91d28fb8b0 cleanup in API-graphs 2021-04-12 11:30:15 +02:00
CodeQL CI
63f087a8e9 Merge pull request #5653 from erik-krogh/givenCommand
Approved by asgerf
2021-04-12 02:01:32 -07:00
Rasmus Wriedt Larsen
364d48948f Merge pull request #3810 from dilanbhalla/syntaxpython
Python: Function/Class Naming Convention (Syntax)
2021-04-12 10:42:17 +02:00
Erik Krogh Kristensen
17c4bbbc4e allow parameters that end with "Command" in js/shell-command-constructed-from-input 2021-04-12 09:57:40 +02:00
haby0
1b948ac2e2 Combine two Configurations into one 2021-04-12 15:44:39 +08:00
ihsinme
feb3a8deb1 Update InsufficientControlFlowManagementAfterRefactoringTheCode.expected 2021-04-12 08:23:41 +03:00
ihsinme
6924c6c51c Update test.c 2021-04-12 08:23:06 +03:00
ihsinme
3da88f2103 Update InsufficientControlFlowManagementAfterRefactoringTheCode.c 2021-04-12 08:15:36 +03:00
ihsinme
17d1c77a14 Update InsufficientControlFlowManagementAfterRefactoringTheCode.ql 2021-04-12 08:14:17 +03:00
yo-h
4f2060f96b Merge commit '2d618d6b928d8b76ac8033b3b63d9bde71caa325' into yo-h/java16 2021-04-11 23:55:33 -04:00
Taus
10be2735ec Python: Get rid of _attr predicates
Also changes all `CfgNode`s representing calls to `CallCfgNode`s.
2021-04-10 12:12:18 +00:00
haby0
d90527bead JsonpInjectionExpr updated to JsonpBuilderExpr 2021-04-10 10:33:21 +08:00
Marcono1234
9349e6922d Java: Add ToStringMethod 2021-04-10 04:00:44 +02:00
haby0
eeae91e620 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 09:48:55 +08:00
haby0
046aeaa38c Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 09:37:29 +08:00
haby0
8b756d7f1b Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.ql
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 09:27:03 +08:00
haby0
650446f761 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 09:26:32 +08:00
haby0
a5ebe8c600 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 09:26:08 +08:00
porcupineyhairs
8687c5c145 Apply suggestions from code review
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:18:35 +05:30
haby0
8a7d28a2ed Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:29:49 +08:00
haby0
4c21980d4f Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:29:30 +08:00
haby0
9635a36044 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.ql
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:29:06 +08:00
haby0
760231c004 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:28:17 +08:00
haby0
c77c7b0a98 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:27:16 +08:00
haby0
837f20108d Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjectionLib.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:25:43 +08:00
haby0
157e4670fd Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.qhelp
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:25:11 +08:00
haby0
79c1374925 Update java/ql/src/semmle/code/java/frameworks/Servlets.qll
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:24:49 +08:00
haby0
1510048f7a Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.qhelp
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:23:13 +08:00
haby0
d8165145c7 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.qhelp
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:22:44 +08:00
haby0
ebd38eaf3b Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.qhelp
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:22:08 +08:00
haby0
b8c11503f0 Update java/ql/src/experimental/Security/CWE/CWE-352/JsonpInjection.qhelp
Co-authored-by: Chris Smowton <smowton@github.com>
2021-04-10 04:21:49 +08:00
Dave Bartolomeo
0a86642056 C++: Refactor some side effect generation code
This change was necessary for my upcoming changes to introduce side effect instructions for indirections of smart pointers. The code to decide which parameters have which side effects appeared in both the IPA constructor for `TTranslatedSideEffect` and in `TranslatedCall`. These two versions didn't quite agree, especially once the `SideEffectFunction` model provides its own side effects instead of the defaults.
The relevant code has now been factored out into `SideEffects.qll`. This queries the model if one exists, and provides default side effects if no model exists. This fixes at least one existing issue, where we were emitting a buffer read side effect for `*this` instead of an indirect read side effect. This accounts for all of the IR diffs in the tests.
2021-04-09 16:14:03 -04:00
luchua-bc
4e3791dc0d Remove LoadCredentialsConfiguration and update qldoc 2021-04-09 19:36:35 +00:00
Taus
720fbaf301 Python: Fix test error.
Somehow, having to type "Node" all day long made me turn "json" into
"node"...

Also removes some bits that weren't needed after all.
2021-04-09 19:04:49 +00:00
Mathias Vorreiter Pedersen
1510fe370d C++: Add cases for const pointer wrapper references to AddressFlow and FlowVar. 2021-04-09 20:58:05 +02:00
Mathias Vorreiter Pedersen
2329b31601 C++: Replace the new SmartPointerPartialDefinition with additional steps in AddressFlow.qll 2021-04-09 20:49:45 +02:00
Mathias Vorreiter Pedersen
a460e3ad3d Merge branch 'main' into ast-flow-smart-pointers 2021-04-09 19:41:10 +02:00
Taus
cc4827600b Python: Use API graphs in Stdlib.qll
Eliminates _almost_ all of the bespoke type trackers found here. The
ones that remain do not fit easily inside the framework of API graphs
(at least, not yet), and I did not see any easy ways to clean them up.
They have, however, been rewritten to use `LocalSourceNode` internally,
which was the primary goal of this exercise.

I'm sure we could also clean up many of the inner modules given the more
lean presentation we have now, but this can wait for a different PR.
2021-04-09 17:11:47 +00:00
luchua-bc
04b0682bbf Use isAdditionalTaintStep and make the query more readable 2021-04-09 16:14:51 +00:00
Tom Hvitved
fd8f745468 Java: Adopt shared flow summary library and refactor data-flow nodes. 2021-04-09 16:57:03 +02:00
Tom Hvitved
f130616369 Data flow: Make getLocalCc private again 2021-04-09 16:22:58 +02:00
Taus
d2b874f217 Python: Use API graphs in PEP249 support
Because the replacement extension point now extends `API::Node`, I
modified the `toString` method of the latter to have an empty body.
The alternative would be to require everyone to provide a `toString`
predicate for their extensions, but seeing as these will usually be
pointing to already existing API graph nodes, this seems silly.

(This may be the reason why the equivalent method in the JS libs has
such an implementation.)
2021-04-09 14:19:00 +00:00
Tom Hvitved
6874b8d4b3 Data flow: Prevent bad join-order in pathStep 2021-04-09 14:24:47 +02:00
Taus
affdedd840 Python: Add missing builtins to API::builtin
We were missing out on `None`, `True`, and `False` as these do not
appear as actual attributes of the `builtins` module in Python 3
(because they are elevated to the status of keywords there)

The simple solution, then, is to just always include them directly.
2021-04-09 12:02:07 +00:00
Mathias Vorreiter Pedersen
0a6aef71a2 C++: Respond to review comments. 2021-04-09 12:29:13 +02:00
Tamas Vajk
53daa7c436 Java: Migrate LDAP injection sinks to CSV format 2021-04-09 09:15:47 +02:00
luchua-bc
11304b2ae1 Update qldoc and change the wrapper method implementation 2021-04-09 02:21:59 +00:00
Erik Krogh Kristensen
7f01586bf1 fix bad join order in getDocumentedParameter 2021-04-09 01:15:46 +02:00
Erik Krogh Kristensen
e5bce548de add nomagic on mayHaveStringValue 2021-04-09 00:08:51 +02:00
Erik Krogh Kristensen
956311457d fixed bad SourceNode X SourceNode join in HTTP model 2021-04-08 21:15:50 +02:00
ihsinme
9b3ccade43 Update test.c 2021-04-08 22:06:35 +03:00
ihsinme
3d117243e4 Update test.c 2021-04-08 22:05:31 +03:00
ihsinme
02eb447a35 Update InsufficientControlFlowManagementWhenUsingBitOperations.expected 2021-04-08 22:04:08 +03:00
ihsinme
a6b486a448 Update InsufficientControlFlowManagementWhenUsingBitOperations.ql 2021-04-08 22:01:43 +03:00
Dilan
d73ba13b28 autoformat fix 2021-04-08 11:41:58 -07:00
Artem Smotrakov
b39a3ab12c Added setVariable() sink 2021-04-08 20:41:43 +03:00
Rasmus Wriedt Larsen
83477439a1 Python: Make django views/fields/forms class modeling extensible
This also requires that we make this part of the modeling public, which I guess
is step we want to take eventually anyway!

I'm not quite sure whether the modules `Django::Views` and `Django::Forms` are
actually helpful, or whether we should just have their modules available as
`Django::View`, `Django::Form`, and `Django::Field`...
2021-04-08 12:45:37 +02:00
Rasmus Wriedt Larsen
b7483a5394 Python: Add modeledSubclassRef for Django views/fields/forms 2021-04-08 12:45:36 +02:00
Rasmus Wriedt Larsen
322bdcb703 Python: Port Django view modeling to API graphs 2021-04-08 12:45:35 +02:00
Rasmus Wriedt Larsen
8ce5c46e05 Python: Minor refactor
modName/clsName _is_ shorter, but also looks way worse :D
2021-04-08 12:45:34 +02:00
Dilan
675de07c3e autoformat ql 2021-04-07 15:04:18 -07:00
ihsinme
ed34c96357 Update InsufficientControlFlowManagementWhenUsingBitOperations.ql 2021-04-07 21:40:49 +03:00
ihsinme
eb9b41acab Apply suggestions from code review
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-04-07 21:31:12 +03:00
Artem Smotrakov
a764a79090 Always bind arguments in TaintPropagatingCall 2021-04-07 21:12:21 +03:00
Artem Smotrakov
c13ee0859a LambdaExpression should extend JakartaType 2021-04-07 21:02:21 +03:00
Artem Smotrakov
3d8e173c57 Removed a reference to Apache Commons EL 2021-04-07 20:59:07 +03:00
Artem Smotrakov
80ac2aff26 Fixed typos
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-04-07 20:55:03 +03:00
Taus
6c69c1aeeb Python: Minor cleanup 2021-04-07 10:47:21 +00:00
ihsinme
cbf158ea6b Add files via upload 2021-04-07 13:12:30 +03:00
ihsinme
36de496d47 Add files via upload 2021-04-07 13:12:29 +03:00
ihsinme
ed2a8db8c9 Add files via upload 2021-04-07 13:10:01 +03:00
ihsinme
9c3b7e81c7 Add files via upload 2021-04-07 13:10:00 +03:00
Taus
a93132daae Merge branch 'python-allow-absolute-imports-from-source-directory' of https://github.com/tausbn/codeql into python-allow-absolute-imports-from-source-directory 2021-04-06 19:58:57 +00:00
Taus
43ae7462b4 Python: Only track modules that are imported
This greatly restricts the set of modules that have a new name under
this scheme.

One change to the tests was needed, which reflects the fact that the
two `main.py` files no longer have the name `main` (which makes sense,
since they're never imported under this name).
2021-04-06 21:56:12 +02:00
Taus
b44db460f6 Python: Only track modules that are imported 2021-04-06 19:55:43 +00:00
yo-h
cc63563a88 Merge remote-tracking branch 'upstream-public/main' into yo-h/java16 2021-04-06 13:16:02 -04:00
Taus Brock-Nannestad
8e11abca40 Revert "Merge pull request #5552 from RasmusWL/revert-import-change"
This reverts commit 49d1937dc4, reversing
changes made to d4877a9038.
2021-04-06 17:39:41 +02:00
Mathias Vorreiter Pedersen
32a8b9a857 C++: Move copy constructor to its own line and accept test changes. 2021-04-06 08:56:14 +02:00
Luke Cartey
480ce39618 C#: Exclude jump-to-def information for elements with too many locations
In databases which include multiple duplicated files, we can get an
explosion of definition locations that can cause this query to produce
too many results for the CodeQL toolchain. This commit restricts the
definitions.ql query to producing definition/uses for definitions with
fewer than 10 locations. This replicates the logic used in the C++
definitions.qll library which faces similar problems.
2021-04-01 11:23:31 +01:00
Mathias Vorreiter Pedersen
ecbce88ec7 C++: Fix comment. 2021-03-31 22:23:50 +02:00
Mathias Vorreiter Pedersen
9ff894bf83 C++: Add support for AST dataflow out of functions that take a smart pointer by value. 2021-03-31 13:54:32 +02:00
Mathias Vorreiter Pedersen
8159098dc0 C++: Add test from issue #5190. 2021-03-31 11:32:01 +02:00
luchua-bc
1349bf7b0b Create a .qll file to reuse the code and add check of Spring properties 2021-03-30 11:25:29 +00:00
haby0
0775d35591 update VerificationMethodFlowConfig, add if test 2021-03-29 12:02:37 +08:00
ihsinme
3f215d0954 Update OperatorPrecedenceLogicErrorWhenUseBoolType.ql 2021-03-28 23:43:22 +03:00
ihsinme
093c63ea3b Update OperatorPrecedenceLogicErrorWhenUseBoolType.expected 2021-03-28 23:42:36 +03:00
luchua-bc
5ce3f9d6ff Update qldoc and enhance the query 2021-03-28 16:10:35 +00:00
luchua-bc
a53cbc1631 Update qldoc and make the query more readable 2021-03-27 00:11:01 +00:00
luchua-bc
a72b1340eb Add a comment on how to run the query 2021-03-26 16:51:43 +00:00
Alexander Eyers-Taylor
b21672c81c Apply suggestions from code review
Co-authored-by: Shati Patel <42641846+shati-patel@users.noreply.github.com>
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-03-26 11:15:46 +00:00
luchua-bc
d33b04cd96 Query to detect plaintext credentials in Java properties files 2021-03-26 02:33:40 +00:00
Porcuiney Hairs
2ca95166d9 Java : add query to detect insecure loading of Dex File 2021-03-26 01:59:11 +05:30
alexet
2576c86ebf Docs: Update the language specification for changes to super. 2021-03-25 18:16:13 +00:00
luchua-bc
57bd3f3c14 Optimize the taint flow source 2021-03-25 10:44:26 +00:00
luchua-bc
fe0e7f5eac Change method check to taint flow 2021-03-25 01:45:13 +00:00
luchua-bc
08c3bf26d5 Update the query to accommodate more cases 2021-03-24 23:32:27 +00:00
haby0
3df23eecb6 Merge remote-tracking branch 'upstream/main' into JsonHijacking 2021-03-24 15:52:01 +08:00
Rasmus Wriedt Larsen
c8a6e837b5 Python: Model QuerySet chains in django 2021-03-22 14:38:54 +01:00
Rasmus Wriedt Larsen
701b935564 Python: Add example of QuerySet chain (django) 2021-03-22 00:57:43 +01:00
Artem Smotrakov
6c24699403 Cover both javax.el and jakarta.el packages 2021-03-21 21:19:39 +03:00
Artem Smotrakov
adb1ed380a Added tests for Jakarta expression injection 2021-03-21 21:19:39 +03:00
Artem Smotrakov
73e940de74 Added query for Jakarta EL injections
- Added JakartaExpressionInjection.ql
- Added a qhelp file with examples
2021-03-21 21:19:39 +03:00
yo-h
0200aedc2e Java 16: adjust test options 2021-03-21 12:55:25 -04:00
ihsinme
26bac9f425 Apply suggestions from code review
Co-authored-by: Robert Marsh <rdmarsh2@gmail.com>
2021-03-21 15:25:29 +03:00
Dilan
1385b22642 pr fixes, typo in qhelp file and helper method for queries 2021-03-19 16:43:29 -07:00
haby0
15206fd2ce JsonpInjection.ql autoformatted 2021-03-17 15:52:05 +08:00
haby0
98204a15a6 Fix the problem 2021-03-17 15:28:04 +08:00
luchua-bc
1a2e341b7c Refactor the business logic of the query into a separate predicate 2021-03-12 12:19:37 +00:00
luchua-bc
c8b1bc3a89 Enhance the query 2021-03-11 21:41:34 +00:00
luchua-bc
0a35feef76 Exclude CSRF cookies to reduce FPs 2021-03-11 17:28:07 +00:00
luchua-bc
eeac7e322a Query to detect insecure configuration of Spring Boot Actuator 2021-03-11 13:46:32 +00:00
luchua-bc
a0a1ddee86 Update class name 2021-03-10 17:07:31 +00:00
luchua-bc
f0ddfc9283 Minor qldoc changes 2021-03-10 12:18:55 +00:00
luchua-bc
72f28513eb Move test check to the sink 2021-03-10 12:12:27 +00:00
luchua-bc
48975fa7d2 Replace sanitizers 2021-03-10 00:17:26 +00:00
luchua-bc
31eaa80f5b Revamp the source 2021-03-06 00:56:15 +00:00
luchua-bc
a93aabab40 Add the toString() method 2021-03-05 03:05:49 +00:00
luchua-bc
919c6b4b0a Optimize flow steps 2021-03-05 02:50:54 +00:00
ihsinme
10cc574289 Add files via upload 2021-03-04 16:15:26 +03:00
ihsinme
01c13c4703 Add files via upload 2021-03-04 16:14:11 +03:00
haby0
c5577cb09a Fix the problem 2021-03-04 19:54:49 +08:00
luchua-bc
502cf38fcc Use concise API 2021-03-03 14:07:43 +00:00
luchua-bc
1b1c3f953b Remove localflow from the source 2021-03-03 13:54:26 +00:00
luchua-bc
b366ffa69e Revamp source of the query 2021-03-03 13:38:18 +00:00
luchua-bc
95d1994196 Query to check sensitive cookies without the HttpOnly flag set 2021-03-01 22:06:52 +00:00
haby0
f795d5e0d3 update JSONP Injection ql 2021-02-27 16:25:17 +08:00
haby0
0521ef87da Merge remote-tracking branch 'upstream/main' into JsonHijacking 2021-02-25 16:31:14 +08:00
haby0
6fe8bafc7d *)update 2021-02-24 20:59:51 +08:00
haby0
872a000a33 *)update to JSONP injection 2021-02-24 20:36:12 +08:00
haby0
8119fd2ad1 *)add JsonHijacking ql query 2021-02-18 18:11:10 +08:00
dilanbhalla
26b030f8cc fixed pr suggestions 2020-07-07 10:52:26 -07:00
dilanbhalla
dc73fcc4e8 moved to experimental 2020-07-01 09:54:58 -07:00
dilanbhalla
dc58f6fa87 function/class synatax 2020-06-25 11:39:09 -07:00
456 changed files with 11113 additions and 6328 deletions

30
.github/workflows/close-stale.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Mark stale issues
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
if: github.repository == 'github/codeql'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Comment or remove the `Stale` label in order to avoid having this issue closed in 7 days.'
close-issue-message: 'This issue was closed because it has been inactive for 7 days.'
days-before-stale: 14
days-before-close: 7
only-labels: awaiting-response
# do not mark PRs as stale
days-before-pr-stale: -1
days-before-pr-close: -1
# Uncomment for dry-run
# debug-only: true
# operations-per-run: 1000

View File

@@ -19,13 +19,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
security_events: write
pull_requests: read
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@main
# Override language selection by uncommenting this and choosing your languages # Override language selection by uncommenting this and choosing your languages
with: with:
languages: csharp languages: csharp
@@ -34,7 +39,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@main
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -48,4 +53,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@main

View File

@@ -56,6 +56,10 @@
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll" "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
], ],
"DataFlow Java/C# Flow Summaries": [
"java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll"
],
"SsaReadPosition Java/C#": [ "SsaReadPosition Java/C#": [
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll", "java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll" "csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"

View File

@@ -0,0 +1,2 @@
lgtm
* The queries cpp/tainted-arithmetic, cpp/uncontrolled-arithmetic, and cpp/arithmetic-with-extreme-values have been improved to produce fewer false positives.

View File

@@ -0,0 +1,2 @@
codescanning
* The 'Pointer to stack object used as return value' (cpp/return-stack-allocated-object) query has been deprecated, and any uses should be replaced with `Returning stack-allocated memory` (cpp/return-stack-allocated-memory).

View File

@@ -7,6 +7,8 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-562 * external/cwe/cwe-562
* @deprecated This query is not suitable for production use and has been deprecated. Use
* cpp/return-stack-allocated-memory instead.
*/ */
import semmle.code.cpp.pointsto.PointsTo import semmle.code.cpp.pointsto.PointsTo

View File

@@ -13,6 +13,7 @@
import cpp import cpp
import semmle.code.cpp.dataflow.EscapesTree import semmle.code.cpp.dataflow.EscapesTree
import semmle.code.cpp.models.interfaces.PointerWrapper
import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow
/** /**
@@ -39,6 +40,10 @@ predicate hasNontrivialConversion(Expr e) {
e instanceof ParenthesisExpr e instanceof ParenthesisExpr
) )
or or
// A smart pointer can be stack-allocated while the data it points to is heap-allocated.
// So we exclude such "conversions" from this predicate.
e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction()
or
hasNontrivialConversion(e.getConversion()) hasNontrivialConversion(e.getConversion())
} }

View File

@@ -0,0 +1,17 @@
while(flagsLoop)
{
...
if(flagsIf) break;
...
}while(flagsLoop); // BAD: when exiting through `break`, it is possible to get into an eternal loop.
...
while(flagsLoop)
{
...
if(flagsIf) break;
...
} // GOOD: correct cycle
...
if(intA+intB) return 1; // BAD: possibly no comparison
...
if(intA+intB>intC) return 1; // GOOD: correct comparison

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>In some situations, after code refactoring, parts of the old constructs may remain. They are correctly accepted by the compiler, but can critically affect program execution. For example, if you switch from `do {...} while ();` to `while () {...}` forgetting to remove the old construct completely, you get `while(){...}while();` which may be vulnerable. These code snippets look suspicious and require the developer's attention.</p>
</overview>
<recommendation>
<p>We recommend that you use more explicit code transformations.</p>
</recommendation>
<example>
<p>The following example demonstrates the erroneous and corrected sections of the code.</p>
<sample src="InsufficientControlFlowManagementAfterRefactoringTheCode.c" />
</example>
<references>
<li>
CWE Common Weakness Enumeration:
<a href="https://cwe.mitre.org/data/definitions/691.html"> CWE-691: Insufficient Control Flow Management</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,119 @@
/**
* @name Errors After Refactoring
* @description --In some situations, after code refactoring, parts of the old constructs may remain.
* --They are correctly accepted by the compiler, but can critically affect program execution.
* --For example, if you switch from `do {...} while ();` to `while () {...}` with errors, you run the risk of running out of resources.
* --These code snippets look suspicious and require the developer's attention.
* @kind problem
* @id cpp/errors-after-refactoring
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-691
*/
import cpp
import semmle.code.cpp.valuenumbering.HashCons
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* Using `while` directly after the body of another` while`.
*/
class UsingWhileAfterWhile extends WhileStmt {
/**
* Using a loop call after another loop has finished running can result in an eternal loop.
* For example, perhaps as a result of refactoring, the `do ... while ()` loop was incorrectly corrected.
* Even in the case of deliberate use of such an expression, it is better to correct it.
*/
UsingWhileAfterWhile() {
exists(WhileStmt wh1 |
wh1.getStmt().getAChild*().(BreakStmt).(ControlFlowNode).getASuccessor().getASuccessor() =
this and
hashCons(wh1.getCondition()) = hashCons(this.getCondition()) and
this.getStmt() instanceof EmptyStmt
)
or
exists(ForStmt fr1 |
fr1.getStmt().getAChild*().(BreakStmt).(ControlFlowNode).getASuccessor().getASuccessor() =
this and
hashCons(fr1.getCondition()) = hashCons(this.getCondition()) and
this.getStmt() instanceof EmptyStmt
)
}
}
/**
* Using arithmetic in a condition.
*/
class UsingArithmeticInComparison extends BinaryArithmeticOperation {
/**
* Using arithmetic operations in a comparison operation can be dangerous.
* For example, part of the comparison may have been lost as a result of refactoring.
* Even if you deliberately use such an expression, it is better to add an explicit comparison.
*/
UsingArithmeticInComparison() {
this.getParent*() instanceof IfStmt and
not this.getAChild*().isConstant() and
not this.getParent*() instanceof Call and
not this.getParent*() instanceof AssignExpr and
not this.getParent*() instanceof ArrayExpr and
not this.getParent*() instanceof RemExpr and
not this.getParent*() instanceof AssignBitwiseOperation and
not this.getParent*() instanceof AssignArithmeticOperation and
not this.getParent*() instanceof EqualityOperation and
not this.getParent*() instanceof RelationalOperation
}
/** Holds when the expression is inside the loop body. */
predicate insideTheLoop() { exists(Loop lp | lp.getStmt().getAChild*() = this.getParent*()) }
/** Holds when the expression is used in binary operations. */
predicate workingWithValue() {
this.getParent*() instanceof BinaryBitwiseOperation or
this.getParent*() instanceof NotExpr
}
/** Holds when the expression contains a pointer. */
predicate workingWithPointer() {
this.getAChild*().getFullyConverted().getType() instanceof DerivedType
}
/** Holds when a null comparison expression exists. */
predicate compareWithZero() {
exists(Expr exp |
exp instanceof ComparisonOperation and
(
globalValueNumber(exp.getAChild*()) = globalValueNumber(this) or
hashCons(exp.getAChild*()) = hashCons(this)
) and
(
exp.(ComparisonOperation).getLeftOperand().getValue() = "0" or
exp.(ComparisonOperation).getRightOperand().getValue() = "0"
)
)
}
/** Holds when a comparison expression exists. */
predicate compareWithOutZero() {
exists(Expr exp |
exp instanceof ComparisonOperation and
(
globalValueNumber(exp.getAChild*()) = globalValueNumber(this) or
hashCons(exp.getAChild*()) = hashCons(this)
)
)
}
}
from Expr exp
where
exp instanceof UsingArithmeticInComparison and
not exp.(UsingArithmeticInComparison).workingWithValue() and
not exp.(UsingArithmeticInComparison).workingWithPointer() and
not exp.(UsingArithmeticInComparison).insideTheLoop() and
not exp.(UsingArithmeticInComparison).compareWithZero() and
exp.(UsingArithmeticInComparison).compareWithOutZero()
or
exists(WhileStmt wst | wst instanceof UsingWhileAfterWhile and exp = wst.getCondition())
select exp, "this expression needs your attention"

View File

@@ -0,0 +1,4 @@
if(len>0 & memset(buf,0,len)) return 1; // BAD: `memset` will be called regardless of the value of the `len` variable. moreover, one cannot be sure that it will happen after verification
...
if(len>0 && memset(buf,0,len)) return 1; // GOOD: `memset` will be called after the `len` variable has been checked.
...

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Using bitwise operations can be a mistake in some situations. For example, if parameters are evaluated in an expression and the function should be called only upon certain test results. These bitwise operations look suspicious and require developer attention.</p>
</overview>
<recommendation>
<p>We recommend that you evaluate the correctness of using the specified bit operations.</p>
</recommendation>
<example>
<p>The following example demonstrates the erroneous and fixed use of bit and logical operations.</p>
<sample src="InsufficientControlFlowManagementWhenUsingBitOperations.c" />
</example>
<references>
<li>
CWE Common Weakness Enumeration:
<a href="https://cwe.mitre.org/data/definitions/691.html"> CWE-691: Insufficient Control Flow Management</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,78 @@
/**
* @name Errors When Using Bit Operations
* @description Unlike the binary operations `||` and `&&`, there is no sequence point after evaluating an
* operand of a bitwise operation like `|` or `&`. If left-to-right evaluation is expected this may be confusing.
* @kind problem
* @id cpp/errors-when-using-bit-operations
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-691
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* Dangerous uses of bit operations.
* For example: `if(intA>0 & intA<10 & charBuf&myFunc(charBuf[intA]))`.
* In this case, the function will be called in any case, and even the sequence of the call is not guaranteed.
*/
class DangerousBitOperations extends BinaryBitwiseOperation {
FunctionCall bfc;
/**
* The assignment indicates the conscious use of the bit operator.
* Use in comparison, conversion, or return value indicates conscious use of the bit operator.
* The use of shifts and bitwise operations on any element of an expression indicates a conscious use of the bitwise operator.
*/
DangerousBitOperations() {
bfc = this.getRightOperand() and
not this.getParent*() instanceof Assignment and
not this.getParent*() instanceof Initializer and
not this.getParent*() instanceof ReturnStmt and
not this.getParent*() instanceof EqualityOperation and
not this.getParent*() instanceof UnaryLogicalOperation and
not this.getParent*() instanceof BinaryLogicalOperation and
not this.getAChild*() instanceof BitwiseXorExpr and
not this.getAChild*() instanceof LShiftExpr and
not this.getAChild*() instanceof RShiftExpr
}
/** Holds when part of a bit expression is used in a logical operation. */
predicate useInLogicalOperations() {
exists(BinaryLogicalOperation blop, Expr exp |
blop.getAChild*() = exp and
exp.(FunctionCall).getTarget() = bfc.getTarget() and
not exp.getParent() instanceof ComparisonOperation and
not exp.getParent() instanceof BinaryBitwiseOperation
)
}
/** Holds when part of a bit expression is used as part of another supply. For example, as an argument to another function. */
predicate useInOtherCalls() {
bfc.hasQualifier() or
bfc.getTarget() instanceof Operator or
exists(FunctionCall fc | fc.getAnArgument().getAChild*() = this) or
bfc.getTarget() instanceof BuiltInFunction
}
/** Holds when the bit expression contains both arguments and a function call. */
predicate dangerousArgumentChecking() {
not this.getLeftOperand() instanceof Call and
globalValueNumber(this.getLeftOperand().getAChild*()) = globalValueNumber(bfc.getAnArgument())
}
/** Holds when function calls are present in the bit expression. */
predicate functionCallsInBitsExpression() {
this.getLeftOperand().getAChild*() instanceof FunctionCall
}
}
from DangerousBitOperations dbo
where
not dbo.useInOtherCalls() and
dbo.useInLogicalOperations() and
(not dbo.functionCallsInBitsExpression() or dbo.dangerousArgumentChecking())
select dbo, "This bitwise operation appears in a context where a Boolean operation is expected."

View File

@@ -0,0 +1,11 @@
if(len=funcReadData()==0) return 1; // BAD: variable `len` will not equal the value returned by function `funcReadData()`
...
if((len=funcReadData())==0) return 1; // GOOD: variable `len` equal the value returned by function `funcReadData()`
...
bool a=true;
a++;// BAD: variable `a` does not change its meaning
bool b;
b=-a;// BAD: variable `b` equal `true`
...
a=false;// GOOD: variable `a` equal `false`
b=!a;// GOOD: variable `b` equal `false`

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Finding places of confusing use of boolean type. For example, a unary minus does not work before a boolean type and an increment always gives true.</p>
</overview>
<recommendation>
<p>we recommend making the code simpler.</p>
</recommendation>
<example>
<p>The following example demonstrates erroneous and fixed methods for using a boolean data type.</p>
<sample src="OperatorPrecedenceLogicErrorWhenUseBoolType.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation">EXP00-C. Use parentheses for precedence of operation</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,54 @@
/**
* @name Operator Precedence Logic Error When Use Bool Type
* @description --Finding places of confusing use of boolean type.
* --For example, a unary minus does not work before a boolean type and an increment always gives true.
* @kind problem
* @id cpp/operator-precedence-logic-error-when-use-bool-type
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-783
* external/cwe/cwe-480
*/
import cpp
import semmle.code.cpp.valuenumbering.HashCons
/** Holds if `exp` increments a boolean value. */
predicate incrementBoolType(IncrementOperation exp) {
exp.getOperand().getType() instanceof BoolType
}
/** Holds if `exp` applies the unary minus operator to a boolean type. */
predicate revertSignBoolType(UnaryMinusExpr exp) {
exp.getAnOperand().getType() instanceof BoolType and
exp.getFullyConverted().getType() instanceof BoolType
}
/** Holds, if this is an expression, uses comparison and assignment outside of execution precedence. */
predicate assignBoolType(Expr exp) {
exists(ComparisonOperation co |
exp.(AssignExpr).getRValue() = co and
exp.isCondition() and
not co.isParenthesised() and
not exp.(AssignExpr).getLValue().getType() instanceof BoolType and
not exists(Expr exbl |
hashCons(exbl.(AssignExpr).getLValue()) = hashCons(exp.(AssignExpr).getLValue()) and
not exbl.isCondition() and
exbl.(AssignExpr).getRValue().getType() instanceof BoolType and
exbl.(AssignExpr).getLValue().getType() = exp.(AssignExpr).getLValue().getType()
) and
co.getLeftOperand() instanceof FunctionCall and
not co.getRightOperand().getType() instanceof BoolType and
not co.getRightOperand().getValue() = "0" and
not co.getRightOperand().getValue() = "1"
)
}
from Expr exp
where
incrementBoolType(exp) or
revertSignBoolType(exp) or
assignBoolType(exp)
select exp, "this expression needs attention"

View File

@@ -3,7 +3,7 @@
* @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. * @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior.
* If terminal zero is present, then the specified expression is meaningless. * If terminal zero is present, then the specified expression is meaningless.
* @kind problem * @kind problem
* @id cpp/access-memory-location-after-end-buffer * @id cpp/access-memory-location-after-end-buffer-strlen
* @problem.severity warning * @problem.severity warning
* @precision medium * @precision medium
* @tags correctness * @tags correctness

View File

@@ -2,7 +2,7 @@
* @name Access Of Memory Location After The End Of A Buffer Using Strncat * @name Access Of Memory Location After The End Of A Buffer Using Strncat
* @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer. * @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer.
* @kind problem * @kind problem
* @id cpp/access-memory-location-after-end-buffer * @id cpp/access-memory-location-after-end-buffer-strncat
* @problem.severity warning * @problem.severity warning
* @precision medium * @precision medium
* @tags correctness * @tags correctness
@@ -11,54 +11,32 @@
*/ */
import cpp import cpp
import semmle.code.cpp.models.implementations.Strcat
import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/** /**
* A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`. * Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and
* destination arguments, respectively.
*/ */
class WrongCallStrncat extends FunctionCall { predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
Expr leftsomeExpr; exists(StrcatFunction strcat |
strcat = call.getTarget() and
WrongCallStrncat() { sizeArg = call.getArgument(strcat.getParamSize()) and
this.getTarget().hasGlobalOrStdName("strncat") and destArg = call.getArgument(strcat.getParamDest())
// the expression of the first argument in `strncat` and `strnlen` is identical )
globalValueNumber(this.getArgument(0)) =
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
// using a string constant often speaks of manually calculating the length of the required buffer.
(
not this.getArgument(1) instanceof StringLiteral and
not this.getArgument(1) instanceof CharLiteral
) and
// for use in predicates
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
}
/**
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
*/
predicate isExpressionEqualSizeof() {
// the left side of the expression `someExpr` is `sizeof(buf)`.
globalValueNumber(this.getArgument(0)) =
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
or
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
}
/**
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
*/
predicate isVariableEqualValueSizegBuffer() {
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
exists(AllocationExpr alc |
leftsomeExpr.(VariableAccess).getTarget() =
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
)
}
} }
from WrongCallStrncat sc from FunctionCall call, Expr sizeArg, Expr destArg, SubExpr sub, int n
where where
sc.isExpressionEqualSizeof() or interestringCallWithArgs(call, sizeArg, destArg) and
sc.isVariableEqualValueSizegBuffer() // The destination buffer is an array of size n
select sc, "if the used buffer is full, writing out of the buffer is possible" destArg.getUnspecifiedType().(ArrayType).getSize() = n and
// The size argument is equivalent to a subtraction
globalValueNumber(sizeArg).getAnExpr() = sub and
// ... where the left side of the subtraction is the constant n
globalValueNumber(sub.getLeftOperand()).getAnExpr().getValue().toInt() = n and
// ... and the right side of the subtraction is a call to `strlen` where the argument is the
// destination buffer.
globalValueNumber(sub.getRightOperand()).getAnExpr().(StrlenCall).getStringExpr() =
globalValueNumber(destArg).getAnExpr()
select call, "Possible out-of-bounds write due to incorrect size argument."

View File

@@ -1307,7 +1307,8 @@ private predicate conditionJumps(Expr test, boolean truth, Node n2, Pos p2) {
) )
} }
// Factored out for performance. See QL-796. // Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.
private predicate normalGroupMemberBaseCase(Node memberNode, Pos memberPos, Node atNode) { private predicate normalGroupMemberBaseCase(Node memberNode, Pos memberPos, Node atNode) {
memberNode = atNode and memberNode = atNode and
memberPos.isAt() and memberPos.isAt() and

View File

@@ -104,9 +104,43 @@ private predicate loopConditionAlwaysUponEntry(ControlFlowNode loop, Expr condit
) )
} }
/**
* This relation is the same as the `el instanceof Function`, only obfuscated
* so the optimizer will not understand that any `FunctionCall.getTarget()`
* should be in this relation.
*/
pragma[noinline]
private predicate isFunction(Element el) {
el instanceof Function
or
el.(Expr).getParent() = el
}
/**
* Holds if `fc` is a `FunctionCall` with no return value for `getTarget`. This
* can happen in case of rare database inconsistencies.
*/
pragma[noopt]
private predicate callHasNoTarget(@funbindexpr fc) {
exists(Function f |
funbind(fc, f) and
not isFunction(f)
)
}
// Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.
private predicate potentiallyReturningFunctionCall_base(FunctionCall fc) {
fc.isVirtual()
or
callHasNoTarget(fc)
}
/** A function call that *may* return; if in doubt, we assume it may. */ /** A function call that *may* return; if in doubt, we assume it may. */
private predicate potentiallyReturningFunctionCall(FunctionCall fc) { private predicate potentiallyReturningFunctionCall(FunctionCall fc) {
potentiallyReturningFunction(fc.getTarget()) or fc.isVirtual() potentiallyReturningFunctionCall_base(fc)
or
potentiallyReturningFunction(fc.getTarget())
} }
/** A function that *may* return; if in doubt, we assume it may. */ /** A function that *may* return; if in doubt, we assume it may. */

View File

@@ -15,6 +15,7 @@
*/ */
private import cpp private import cpp
private import semmle.code.cpp.models.interfaces.PointerWrapper
/** /**
* Holds if `f` is an instantiation of the `std::move` or `std::forward` * Holds if `f` is an instantiation of the `std::move` or `std::forward`
@@ -94,6 +95,12 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) { private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) {
lvalueIn.getConversion() = referenceOut.(ReferenceToExpr) lvalueIn.getConversion() = referenceOut.(ReferenceToExpr)
or
exists(PointerWrapper wrapper, Call call | call = referenceOut |
referenceOut.getUnspecifiedType() instanceof ReferenceType and
call = wrapper.getAnUnwrapperFunction().getACallToThisFunction() and
lvalueIn = call.getQualifier().getFullyConverted()
)
} }
private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) { private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {
@@ -106,6 +113,13 @@ private predicate referenceToPointerStep(Expr referenceIn, Expr pointerOut) {
stdAddressOf(call.getTarget()) and stdAddressOf(call.getTarget()) and
referenceIn = call.getArgument(0).getFullyConverted() referenceIn = call.getArgument(0).getFullyConverted()
) )
or
exists(CopyConstructor copy, Call call | call = pointerOut |
copy.getDeclaringType() instanceof PointerWrapper and
call.getTarget() = copy and
// The 0'th argument is the value being copied.
referenceIn = call.getArgument(0).getFullyConverted()
)
} }
private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) { private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) {
@@ -190,6 +204,19 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
// See the `lvalueToUpdate` case for an explanation of this conjunct. // See the `lvalueToUpdate` case for an explanation of this conjunct.
call.getType().isDeeplyConstBelow() call.getType().isDeeplyConstBelow()
) )
or
// Pointer wrappers behave as raw pointers for dataflow purposes.
outer = call.getAnArgument().getFullyConverted() and
exists(PointerWrapper wrapper | wrapper = outer.getType().stripTopLevelSpecifiers() |
not wrapper.pointsToConst()
)
or
outer = call.getQualifier().getFullyConverted() and
outer.getUnspecifiedType() instanceof PointerWrapper and
not (
call.getTarget().hasSpecifier("const") and
call.getType().isDeeplyConstBelow()
)
) )
or or
exists(PointerFieldAccess fa | exists(PointerFieldAccess fa |
@@ -218,7 +245,9 @@ private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode
not stdIdentityFunction(call.getTarget()) and not stdIdentityFunction(call.getTarget()) and
not stdAddressOf(call.getTarget()) and not stdAddressOf(call.getTarget()) and
exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() | exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() |
not rt.getBaseType().isConst() not rt.getBaseType().isConst() or
rt.getBaseType().getUnspecifiedType() =
any(PointerWrapper wrapper | not wrapper.pointsToConst())
) )
) and ) and
reference = outer reference = outer

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -46,7 +46,7 @@ class Node extends TNode {
/** /**
* INTERNAL: Do not use. Alternative name for `getFunction`. * INTERNAL: Do not use. Alternative name for `getFunction`.
*/ */
final Function getEnclosingCallable() { result = unique(Function f | f = this.getFunction() | f) } final Function getEnclosingCallable() { result = this.getFunction() }
/** Gets the type of this node. */ /** Gets the type of this node. */
Type getType() { none() } // overridden in subclasses Type getType() { none() } // overridden in subclasses
@@ -324,7 +324,7 @@ private class VariablePartialDefinitionNode extends PartialDefinitionNode {
* A synthetic data flow node used for flow into a collection when an iterator * A synthetic data flow node used for flow into a collection when an iterator
* write occurs in a callee. * write occurs in a callee.
*/ */
class IteratorPartialDefinitionNode extends PartialDefinitionNode { private class IteratorPartialDefinitionNode extends PartialDefinitionNode {
override IteratorPartialDefinition pd; override IteratorPartialDefinition pd;
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
@@ -715,6 +715,7 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
} }
private module FieldFlow { private module FieldFlow {
private import DataFlowImplCommon
private import DataFlowImplLocal private import DataFlowImplLocal
private import DataFlowPrivate private import DataFlowPrivate
@@ -747,7 +748,7 @@ private module FieldFlow {
exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and
// This configuration should not be able to cross function boundaries, but // This configuration should not be able to cross function boundaries, but
// we double-check here just to be sure. // we double-check here just to be sure.
node1.getEnclosingCallable() = node2.getEnclosingCallable() getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2)
} }
} }

View File

@@ -7,6 +7,7 @@ private import semmle.code.cpp.controlflow.SSA
private import semmle.code.cpp.dataflow.internal.SubBasicBlocks private import semmle.code.cpp.dataflow.internal.SubBasicBlocks
private import semmle.code.cpp.dataflow.internal.AddressFlow private import semmle.code.cpp.dataflow.internal.AddressFlow
private import semmle.code.cpp.models.implementations.Iterator private import semmle.code.cpp.models.implementations.Iterator
private import semmle.code.cpp.models.interfaces.PointerWrapper
/** /**
* A conceptual variable that is assigned only once, like an SSA variable. This * A conceptual variable that is assigned only once, like an SSA variable. This
@@ -158,18 +159,14 @@ private module PartialDefinitions {
Expr innerDefinedExpr; Expr innerDefinedExpr;
IteratorPartialDefinition() { IteratorPartialDefinition() {
exists(Expr convertedInner | innerDefinedExpr = getInnerDefinedExpr(this, node) and
not this instanceof Conversion and (
valueToUpdate(convertedInner, this.getFullyConverted(), node) and innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection)
innerDefinedExpr = convertedInner.getUnconverted() and or
( innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and
innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection) collection instanceof IteratorParameter
or ) and
innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator
collection instanceof IteratorParameter
) and
innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator
)
or or
// iterators passed by value without a copy constructor // iterators passed by value without a copy constructor
exists(Call call | exists(Call call |
@@ -207,16 +204,18 @@ private module PartialDefinitions {
} }
} }
private Expr getInnerDefinedExpr(Expr e, ControlFlowNode node) {
not e instanceof Conversion and
exists(Expr convertedInner |
valueToUpdate(convertedInner, e.getFullyConverted(), node) and
result = convertedInner.getUnconverted()
)
}
class VariablePartialDefinition extends PartialDefinition { class VariablePartialDefinition extends PartialDefinition {
Expr innerDefinedExpr; Expr innerDefinedExpr;
VariablePartialDefinition() { VariablePartialDefinition() { innerDefinedExpr = getInnerDefinedExpr(this, node) }
not this instanceof Conversion and
exists(Expr convertedInner |
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
innerDefinedExpr = convertedInner.getUnconverted()
)
}
deprecated override predicate partiallyDefines(Variable v) { deprecated override predicate partiallyDefines(Variable v) {
innerDefinedExpr = v.getAnAccess() innerDefinedExpr = v.getAnAccess()
@@ -296,7 +295,8 @@ module FlowVar_internal {
// treating them as immutable, but for data flow it gives better results in // treating them as immutable, but for data flow it gives better results in
// practice to make the variable synonymous with its contents. // practice to make the variable synonymous with its contents.
not v.getUnspecifiedType() instanceof ReferenceType and not v.getUnspecifiedType() instanceof ReferenceType and
not v instanceof IteratorParameter not v instanceof IteratorParameter and
not v instanceof PointerWrapperParameter
} }
/** /**
@@ -644,10 +644,19 @@ module FlowVar_internal {
predicate parameterIsNonConstReference(Parameter p) { predicate parameterIsNonConstReference(Parameter p) {
exists(ReferenceType refType | exists(ReferenceType refType |
refType = p.getUnderlyingType() and refType = p.getUnderlyingType() and
not refType.getBaseType().isConst() (
not refType.getBaseType().isConst()
or
// A field of a parameter of type `const std::shared_ptr<A>& p` can still be changed even though
// the base type of the reference is `const`.
refType.getBaseType().getUnspecifiedType() =
any(PointerWrapper wrapper | not wrapper.pointsToConst())
)
) )
or or
p instanceof IteratorParameter p instanceof IteratorParameter
or
p instanceof PointerWrapperParameter
} }
/** /**
@@ -836,6 +845,10 @@ module FlowVar_internal {
IteratorParameter() { this.getUnspecifiedType() instanceof Iterator } IteratorParameter() { this.getUnspecifiedType() instanceof Iterator }
} }
class PointerWrapperParameter extends Parameter {
PointerWrapperParameter() { this.getUnspecifiedType() instanceof PointerWrapper }
}
/** /**
* Holds if `v` is initialized to have value `assignedExpr`. * Holds if `v` is initialized to have value `assignedExpr`.
*/ */

View File

@@ -11,6 +11,7 @@
private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.DataFlow
private import semmle.code.cpp.models.interfaces.Taint private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.Iterator private import semmle.code.cpp.models.interfaces.Iterator
private import semmle.code.cpp.models.interfaces.PointerWrapper
private module DataFlow { private module DataFlow {
import semmle.code.cpp.dataflow.internal.DataFlowUtil import semmle.code.cpp.dataflow.internal.DataFlowUtil
@@ -141,7 +142,10 @@ private predicate noFlowFromChildExpr(Expr e) {
or or
e instanceof LogicalOrExpr e instanceof LogicalOrExpr
or or
e instanceof Call // Allow taint from `operator*` on smart pointers.
exists(Call call | e = call |
not call.getTarget() = any(PointerWrapper wrapper).getAnUnwrapperFunction()
)
or or
e instanceof SizeofOperator e instanceof SizeofOperator
or or

View File

@@ -314,6 +314,7 @@ class OverloadedPointerDereferenceFunction extends Function {
* T1 operator*(const T2 &); * T1 operator*(const T2 &);
* T1 a; T2 b; * T1 a; T2 b;
* a = *b; * a = *b;
* ```
*/ */
class OverloadedPointerDereferenceExpr extends FunctionCall { class OverloadedPointerDereferenceExpr extends FunctionCall {
OverloadedPointerDereferenceExpr() { OverloadedPointerDereferenceExpr() {

View File

@@ -1271,7 +1271,8 @@ private predicate convparents(Expr child, int idx, Element parent) {
) )
} }
// Pulled out for performance. See QL-796. // Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.
private predicate hasNoConversions(Expr e) { not e.hasConversion() } private predicate hasNoConversions(Expr e) { not e.hasConversion() }
/** /**

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -362,15 +362,22 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
/** /**
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to. * Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
* For instance, an update to a field of a struct containing only one field. For these cases we * For instance, an update to a field of a struct containing only one field. Even if the store does
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case * have a chi instruction, a subsequent use of the result of the store may be linked directly to the
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`. * result of the store as an inexact definition if the store totally overlaps the use. For these
* cases we attach the PostUpdateNode to the store instruction. There's no obvious pre update node
* for this case (as the entire memory is updated), so `getPreUpdateNode` is implemented as
* `none()`.
*/ */
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode { private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr; override StoreInstruction instr;
ExplicitSingleFieldStoreQualifierNode() { ExplicitSingleFieldStoreQualifierNode() {
not exists(ChiInstruction chi | chi.getPartial() = instr) and (
instr.getAUse().isDefinitionInexact()
or
not exists(ChiInstruction chi | chi.getPartial() = instr)
) and
// Without this condition any store would create a `PostUpdateNode`. // Without this condition any store would create a `PostUpdateNode`.
instr.getDestinationAddress() instanceof FieldAddressInstruction instr.getDestinationAddress() instanceof FieldAddressInstruction
} }

View File

@@ -6,34 +6,7 @@ private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import PrintIRUtilities
/**
* Gets a short ID for an IR dataflow node.
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
* instruction and a dot (e.g. `m128.left`).
* - For `Variable`s, this is the qualified name of the variable.
*/
private string nodeId(DataFlow::Node node, int order1, int order2) {
exists(Instruction instruction | instruction = node.asInstruction() |
result = instruction.getResultId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
exists(Operand operand, Instruction instruction |
operand = node.asOperand() and
instruction = operand.getUse()
|
result = instruction.getResultId() + "." + operand.getDumpId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
result = "var(" + node.asVariable().getQualifiedName() + ")" and
order1 = 1000000 and
order2 = 0
}
/** /**
* Gets the local dataflow from other nodes in the same function to this node. * Gets the local dataflow from other nodes in the same function to this node.

View File

@@ -0,0 +1,33 @@
/**
* Print the dataflow local store steps in IR dumps.
*/
private import cpp
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
// that the cached IR gets the same checksum here as it does in queries that use
// `ValueNumbering` without `DataFlow`.
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import PrintIRUtilities
/**
* Property provider for local IR dataflow store steps.
*/
class LocalFlowPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instruction, string key) {
exists(DataFlow::Node objectNode, Content content |
key = "content[" + content.toString() + "]" and
instruction = objectNode.asInstruction() and
result =
strictconcat(string element, DataFlow::Node fieldNode |
storeStep(fieldNode, content, objectNode) and
element = nodeId(fieldNode, _, _)
|
element, ", "
)
)
}
}

View File

@@ -0,0 +1,39 @@
/**
* Shared utilities used when printing dataflow annotations in IR dumps.
*/
private import cpp
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
// that the cached IR gets the same checksum here as it does in queries that use
// `ValueNumbering` without `DataFlow`.
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
/**
* Gets a short ID for an IR dataflow node.
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
* instruction and a dot (e.g. `m128.left`).
* - For `Variable`s, this is the qualified name of the variable.
*/
string nodeId(DataFlow::Node node, int order1, int order2) {
exists(Instruction instruction | instruction = node.asInstruction() |
result = instruction.getResultId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
exists(Operand operand, Instruction instruction |
operand = node.asOperand() and
instruction = operand.getUse()
|
result = instruction.getResultId() + "." + operand.getDumpId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
result = "var(" + node.asVariable().getQualifiedName() + ")" and
order1 = 1000000 and
order2 = 0
}

View File

@@ -0,0 +1,109 @@
/**
* Predicates to compute the modeled side effects of calls during IR construction.
*
* These are used in `TranslatedElement.qll` to generate the `TTranslatedSideEffect` instances, and
* also in `TranslatedCall.qll` to inject the actual side effect instructions.
*/
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.models.interfaces.SideEffect
/**
* Holds if the specified call has a side effect that does not come from a `SideEffectFunction`
* model.
*/
private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buffer, boolean isWrite) {
not call.getTarget() instanceof SideEffectFunction and
(
exists(MemberFunction mfunc |
// A non-static member function, including a constructor or destructor, may write to `*this`,
// and may also read from `*this` if it is not a constructor.
i = -1 and
mfunc = call.getTarget() and
not mfunc.isStatic() and
buffer = false and
(
isWrite = false and not mfunc instanceof Constructor
or
isWrite = true and not mfunc instanceof ConstMemberFunction
)
)
or
exists(Expr expr |
// A pointer-like argument is assumed to read from the pointed-to buffer, and may write to the
// buffer as well unless the pointer points to a `const` value.
i >= 0 and
buffer = true and
expr = call.getArgument(i).getFullyConverted() and
exists(Type t | t = expr.getUnspecifiedType() |
t instanceof ArrayType or
t instanceof PointerType or
t instanceof ReferenceType
) and
(
isWrite = true and
not call.getTarget().getParameter(i).getType().isDeeplyConstBelow()
or
isWrite = false
)
)
)
}
/**
* Returns a side effect opcode for parameter index `i` of the specified call.
*
* This predicate will return at most two results: one read side effect, and one write side effect.
*/
Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
exists(boolean buffer |
(
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(i, buffer)
or
not call.getTarget() instanceof SideEffectFunction and
hasDefaultSideEffect(call, i, buffer, false)
) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(i))
then (
buffer = true and
result instanceof Opcode::SizedBufferReadSideEffect
) else (
buffer = false and result instanceof Opcode::IndirectReadSideEffect
or
buffer = true and result instanceof Opcode::BufferReadSideEffect
)
)
or
exists(boolean buffer, boolean mustWrite |
(
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(i, buffer, mustWrite)
or
not call.getTarget() instanceof SideEffectFunction and
hasDefaultSideEffect(call, i, buffer, true) and
mustWrite = false
) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(i))
then (
buffer = true and
mustWrite = false and
result instanceof Opcode::SizedBufferMayWriteSideEffect
or
buffer = true and
mustWrite = true and
result instanceof Opcode::SizedBufferMustWriteSideEffect
) else (
buffer = false and
mustWrite = false and
result instanceof Opcode::IndirectMayWriteSideEffect
or
buffer = false and
mustWrite = true and
result instanceof Opcode::IndirectMustWriteSideEffect
or
buffer = true and mustWrite = false and result instanceof Opcode::BufferMayWriteSideEffect
or
buffer = true and mustWrite = true and result instanceof Opcode::BufferMustWriteSideEffect
)
)
}

View File

@@ -4,6 +4,7 @@ private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import semmle.code.cpp.ir.internal.CppType private import semmle.code.cpp.ir.internal.CppType
private import semmle.code.cpp.models.interfaces.SideEffect private import semmle.code.cpp.models.interfaces.SideEffect
private import InstructionTag private import InstructionTag
private import SideEffects
private import TranslatedElement private import TranslatedElement
private import TranslatedExpr private import TranslatedExpr
private import TranslatedFunction private import TranslatedFunction
@@ -424,12 +425,15 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi
} }
class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects { class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects {
TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() } TranslatedStructorCallSideEffects() {
getParent().(TranslatedStructorCall).hasQualifier() and
getASideEffectOpcode(expr, -1) instanceof WriteSideEffectOpcode
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) {
opcode instanceof Opcode::IndirectMayWriteSideEffect and
tag instanceof OnlyInstructionTag and tag instanceof OnlyInstructionTag and
t = getTypeForPRValue(expr.getTarget().getDeclaringType()) t = getTypeForPRValue(expr.getTarget().getDeclaringType()) and
opcode = getASideEffectOpcode(expr, -1).(WriteSideEffectOpcode)
} }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -460,9 +464,11 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
Call call; Call call;
Expr arg; Expr arg;
int index; int index;
boolean write; SideEffectOpcode sideEffectOpcode;
TranslatedSideEffect() { this = TTranslatedArgumentSideEffect(call, arg, index, write) } TranslatedSideEffect() {
this = TTranslatedArgumentSideEffect(call, arg, index, sideEffectOpcode)
}
override Locatable getAST() { result = arg } override Locatable getAST() { result = arg }
@@ -472,13 +478,13 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
int getArgumentIndex() { result = index } int getArgumentIndex() { result = index }
predicate isWrite() { write = true } predicate isWrite() { sideEffectOpcode instanceof WriteSideEffectOpcode }
override string toString() { override string toString() {
write = true and isWrite() and
result = "(write side effect for " + arg.toString() + ")" result = "(write side effect for " + arg.toString() + ")"
or or
write = false and not isWrite() and
result = "(read side effect for " + arg.toString() + ")" result = "(read side effect for " + arg.toString() + ")"
} }
@@ -489,29 +495,29 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
isWrite() and
hasSpecificWriteSideEffect(opcode) and
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
opcode = sideEffectOpcode and
( (
opcode instanceof BufferAccessOpcode and isWrite() and
type = getUnknownType() (
or opcode instanceof BufferAccessOpcode and
not opcode instanceof BufferAccessOpcode and type = getUnknownType()
exists(Type baseType | baseType = arg.getUnspecifiedType().(DerivedType).getBaseType() | or
if baseType instanceof VoidType not opcode instanceof BufferAccessOpcode and
then type = getUnknownType() exists(Type baseType | baseType = arg.getUnspecifiedType().(DerivedType).getBaseType() |
else type = getTypeForPRValueOrUnknown(baseType) if baseType instanceof VoidType
then type = getUnknownType()
else type = getTypeForPRValueOrUnknown(baseType)
)
or
index = -1 and
not arg.getUnspecifiedType() instanceof DerivedType and
type = getTypeForPRValueOrUnknown(arg.getUnspecifiedType())
) )
or or
index = -1 and not isWrite() and
not arg.getUnspecifiedType() instanceof DerivedType and type = getVoidType()
type = getTypeForPRValueOrUnknown(arg.getUnspecifiedType())
) )
or
not isWrite() and
hasSpecificReadSideEffect(opcode) and
tag = OnlyInstructionTag() and
type = getVoidType()
} }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -535,7 +541,7 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
override CppType getInstructionMemoryOperandType(InstructionTag tag, TypedOperandTag operandTag) { override CppType getInstructionMemoryOperandType(InstructionTag tag, TypedOperandTag operandTag) {
not isWrite() and not isWrite() and
if hasSpecificReadSideEffect(any(BufferAccessOpcode op)) if sideEffectOpcode instanceof BufferAccessOpcode
then then
result = getUnknownType() and result = getUnknownType() and
tag instanceof OnlyInstructionTag and tag instanceof OnlyInstructionTag and
@@ -557,56 +563,6 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
) )
} }
predicate hasSpecificWriteSideEffect(Opcode op) {
exists(boolean buffer, boolean mustWrite |
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
then
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(index, true, mustWrite) and
buffer = true and
(
mustWrite = false and op instanceof Opcode::SizedBufferMayWriteSideEffect
or
mustWrite = true and op instanceof Opcode::SizedBufferMustWriteSideEffect
)
else (
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(index, buffer, mustWrite) and
(
buffer = true and mustWrite = false and op instanceof Opcode::BufferMayWriteSideEffect
or
buffer = false and mustWrite = false and op instanceof Opcode::IndirectMayWriteSideEffect
or
buffer = true and mustWrite = true and op instanceof Opcode::BufferMustWriteSideEffect
or
buffer = false and mustWrite = true and op instanceof Opcode::IndirectMustWriteSideEffect
)
)
)
or
not call.getTarget() instanceof SideEffectFunction and
getArgumentIndex() != -1 and
op instanceof Opcode::BufferMayWriteSideEffect
or
not call.getTarget() instanceof SideEffectFunction and
getArgumentIndex() = -1 and
op instanceof Opcode::IndirectMayWriteSideEffect
}
predicate hasSpecificReadSideEffect(Opcode op) {
exists(boolean buffer |
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(index, buffer) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
then buffer = true and op instanceof Opcode::SizedBufferReadSideEffect
else (
buffer = true and op instanceof Opcode::BufferReadSideEffect
or
buffer = false and op instanceof Opcode::IndirectReadSideEffect
)
)
or
not call.getTarget() instanceof SideEffectFunction and
op instanceof Opcode::BufferReadSideEffect
}
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
result = getTranslatedCallInstruction(call) result = getTranslatedCallInstruction(call)

View File

@@ -12,6 +12,7 @@ private import TranslatedStmt
private import TranslatedExpr private import TranslatedExpr
private import IRConstruction private import IRConstruction
private import semmle.code.cpp.models.interfaces.SideEffect private import semmle.code.cpp.models.interfaces.SideEffect
private import SideEffects
/** /**
* Gets the "real" parent of `expr`. This predicate treats conversions as if * Gets the "real" parent of `expr`. This predicate treats conversions as if
@@ -41,7 +42,8 @@ IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
*/ */
predicate isIRConstant(Expr expr) { exists(expr.getValue()) } predicate isIRConstant(Expr expr) { exists(expr.getValue()) }
// Pulled out to work around QL-796 // Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.
private predicate isOrphan(Expr expr) { not exists(getRealParent(expr)) } private predicate isOrphan(Expr expr) { not exists(getRealParent(expr)) }
/** /**
@@ -635,46 +637,15 @@ newtype TTranslatedElement =
// The side effects of an allocation, i.e. `new`, `new[]` or `malloc` // The side effects of an allocation, i.e. `new`, `new[]` or `malloc`
TTranslatedAllocationSideEffects(AllocationExpr expr) { not ignoreExpr(expr) } or TTranslatedAllocationSideEffects(AllocationExpr expr) { not ignoreExpr(expr) } or
// A precise side effect of an argument to a `Call` // A precise side effect of an argument to a `Call`
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) { TTranslatedArgumentSideEffect(Call call, Expr expr, int n, SideEffectOpcode opcode) {
(
expr = call.getArgument(n).getFullyConverted()
or
expr = call.getQualifier().getFullyConverted() and
n = -1 and
// Exclude calls to static member functions. They don't modify the qualifier
not exists(MemberFunction func | func = call.getTarget() and func.isStatic())
) and
(
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(n, _) and
isWrite = false
or
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(n, _, _) and
isWrite = true
or
not call.getTarget() instanceof SideEffectFunction and
exists(Type t | t = expr.getUnspecifiedType() |
t instanceof ArrayType or
t instanceof PointerType or
t instanceof ReferenceType
) and
(
isWrite = true and
not call.getTarget().getParameter(n).getType().isDeeplyConstBelow()
or
isWrite = false
)
or
not call.getTarget() instanceof SideEffectFunction and
n = -1 and
(
isWrite = true and
not call.getTarget() instanceof ConstMemberFunction
or
isWrite = false
)
) and
not ignoreExpr(expr) and not ignoreExpr(expr) and
not ignoreExpr(call) not ignoreExpr(call) and
(
n >= 0 and expr = call.getArgument(n).getFullyConverted()
or
n = -1 and expr = call.getQualifier().getFullyConverted()
) and
opcode = getASideEffectOpcode(call, n)
} }
/** /**

View File

@@ -13,23 +13,25 @@ private class UniqueOrSharedPtr extends Class, PointerWrapper {
or or
result.getClassAndName(["operator->", "get"]) = this result.getClassAndName(["operator->", "get"]) = this
} }
override predicate pointsToConst() { this.getTemplateArgument(0).(Type).isConst() }
} }
/** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */ /** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */
private class PointerWrapperDataFlow extends DataFlowFunction { private class PointerWrapperFlow extends TaintFunction, DataFlowFunction {
PointerWrapperDataFlow() { PointerWrapperFlow() {
this = any(PointerWrapper wrapper).getAnUnwrapperFunction() and this = any(PointerWrapper wrapper).getAnUnwrapperFunction() and
not this.getUnspecifiedType() instanceof ReferenceType not this.getUnspecifiedType() instanceof ReferenceType
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and output.isReturnValue()
or
input.isQualifierObject() and output.isReturnValueDeref()
or
input.isReturnValueDeref() and input.isReturnValueDeref() and
output.isQualifierObject() output.isQualifierObject()
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and output.isReturnValue()
}
} }
/** /**

View File

@@ -11,4 +11,7 @@ abstract class PointerWrapper extends Class {
* that return a reference to the pointed-to object. * that return a reference to the pointed-to object.
*/ */
abstract MemberFunction getAnUnwrapperFunction(); abstract MemberFunction getAnUnwrapperFunction();
/** Holds if the type of the data that is pointed to by this pointer wrapper is `const`. */
abstract predicate pointsToConst();
} }

View File

@@ -5,6 +5,8 @@
import cpp import cpp
import semmle.code.cpp.controlflow.Dominance import semmle.code.cpp.controlflow.Dominance
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
/** /**
* Holds if the value of `use` is guarded using `abs`. * Holds if the value of `use` is guarded using `abs`.
@@ -94,9 +96,15 @@ predicate guardedGreater(Operation e, Expr use) {
VariableAccess varUse(LocalScopeVariable v) { result = v.getAnAccess() } VariableAccess varUse(LocalScopeVariable v) { result = v.getAnAccess() }
/** /**
* Holds if `e` is not guarded against overflow by `use`. * Holds if `e` potentially overflows and `use` is an operand of `e` that is not guarded.
*/ */
predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) { predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
(
convertedExprMightOverflowPositively(e)
or
// Ensure that the predicate holds when range analysis cannot determine an upper bound
upperBound(e.getFullyConverted()) = exprMaxVal(e.getFullyConverted())
) and
use = e.getAnOperand() and use = e.getAnOperand() and
exists(LocalScopeVariable v | use.getTarget() = v | exists(LocalScopeVariable v | use.getTarget() = v |
// overflow possible if large // overflow possible if large
@@ -115,9 +123,15 @@ predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
} }
/** /**
* Holds if `e` is not guarded against underflow by `use`. * Holds if `e` potentially underflows and `use` is an operand of `e` that is not guarded.
*/ */
predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) { predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) {
(
convertedExprMightOverflowNegatively(e)
or
// Ensure that the predicate holds when range analysis cannot determine a lower bound
lowerBound(e.getFullyConverted()) = exprMinVal(e.getFullyConverted())
) and
use = e.getAnOperand() and use = e.getAnOperand() and
exists(LocalScopeVariable v | use.getTarget() = v | exists(LocalScopeVariable v | use.getTarget() = v |
// underflow possible if use is left operand and small // underflow possible if use is left operand and small

View File

@@ -0,0 +1,4 @@
| test.c:15:6:15:16 | ... + ... | this expression needs your attention |
| test.c:17:17:17:27 | ... + ... | this expression needs your attention |
| test.c:22:10:22:15 | ... > ... | this expression needs your attention |
| test.c:26:10:26:15 | ... > ... | this expression needs your attention |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementAfterRefactoringTheCode.ql

View File

@@ -0,0 +1,2 @@
| test.c:8:6:8:51 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |
| test.c:10:6:10:30 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementWhenUsingBitOperations.ql

View File

@@ -0,0 +1,32 @@
int tmpFunction(){
return 5;
}
void workFunction_0(char *s) {
int intSize;
char buf[80];
if(intSize>0 && intSize<80 && memset(buf,0,intSize)) return; // GOOD
if(intSize>0 & intSize<80 & memset(buf,0,intSize)) return; // BAD
if(intSize>0 && tmpFunction()) return;
if(intSize<0 & tmpFunction()) return; // BAD
}
void workFunction_1(char *s) {
int intA,intB;
if(intA + intB) return; // BAD
if(intA + intB>4) return; // GOOD
if(intA>0 && (intA + intB)) return; // BAD
while(intA>0)
{
if(intB - intA<10) break;
intA--;
}while(intA>0); // BAD
for(intA=100; intA>0; intA--)
{
if(intB - intA<10) break;
}while(intA>0); // BAD
while(intA>0)
{
if(intB - intA<10) break;
intA--;
} // GOOD
}

View File

@@ -1,9 +1,9 @@
| test.c:42:3:42:24 | ... = ... | potential unsafe or redundant assignment. | | test.c:54:3:54:24 | ... = ... | potential unsafe or redundant assignment. |
| test.c:43:3:43:40 | ... = ... | potential unsafe or redundant assignment. | | test.c:55:3:55:40 | ... = ... | potential unsafe or redundant assignment. |
| test.c:44:3:44:40 | ... = ... | potential unsafe or redundant assignment. | | test.c:56:3:56:44 | ... = ... | potential unsafe or redundant assignment. |
| test.c:45:3:45:44 | ... = ... | potential unsafe or redundant assignment. | | test.c:57:3:57:44 | ... = ... | potential unsafe or redundant assignment. |
| test.c:46:3:46:44 | ... = ... | potential unsafe or redundant assignment. | | test.c:58:3:58:48 | ... = ... | potential unsafe or redundant assignment. |
| test.c:47:3:47:48 | ... = ... | potential unsafe or redundant assignment. | | test.c:59:3:59:48 | ... = ... | potential unsafe or redundant assignment. |
| test.c:48:3:48:48 | ... = ... | potential unsafe or redundant assignment. | | test.c:60:3:60:52 | ... = ... | potential unsafe or redundant assignment. |
| test.c:49:3:49:50 | ... = ... | potential unsafe or redundant assignment. | | test.c:61:3:61:50 | ... = ... | potential unsafe or redundant assignment. |
| test.c:50:3:50:50 | ... = ... | potential unsafe or redundant assignment. | | test.c:62:3:62:54 | ... = ... | potential unsafe or redundant assignment. |

View File

@@ -1,3 +1,5 @@
| test.c:4:3:4:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | | test.c:8:3:8:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
| test.c:11:3:11:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | | test.c:9:3:9:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
| test.c:19:3:19:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | | test.c:17:3:17:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
| test.c:18:3:18:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
| test.c:46:3:46:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |

View File

@@ -0,0 +1,5 @@
| test.cpp:10:8:10:10 | - ... | this expression needs attention |
| test.cpp:12:3:12:6 | ... ++ | this expression needs attention |
| test.cpp:13:3:13:6 | ++ ... | this expression needs attention |
| test.cpp:14:6:14:21 | ... = ... | this expression needs attention |
| test.cpp:16:6:16:21 | ... = ... | this expression needs attention |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-783/OperatorPrecedenceLogicErrorWhenUseBoolType.ql

View File

@@ -1,70 +1,84 @@
void workFunction_0(char *s) { char * strncat(char*, const char*, unsigned);
unsigned strlen(const char*);
void* malloc(unsigned);
void strncat_test1(char *s) {
char buf[80]; char buf[80];
strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD strncat(buf, s, sizeof(buf) - strlen(buf) - 1); // GOOD
strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD strncat(buf, s, sizeof(buf) - strlen(buf)); // BAD
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED] strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD
} }
void workFunction_1(char *s) {
#define MAX_SIZE 80 #define MAX_SIZE 80
void strncat_test2(char *s) {
char buf[MAX_SIZE]; char buf[MAX_SIZE];
strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD strncat(buf, s, MAX_SIZE - strlen(buf) - 1); // GOOD
strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD strncat(buf, s, MAX_SIZE - strlen(buf)); // BAD
strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD [NOT DETECTED] strncat(buf, "fix", MAX_SIZE - strlen(buf)); // BAD
} }
void workFunction_2_0(char *s) {
char * buf; void strncat_test3(char *s) {
int len=80; int len = 80;
buf = (char *) malloc(len); char* buf = (char *) malloc(len);
strncat(buf, s, len-strlen(buf)-1); // GOOD strncat(buf, s, len - strlen(buf) - 1); // GOOD
strncat(buf, s, len-strlen(buf)); // BAD strncat(buf, s, len - strlen(buf)); // BAD [NOT DETECTED]
strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED] strncat(buf, "fix", len - strlen(buf)); // BAD [NOT DETECTED]
} }
void workFunction_2_1(char *s) {
char * buf; void strncat_test4(char *s) {
int len=80; int len = 80;
buf = (char *) malloc(len+1); char* buf = (char *) malloc(len + 1);
strncat(buf, s, len-strlen(buf)-1); // GOOD strncat(buf, s, len - strlen(buf) - 1); // GOOD
strncat(buf, s, len-strlen(buf)); // GOOD strncat(buf, s, len - strlen(buf)); // GOOD
} }
struct buffers struct buffers
{ {
unsigned char buff1[50]; unsigned char array[50];
unsigned char *buff2; unsigned char *pointer;
} globalBuff1,*globalBuff2,globalBuff1_c,*globalBuff2_c; } globalBuff1,*globalBuff2,globalBuff1_c,*globalBuff2_c;
void strncat_test5(char* s, struct buffers* buffers) {
unsigned len_array = strlen(buffers->array);
unsigned max_size = sizeof(buffers->array);
unsigned free_size = max_size - len_array;
strncat(buffers->array, s, free_size); // BAD
}
void badFunc0(){ void strlen_test1(){
unsigned char buff1[12]; unsigned char buff1[12];
struct buffers buffAll; struct buffers buffAll;
struct buffers * buffAll1; struct buffers * buffAll1;
buff1[strlen(buff1)]=0; // BAD buff1[strlen(buff1)]=0; // BAD
buffAll.buff1[strlen(buffAll.buff1)]=0; // BAD buffAll.array[strlen(buffAll.array)]=0; // BAD
buffAll.buff2[strlen(buffAll.buff2)]=0; // BAD buffAll.pointer[strlen(buffAll.pointer)]=0; // BAD
buffAll1->buff1[strlen(buffAll1->buff1)]=0; // BAD buffAll1->array[strlen(buffAll1->array)]=0; // BAD
buffAll1->buff2[strlen(buffAll1->buff2)]=0; // BAD buffAll1->pointer[strlen(buffAll1->pointer)]=0; // BAD
globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; // BAD globalBuff1.array[strlen(globalBuff1.array)]=0; // BAD
globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; // BAD globalBuff1.pointer[strlen(globalBuff1.pointer)]=0; // BAD
globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; // BAD globalBuff2->array[strlen(globalBuff2->array)]=0; // BAD
globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; // BAD globalBuff2->pointer[strlen(globalBuff2->pointer)]=0; // BAD
} }
void noBadFunc0(){
void strlen_test2(){
unsigned char buff1[12],buff1_c[12]; unsigned char buff1[12],buff1_c[12];
struct buffers buffAll,buffAll_c; struct buffers buffAll,buffAll_c;
struct buffers * buffAll1,*buffAll1_c; struct buffers * buffAll1,*buffAll1_c;
buff1[strlen(buff1_c)]=0; // GOOD buff1[strlen(buff1_c)]=0; // GOOD
buffAll.buff1[strlen(buffAll_c.buff1)]=0; // GOOD buffAll.array[strlen(buffAll_c.array)]=0; // GOOD
buffAll.buff2[strlen(buffAll.buff1)]=0; // GOOD buffAll.pointer[strlen(buffAll.array)]=0; // GOOD
buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; // GOOD buffAll1->array[strlen(buffAll1_c->array)]=0; // GOOD
buffAll1->buff2[strlen(buffAll1->buff1)]=0; // GOOD buffAll1->pointer[strlen(buffAll1->array)]=0; // GOOD
globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; // GOOD globalBuff1.array[strlen(globalBuff1_c.array)]=0; // GOOD
globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; // GOOD globalBuff1.pointer[strlen(globalBuff1.array)]=0; // GOOD
globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; // GOOD globalBuff2->array[strlen(globalBuff2_c->array)]=0; // GOOD
globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; // GOOD globalBuff2->pointer[strlen(globalBuff2->array)]=0; // GOOD
} }
void goodFunc0(){
void strlen_test3(){
unsigned char buffer[12]; unsigned char buffer[12];
int i; int i;
for(i = 0; i < 6; i++) for(i = 0; i < 6; i++)

View File

@@ -0,0 +1,26 @@
int tmpFunc()
{
return 12;
}
void testFunction()
{
int i1,i2,i3;
bool b1,b2,b3;
char c1,c2,c3;
b1 = -b2; //BAD
b1 = !b2; //GOOD
b1++; //BAD
++b1; //BAD
if(i1=tmpFunc()!=i2) //BAD
return;
if(i1=tmpFunc()!=11) //BAD
return;
if((i1=tmpFunc())!=i2) //GOOD
return;
if((i1=tmpFunc())!=11) //GOOD
return;
if(i1=tmpFunc()!=1) //GOOD
return;
if(i1=tmpFunc()==b1) //GOOD
return;
}

View File

@@ -26,6 +26,7 @@ unreachableNodeCCtx
localCallNodes localCallNodes
postIsNotPre postIsNotPre
postHasUniquePre postHasUniquePre
| test.cpp:373:5:373:20 | Store | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate uniquePostUpdate
postIsInSameCallable postIsInSameCallable
reverseRead reverseRead
@@ -82,4 +83,5 @@ postWithInFlow
| test.cpp:125:3:125:11 | Chi | PostUpdateNode should not be the target of local flow. | | test.cpp:125:3:125:11 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:359:5:359:20 | Chi | PostUpdateNode should not be the target of local flow. | | test.cpp:359:5:359:20 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:373:5:373:20 | Chi | PostUpdateNode should not be the target of local flow. | | test.cpp:373:5:373:20 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:373:5:373:20 | Store | PostUpdateNode should not be the target of local flow. |
| test.cpp:465:3:465:15 | Chi | PostUpdateNode should not be the target of local flow. | | test.cpp:465:3:465:15 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -20,7 +20,9 @@ unreachableNodeCCtx
localCallNodes localCallNodes
postIsNotPre postIsNotPre
postHasUniquePre postHasUniquePre
| D.cpp:57:5:57:42 | Store | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. | | simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:83:9:83:28 | Store | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. | | simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate uniquePostUpdate
postIsInSameCallable postIsInSameCallable
@@ -54,6 +56,7 @@ postWithInFlow
| D.cpp:49:15:49:24 | Chi | PostUpdateNode should not be the target of local flow. | | D.cpp:49:15:49:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:56:15:56:24 | Chi | PostUpdateNode should not be the target of local flow. | | D.cpp:56:15:56:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:57:5:57:42 | Chi | PostUpdateNode should not be the target of local flow. | | D.cpp:57:5:57:42 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:57:5:57:42 | Store | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:9:3:9:22 | Chi | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:9:3:9:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:13:3:13:21 | Chi | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:13:3:13:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:17:3:17:21 | Chi | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:17:3:17:21 | Chi | PostUpdateNode should not be the target of local flow. |
@@ -150,6 +153,7 @@ postWithInFlow
| simple.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. | | simple.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should not be the target of local flow. | | simple.cpp:65:5:65:22 | Store | PostUpdateNode should not be the target of local flow. |
| simple.cpp:83:9:83:28 | Chi | PostUpdateNode should not be the target of local flow. | | simple.cpp:83:9:83:28 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:83:9:83:28 | Store | PostUpdateNode should not be the target of local flow. |
| simple.cpp:92:5:92:22 | Store | PostUpdateNode should not be the target of local flow. | | simple.cpp:92:5:92:22 | Store | PostUpdateNode should not be the target of local flow. |
| struct_init.c:20:20:20:29 | Chi | PostUpdateNode should not be the target of local flow. | | struct_init.c:20:20:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:20:34:20:34 | Chi | PostUpdateNode should not be the target of local flow. | | struct_init.c:20:34:20:34 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -228,8 +228,8 @@ edges
| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] | | simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] | | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i | | simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | this indirection [f1] | | simple.cpp:83:9:83:28 | Store [f1] | simple.cpp:84:14:84:20 | this indirection [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Chi [f1] | | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store [f1] |
| simple.cpp:84:14:84:20 | this indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 | | simple.cpp:84:14:84:20 | this indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] | | simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] | | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
@@ -494,7 +494,7 @@ nodes
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input | | simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] | | simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i | | simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] | | simple.cpp:83:9:83:28 | Store [f1] | semmle.label | Store [f1] |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input | | simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 | | simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:84:14:84:20 | this indirection [f1] | semmle.label | this indirection [f1] | | simple.cpp:84:14:84:20 | this indirection [f1] | semmle.label | this indirection [f1] |

View File

@@ -19,15 +19,19 @@ class IRPartialDefNode extends IRNode {
override string toString() { result = n.asPartialDefinition().toString() } override string toString() { result = n.asPartialDefinition().toString() }
} }
from Node node, AST::Node astNode, IR::Node irNode, string msg from Node node, string msg
where where
node.asIR() = irNode and exists(IR::Node irNode, Expr partial |
exists(irNode.asPartialDefinition()) and node.asIR() = irNode and
not exists(AST::Node otherNode | otherNode.asPartialDefinition() = irNode.asPartialDefinition()) and partial = irNode.asPartialDefinition() and
not exists(AST::Node otherNode | otherNode.asPartialDefinition() = partial)
) and
msg = "IR only" msg = "IR only"
or or
node.asAST() = astNode and exists(AST::Node astNode, Expr partial |
exists(astNode.asPartialDefinition()) and node.asAST() = astNode and
not exists(IR::Node otherNode | otherNode.asPartialDefinition() = astNode.asPartialDefinition()) and partial = astNode.asPartialDefinition() and
not exists(IR::Node otherNode | otherNode.asPartialDefinition() = partial)
) and
msg = "AST only" msg = "AST only"
select node, msg select node, msg

View File

@@ -3223,49 +3223,63 @@
| smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:12:11:12:11 | p | | | smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:12:11:12:11 | p | |
| smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:13:10:13:10 | p | | | smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:13:10:13:10 | p | |
| smart_pointer.cpp:11:52:11:57 | call to source | smart_pointer.cpp:11:30:11:50 | call to make_shared | TAINT | | smart_pointer.cpp:11:52:11:57 | call to source | smart_pointer.cpp:11:30:11:50 | call to make_shared | TAINT |
| smart_pointer.cpp:12:11:12:11 | p | smart_pointer.cpp:12:10:12:10 | call to operator* | TAINT | | smart_pointer.cpp:12:11:12:11 | p | smart_pointer.cpp:12:10:12:10 | call to operator* | |
| smart_pointer.cpp:12:11:12:11 | ref arg p | smart_pointer.cpp:13:10:13:10 | p | | | smart_pointer.cpp:12:11:12:11 | ref arg p | smart_pointer.cpp:13:10:13:10 | p | |
| smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:18:11:18:11 | p | | | smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:18:11:18:11 | p | |
| smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:19:10:19:10 | p | | | smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:19:10:19:10 | p | |
| smart_pointer.cpp:18:10:18:10 | ref arg call to operator* | smart_pointer.cpp:18:11:18:11 | p [inner post update] | |
| smart_pointer.cpp:18:10:18:10 | ref arg call to operator* | smart_pointer.cpp:19:10:19:10 | p | |
| smart_pointer.cpp:18:11:18:11 | p | smart_pointer.cpp:18:10:18:10 | call to operator* | TAINT | | smart_pointer.cpp:18:11:18:11 | p | smart_pointer.cpp:18:10:18:10 | call to operator* | TAINT |
| smart_pointer.cpp:18:11:18:11 | ref arg p | smart_pointer.cpp:18:11:18:11 | p [inner post update] | |
| smart_pointer.cpp:18:11:18:11 | ref arg p | smart_pointer.cpp:19:10:19:10 | p | | | smart_pointer.cpp:18:11:18:11 | ref arg p | smart_pointer.cpp:19:10:19:10 | p | |
| smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:24:11:24:11 | p | | | smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:24:11:24:11 | p | |
| smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:25:10:25:10 | p | | | smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:25:10:25:10 | p | |
| smart_pointer.cpp:23:52:23:57 | call to source | smart_pointer.cpp:23:30:23:50 | call to make_unique | TAINT | | smart_pointer.cpp:23:52:23:57 | call to source | smart_pointer.cpp:23:30:23:50 | call to make_unique | TAINT |
| smart_pointer.cpp:24:11:24:11 | p | smart_pointer.cpp:24:10:24:10 | call to operator* | TAINT | | smart_pointer.cpp:24:11:24:11 | p | smart_pointer.cpp:24:10:24:10 | call to operator* | |
| smart_pointer.cpp:24:11:24:11 | ref arg p | smart_pointer.cpp:25:10:25:10 | p | | | smart_pointer.cpp:24:11:24:11 | ref arg p | smart_pointer.cpp:25:10:25:10 | p | |
| smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:30:11:30:11 | p | | | smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:30:11:30:11 | p | |
| smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:31:10:31:10 | p | | | smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:31:10:31:10 | p | |
| smart_pointer.cpp:30:10:30:10 | ref arg call to operator* | smart_pointer.cpp:30:11:30:11 | p [inner post update] | |
| smart_pointer.cpp:30:10:30:10 | ref arg call to operator* | smart_pointer.cpp:31:10:31:10 | p | |
| smart_pointer.cpp:30:11:30:11 | p | smart_pointer.cpp:30:10:30:10 | call to operator* | TAINT | | smart_pointer.cpp:30:11:30:11 | p | smart_pointer.cpp:30:10:30:10 | call to operator* | TAINT |
| smart_pointer.cpp:30:11:30:11 | ref arg p | smart_pointer.cpp:30:11:30:11 | p [inner post update] | |
| smart_pointer.cpp:30:11:30:11 | ref arg p | smart_pointer.cpp:31:10:31:10 | p | | | smart_pointer.cpp:30:11:30:11 | ref arg p | smart_pointer.cpp:31:10:31:10 | p | |
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:37:6:37:6 | p | | | smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:37:6:37:6 | p | |
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:38:10:38:10 | p | | | smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:38:10:38:10 | p | |
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:39:11:39:11 | p | | | smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:39:11:39:11 | p | |
| smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | smart_pointer.cpp:37:6:37:6 | p [inner post update] | |
| smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | smart_pointer.cpp:38:10:38:10 | p | |
| smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | smart_pointer.cpp:39:11:39:11 | p | |
| smart_pointer.cpp:37:5:37:17 | ... = ... | smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | | | smart_pointer.cpp:37:5:37:17 | ... = ... | smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | |
| smart_pointer.cpp:37:6:37:6 | p | smart_pointer.cpp:37:5:37:5 | call to operator* | TAINT | | smart_pointer.cpp:37:6:37:6 | p | smart_pointer.cpp:37:5:37:5 | call to operator* | |
| smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:37:6:37:6 | p [inner post update] | |
| smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:38:10:38:10 | p | | | smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:38:10:38:10 | p | |
| smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | | | smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | |
| smart_pointer.cpp:37:10:37:15 | call to source | smart_pointer.cpp:37:5:37:17 | ... = ... | | | smart_pointer.cpp:37:10:37:15 | call to source | smart_pointer.cpp:37:5:37:17 | ... = ... | |
| smart_pointer.cpp:38:10:38:10 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | | | smart_pointer.cpp:38:10:38:10 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | |
| smart_pointer.cpp:39:11:39:11 | p | smart_pointer.cpp:39:10:39:10 | call to operator* | TAINT | | smart_pointer.cpp:39:11:39:11 | p | smart_pointer.cpp:39:10:39:10 | call to operator* | |
| smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:45:6:45:6 | p | | | smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:45:6:45:6 | p | |
| smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:46:10:46:10 | p | | | smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:46:10:46:10 | p | |
| smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:47:11:47:11 | p | | | smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:47:11:47:11 | p | |
| smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | smart_pointer.cpp:45:6:45:6 | p [inner post update] | |
| smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | smart_pointer.cpp:46:10:46:10 | p | |
| smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | smart_pointer.cpp:47:11:47:11 | p | |
| smart_pointer.cpp:45:5:45:17 | ... = ... | smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | | | smart_pointer.cpp:45:5:45:17 | ... = ... | smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | |
| smart_pointer.cpp:45:6:45:6 | p | smart_pointer.cpp:45:5:45:5 | call to operator* | TAINT | | smart_pointer.cpp:45:6:45:6 | p | smart_pointer.cpp:45:5:45:5 | call to operator* | |
| smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:45:6:45:6 | p [inner post update] | |
| smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:46:10:46:10 | p | | | smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:46:10:46:10 | p | |
| smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | | | smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | |
| smart_pointer.cpp:45:10:45:15 | call to source | smart_pointer.cpp:45:5:45:17 | ... = ... | | | smart_pointer.cpp:45:10:45:15 | call to source | smart_pointer.cpp:45:5:45:17 | ... = ... | |
| smart_pointer.cpp:46:10:46:10 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | | | smart_pointer.cpp:46:10:46:10 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | |
| smart_pointer.cpp:47:11:47:11 | p | smart_pointer.cpp:47:10:47:10 | call to operator* | TAINT | | smart_pointer.cpp:47:11:47:11 | p | smart_pointer.cpp:47:10:47:10 | call to operator* | |
| smart_pointer.cpp:51:30:51:50 | call to make_shared | smart_pointer.cpp:52:10:52:10 | p | | | smart_pointer.cpp:51:30:51:50 | call to make_shared | smart_pointer.cpp:52:10:52:10 | p | |
| smart_pointer.cpp:51:52:51:57 | call to source | smart_pointer.cpp:51:30:51:50 | call to make_shared | TAINT | | smart_pointer.cpp:51:52:51:57 | call to source | smart_pointer.cpp:51:30:51:50 | call to make_shared | TAINT |
| smart_pointer.cpp:52:10:52:10 | p | smart_pointer.cpp:52:12:52:14 | call to get | | | smart_pointer.cpp:52:10:52:10 | p | smart_pointer.cpp:52:12:52:14 | call to get | |
| smart_pointer.cpp:52:12:52:14 | ref arg call to get | smart_pointer.cpp:52:10:52:10 | ref arg p | | | smart_pointer.cpp:52:12:52:14 | ref arg call to get | smart_pointer.cpp:52:10:52:10 | ref arg p | TAINT |
| smart_pointer.cpp:56:30:56:50 | call to make_unique | smart_pointer.cpp:57:10:57:10 | p | | | smart_pointer.cpp:56:30:56:50 | call to make_unique | smart_pointer.cpp:57:10:57:10 | p | |
| smart_pointer.cpp:56:52:56:57 | call to source | smart_pointer.cpp:56:30:56:50 | call to make_unique | TAINT | | smart_pointer.cpp:56:52:56:57 | call to source | smart_pointer.cpp:56:30:56:50 | call to make_unique | TAINT |
| smart_pointer.cpp:57:10:57:10 | p | smart_pointer.cpp:57:12:57:14 | call to get | | | smart_pointer.cpp:57:10:57:10 | p | smart_pointer.cpp:57:12:57:14 | call to get | |
| smart_pointer.cpp:57:12:57:14 | ref arg call to get | smart_pointer.cpp:57:10:57:10 | ref arg p | | | smart_pointer.cpp:57:12:57:14 | ref arg call to get | smart_pointer.cpp:57:10:57:10 | ref arg p | TAINT |
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:66:10:66:10 | p | | | smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:66:10:66:10 | p | |
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:67:10:67:10 | p | | | smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:67:10:67:10 | p | |
| smart_pointer.cpp:65:48:65:53 | call to source | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT | | smart_pointer.cpp:65:48:65:53 | call to source | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
@@ -3273,46 +3287,160 @@
| smart_pointer.cpp:66:10:66:10 | p | smart_pointer.cpp:66:11:66:11 | call to operator-> | | | smart_pointer.cpp:66:10:66:10 | p | smart_pointer.cpp:66:11:66:11 | call to operator-> | |
| smart_pointer.cpp:66:10:66:10 | ref arg p | smart_pointer.cpp:67:10:67:10 | p | | | smart_pointer.cpp:66:10:66:10 | ref arg p | smart_pointer.cpp:67:10:67:10 | p | |
| smart_pointer.cpp:67:10:67:10 | p | smart_pointer.cpp:67:11:67:11 | call to operator-> | | | smart_pointer.cpp:67:10:67:10 | p | smart_pointer.cpp:67:11:67:11 | call to operator-> | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:77:3:77:3 | p | | | smart_pointer.cpp:70:37:70:39 | ptr | smart_pointer.cpp:70:37:70:39 | ptr | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:78:8:78:8 | p | | | smart_pointer.cpp:70:37:70:39 | ptr | smart_pointer.cpp:71:4:71:6 | ptr | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:79:8:79:8 | p | | | smart_pointer.cpp:71:3:71:3 | call to operator* [post update] | smart_pointer.cpp:70:37:70:39 | ptr | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:81:3:81:3 | q | | | smart_pointer.cpp:71:3:71:3 | call to operator* [post update] | smart_pointer.cpp:71:4:71:6 | ptr [inner post update] | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:82:8:82:8 | q | | | smart_pointer.cpp:71:3:71:17 | ... = ... | smart_pointer.cpp:71:3:71:3 | call to operator* [post update] | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:83:8:83:8 | q | | | smart_pointer.cpp:71:4:71:6 | ptr | smart_pointer.cpp:71:3:71:3 | call to operator* | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:84:8:84:8 | q | | | smart_pointer.cpp:71:4:71:6 | ref arg ptr | smart_pointer.cpp:70:37:70:39 | ptr | |
| smart_pointer.cpp:77:3:77:3 | p | smart_pointer.cpp:77:4:77:4 | call to operator-> | | | smart_pointer.cpp:71:4:71:6 | ref arg ptr | smart_pointer.cpp:71:4:71:6 | ptr [inner post update] | |
| smart_pointer.cpp:77:3:77:3 | ref arg p | smart_pointer.cpp:78:8:78:8 | p | | | smart_pointer.cpp:71:10:71:15 | call to source | smart_pointer.cpp:71:3:71:17 | ... = ... | |
| smart_pointer.cpp:77:3:77:3 | ref arg p | smart_pointer.cpp:79:8:79:8 | p | | | smart_pointer.cpp:75:26:75:33 | call to shared_ptr | smart_pointer.cpp:76:13:76:13 | p | |
| smart_pointer.cpp:77:3:77:17 | ... = ... | smart_pointer.cpp:77:6:77:6 | x [post update] | | | smart_pointer.cpp:75:26:75:33 | call to shared_ptr | smart_pointer.cpp:77:9:77:9 | p | |
| smart_pointer.cpp:77:3:77:17 | ... = ... | smart_pointer.cpp:78:11:78:11 | x | | | smart_pointer.cpp:76:13:76:13 | p | smart_pointer.cpp:76:13:76:13 | call to shared_ptr | |
| smart_pointer.cpp:77:4:77:4 | call to operator-> [post update] | smart_pointer.cpp:77:3:77:3 | ref arg p | | | smart_pointer.cpp:76:13:76:13 | ref arg call to shared_ptr | smart_pointer.cpp:76:13:76:13 | p [inner post update] | |
| smart_pointer.cpp:77:10:77:15 | call to source | smart_pointer.cpp:77:3:77:17 | ... = ... | | | smart_pointer.cpp:76:13:76:13 | ref arg call to shared_ptr | smart_pointer.cpp:77:9:77:9 | p | |
| smart_pointer.cpp:78:8:78:8 | p | smart_pointer.cpp:78:9:78:9 | call to operator-> | | | smart_pointer.cpp:76:13:76:13 | ref arg p | smart_pointer.cpp:76:13:76:13 | p [inner post update] | |
| smart_pointer.cpp:78:8:78:8 | ref arg p | smart_pointer.cpp:79:8:79:8 | p | | | smart_pointer.cpp:76:13:76:13 | ref arg p | smart_pointer.cpp:77:9:77:9 | p | |
| smart_pointer.cpp:79:8:79:8 | p | smart_pointer.cpp:79:9:79:9 | call to operator-> | | | smart_pointer.cpp:77:9:77:9 | p | smart_pointer.cpp:77:8:77:8 | call to operator* | |
| smart_pointer.cpp:81:3:81:3 | q | smart_pointer.cpp:81:4:81:4 | call to operator-> | | | smart_pointer.cpp:86:45:86:45 | p | smart_pointer.cpp:86:45:86:45 | p | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:82:8:82:8 | q | | | smart_pointer.cpp:86:45:86:45 | p | smart_pointer.cpp:87:3:87:3 | p | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:83:8:83:8 | q | | | smart_pointer.cpp:86:45:86:45 | p | smart_pointer.cpp:88:8:88:8 | p | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | | | smart_pointer.cpp:86:45:86:45 | p | smart_pointer.cpp:89:8:89:8 | p | |
| smart_pointer.cpp:81:3:81:20 | ... = ... | smart_pointer.cpp:81:9:81:9 | x [post update] | | | smart_pointer.cpp:86:67:86:67 | q | smart_pointer.cpp:86:67:86:67 | q | |
| smart_pointer.cpp:81:3:81:20 | ... = ... | smart_pointer.cpp:82:14:82:14 | x | | | smart_pointer.cpp:86:67:86:67 | q | smart_pointer.cpp:91:3:91:3 | q | |
| smart_pointer.cpp:81:4:81:4 | call to operator-> [post update] | smart_pointer.cpp:81:3:81:3 | ref arg q | | | smart_pointer.cpp:86:67:86:67 | q | smart_pointer.cpp:92:8:92:8 | q | |
| smart_pointer.cpp:81:13:81:18 | call to source | smart_pointer.cpp:81:3:81:20 | ... = ... | | | smart_pointer.cpp:86:67:86:67 | q | smart_pointer.cpp:93:8:93:8 | q | |
| smart_pointer.cpp:82:8:82:8 | q | smart_pointer.cpp:82:9:82:9 | call to operator-> | | | smart_pointer.cpp:86:67:86:67 | q | smart_pointer.cpp:94:8:94:8 | q | |
| smart_pointer.cpp:82:8:82:8 | ref arg q | smart_pointer.cpp:83:8:83:8 | q | | | smart_pointer.cpp:87:3:87:3 | p | smart_pointer.cpp:87:4:87:4 | call to operator-> | |
| smart_pointer.cpp:82:8:82:8 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | | | smart_pointer.cpp:87:3:87:3 | ref arg p | smart_pointer.cpp:86:45:86:45 | p | |
| smart_pointer.cpp:83:8:83:8 | q | smart_pointer.cpp:83:9:83:9 | call to operator-> | | | smart_pointer.cpp:87:3:87:3 | ref arg p | smart_pointer.cpp:88:8:88:8 | p | |
| smart_pointer.cpp:83:8:83:8 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | | | smart_pointer.cpp:87:3:87:3 | ref arg p | smart_pointer.cpp:89:8:89:8 | p | |
| smart_pointer.cpp:84:8:84:8 | q | smart_pointer.cpp:84:9:84:9 | call to operator-> | | | smart_pointer.cpp:87:3:87:17 | ... = ... | smart_pointer.cpp:87:6:87:6 | x [post update] | |
| smart_pointer.cpp:87:17:87:18 | pa | smart_pointer.cpp:88:5:88:6 | pa | | | smart_pointer.cpp:87:3:87:17 | ... = ... | smart_pointer.cpp:88:11:88:11 | x | |
| smart_pointer.cpp:88:5:88:20 | ... = ... | smart_pointer.cpp:88:9:88:9 | x [post update] | | | smart_pointer.cpp:87:4:87:4 | call to operator-> [post update] | smart_pointer.cpp:87:3:87:3 | ref arg p | TAINT |
| smart_pointer.cpp:88:13:88:18 | call to source | smart_pointer.cpp:88:5:88:20 | ... = ... | | | smart_pointer.cpp:87:10:87:15 | call to source | smart_pointer.cpp:87:3:87:17 | ... = ... | |
| smart_pointer.cpp:92:25:92:50 | call to unique_ptr | smart_pointer.cpp:93:11:93:11 | p | | | smart_pointer.cpp:88:8:88:8 | p | smart_pointer.cpp:88:9:88:9 | call to operator-> | |
| smart_pointer.cpp:92:25:92:50 | call to unique_ptr | smart_pointer.cpp:94:8:94:8 | p | | | smart_pointer.cpp:88:8:88:8 | ref arg p | smart_pointer.cpp:86:45:86:45 | p | |
| smart_pointer.cpp:93:11:93:11 | p | smart_pointer.cpp:93:13:93:15 | call to get | | | smart_pointer.cpp:88:8:88:8 | ref arg p | smart_pointer.cpp:89:8:89:8 | p | |
| smart_pointer.cpp:93:11:93:11 | ref arg p | smart_pointer.cpp:94:8:94:8 | p | | | smart_pointer.cpp:89:8:89:8 | p | smart_pointer.cpp:89:9:89:9 | call to operator-> | |
| smart_pointer.cpp:93:13:93:15 | ref arg call to get | smart_pointer.cpp:93:11:93:11 | ref arg p | | | smart_pointer.cpp:89:8:89:8 | ref arg p | smart_pointer.cpp:86:45:86:45 | p | |
| smart_pointer.cpp:94:8:94:8 | p | smart_pointer.cpp:94:9:94:9 | call to operator-> | | | smart_pointer.cpp:91:3:91:3 | q | smart_pointer.cpp:91:4:91:4 | call to operator-> | |
| smart_pointer.cpp:91:3:91:3 | ref arg q | smart_pointer.cpp:86:67:86:67 | q | |
| smart_pointer.cpp:91:3:91:3 | ref arg q | smart_pointer.cpp:92:8:92:8 | q | |
| smart_pointer.cpp:91:3:91:3 | ref arg q | smart_pointer.cpp:93:8:93:8 | q | |
| smart_pointer.cpp:91:3:91:3 | ref arg q | smart_pointer.cpp:94:8:94:8 | q | |
| smart_pointer.cpp:91:3:91:20 | ... = ... | smart_pointer.cpp:91:9:91:9 | x [post update] | |
| smart_pointer.cpp:91:3:91:20 | ... = ... | smart_pointer.cpp:92:14:92:14 | x | |
| smart_pointer.cpp:91:4:91:4 | call to operator-> [post update] | smart_pointer.cpp:91:3:91:3 | ref arg q | TAINT |
| smart_pointer.cpp:91:13:91:18 | call to source | smart_pointer.cpp:91:3:91:20 | ... = ... | |
| smart_pointer.cpp:92:8:92:8 | q | smart_pointer.cpp:92:9:92:9 | call to operator-> | |
| smart_pointer.cpp:92:8:92:8 | ref arg q | smart_pointer.cpp:86:67:86:67 | q | |
| smart_pointer.cpp:92:8:92:8 | ref arg q | smart_pointer.cpp:93:8:93:8 | q | |
| smart_pointer.cpp:92:8:92:8 | ref arg q | smart_pointer.cpp:94:8:94:8 | q | |
| smart_pointer.cpp:93:8:93:8 | q | smart_pointer.cpp:93:9:93:9 | call to operator-> | |
| smart_pointer.cpp:93:8:93:8 | ref arg q | smart_pointer.cpp:86:67:86:67 | q | |
| smart_pointer.cpp:93:8:93:8 | ref arg q | smart_pointer.cpp:94:8:94:8 | q | |
| smart_pointer.cpp:94:8:94:8 | q | smart_pointer.cpp:94:9:94:9 | call to operator-> | |
| smart_pointer.cpp:94:8:94:8 | ref arg q | smart_pointer.cpp:86:67:86:67 | q | |
| smart_pointer.cpp:97:17:97:18 | pa | smart_pointer.cpp:98:5:98:6 | pa | |
| smart_pointer.cpp:98:5:98:20 | ... = ... | smart_pointer.cpp:98:9:98:9 | x [post update] | |
| smart_pointer.cpp:98:13:98:18 | call to source | smart_pointer.cpp:98:5:98:20 | ... = ... | |
| smart_pointer.cpp:102:25:102:50 | call to unique_ptr | smart_pointer.cpp:103:11:103:11 | p | |
| smart_pointer.cpp:102:25:102:50 | call to unique_ptr | smart_pointer.cpp:104:8:104:8 | p | |
| smart_pointer.cpp:103:11:103:11 | p | smart_pointer.cpp:103:13:103:15 | call to get | |
| smart_pointer.cpp:103:11:103:11 | ref arg p | smart_pointer.cpp:104:8:104:8 | p | |
| smart_pointer.cpp:103:13:103:15 | ref arg call to get | smart_pointer.cpp:103:11:103:11 | ref arg p | TAINT |
| smart_pointer.cpp:104:8:104:8 | p | smart_pointer.cpp:104:9:104:9 | call to operator-> | |
| smart_pointer.cpp:112:40:112:42 | ptr | smart_pointer.cpp:112:40:112:42 | ptr | |
| smart_pointer.cpp:112:40:112:42 | ptr | smart_pointer.cpp:113:2:113:4 | ptr | |
| smart_pointer.cpp:113:2:113:4 | ptr | smart_pointer.cpp:113:5:113:5 | call to operator-> | |
| smart_pointer.cpp:113:2:113:4 | ref arg ptr | smart_pointer.cpp:112:40:112:42 | ptr | |
| smart_pointer.cpp:113:2:113:18 | ... = ... | smart_pointer.cpp:113:7:113:7 | x [post update] | |
| smart_pointer.cpp:113:5:113:5 | call to operator-> [post update] | smart_pointer.cpp:113:2:113:4 | ref arg ptr | TAINT |
| smart_pointer.cpp:113:11:113:16 | call to source | smart_pointer.cpp:113:2:113:18 | ... = ... | |
| smart_pointer.cpp:116:52:116:54 | ptr | smart_pointer.cpp:116:52:116:54 | ptr | |
| smart_pointer.cpp:116:52:116:54 | ptr | smart_pointer.cpp:117:2:117:4 | ptr | |
| smart_pointer.cpp:117:2:117:4 | ptr | smart_pointer.cpp:117:5:117:5 | call to operator-> | |
| smart_pointer.cpp:117:2:117:4 | ref arg ptr | smart_pointer.cpp:116:52:116:54 | ptr | |
| smart_pointer.cpp:117:2:117:18 | ... = ... | smart_pointer.cpp:117:7:117:7 | x [post update] | |
| smart_pointer.cpp:117:5:117:5 | call to operator-> [post update] | smart_pointer.cpp:117:2:117:4 | ref arg ptr | TAINT |
| smart_pointer.cpp:117:11:117:16 | call to source | smart_pointer.cpp:117:2:117:18 | ... = ... | |
| smart_pointer.cpp:120:48:120:50 | ptr | smart_pointer.cpp:120:48:120:50 | ptr | |
| smart_pointer.cpp:120:48:120:50 | ptr | smart_pointer.cpp:121:4:121:6 | ptr | |
| smart_pointer.cpp:121:3:121:3 | call to operator* [post update] | smart_pointer.cpp:120:48:120:50 | ptr | |
| smart_pointer.cpp:121:3:121:3 | call to operator* [post update] | smart_pointer.cpp:121:4:121:6 | ptr [inner post update] | |
| smart_pointer.cpp:121:3:121:17 | ... = ... | smart_pointer.cpp:121:3:121:3 | call to operator* [post update] | |
| smart_pointer.cpp:121:4:121:6 | ptr | smart_pointer.cpp:121:3:121:3 | call to operator* | |
| smart_pointer.cpp:121:4:121:6 | ref arg ptr | smart_pointer.cpp:120:48:120:50 | ptr | |
| smart_pointer.cpp:121:4:121:6 | ref arg ptr | smart_pointer.cpp:121:4:121:6 | ptr [inner post update] | |
| smart_pointer.cpp:121:10:121:15 | call to source | smart_pointer.cpp:121:3:121:17 | ... = ... | |
| smart_pointer.cpp:124:48:124:49 | p1 | smart_pointer.cpp:124:48:124:49 | p1 | |
| smart_pointer.cpp:124:48:124:49 | p1 | smart_pointer.cpp:125:18:125:19 | p1 | |
| smart_pointer.cpp:124:48:124:49 | p1 | smart_pointer.cpp:126:8:126:9 | p1 | |
| smart_pointer.cpp:124:90:124:91 | p2 | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:124:90:124:91 | p2 | smart_pointer.cpp:128:14:128:15 | p2 | |
| smart_pointer.cpp:124:90:124:91 | p2 | smart_pointer.cpp:129:10:129:11 | p2 | |
| smart_pointer.cpp:125:18:125:19 | p1 | smart_pointer.cpp:125:20:125:20 | call to operator-> | |
| smart_pointer.cpp:125:18:125:19 | ref arg p1 | smart_pointer.cpp:124:48:124:49 | p1 | |
| smart_pointer.cpp:125:18:125:19 | ref arg p1 | smart_pointer.cpp:126:8:126:9 | p1 | |
| smart_pointer.cpp:125:18:125:22 | ref arg call to shared_ptr | smart_pointer.cpp:125:22:125:22 | q [inner post update] | |
| smart_pointer.cpp:125:20:125:20 | call to operator-> [post update] | smart_pointer.cpp:125:18:125:19 | ref arg p1 | TAINT |
| smart_pointer.cpp:125:22:125:22 | q | smart_pointer.cpp:125:18:125:22 | call to shared_ptr | |
| smart_pointer.cpp:125:22:125:22 | ref arg q | smart_pointer.cpp:125:22:125:22 | q [inner post update] | |
| smart_pointer.cpp:126:8:126:9 | p1 | smart_pointer.cpp:126:10:126:10 | call to operator-> | |
| smart_pointer.cpp:126:8:126:9 | ref arg p1 | smart_pointer.cpp:124:48:124:49 | p1 | |
| smart_pointer.cpp:126:10:126:10 | call to operator-> [post update] | smart_pointer.cpp:126:8:126:9 | ref arg p1 | TAINT |
| smart_pointer.cpp:126:12:126:12 | q | smart_pointer.cpp:126:13:126:13 | call to operator-> | |
| smart_pointer.cpp:128:13:128:13 | call to operator* | smart_pointer.cpp:128:13:128:15 | call to shared_ptr | TAINT |
| smart_pointer.cpp:128:13:128:13 | ref arg call to operator* | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:128:13:128:13 | ref arg call to operator* | smart_pointer.cpp:128:13:128:13 | call to operator* [inner post update] | |
| smart_pointer.cpp:128:13:128:13 | ref arg call to operator* | smart_pointer.cpp:128:14:128:15 | p2 [inner post update] | |
| smart_pointer.cpp:128:13:128:13 | ref arg call to operator* | smart_pointer.cpp:129:10:129:11 | p2 | |
| smart_pointer.cpp:128:13:128:15 | ref arg call to shared_ptr | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:128:13:128:15 | ref arg call to shared_ptr | smart_pointer.cpp:128:13:128:13 | call to operator* [inner post update] | |
| smart_pointer.cpp:128:13:128:15 | ref arg call to shared_ptr | smart_pointer.cpp:128:14:128:15 | p2 [inner post update] | |
| smart_pointer.cpp:128:13:128:15 | ref arg call to shared_ptr | smart_pointer.cpp:129:10:129:11 | p2 | |
| smart_pointer.cpp:128:14:128:15 | p2 | smart_pointer.cpp:128:13:128:13 | call to operator* | TAINT |
| smart_pointer.cpp:128:14:128:15 | ref arg p2 | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:128:14:128:15 | ref arg p2 | smart_pointer.cpp:128:14:128:15 | p2 [inner post update] | |
| smart_pointer.cpp:128:14:128:15 | ref arg p2 | smart_pointer.cpp:129:10:129:11 | p2 | |
| smart_pointer.cpp:129:9:129:9 | call to operator* | smart_pointer.cpp:129:8:129:8 | call to operator* | TAINT |
| smart_pointer.cpp:129:9:129:9 | ref arg call to operator* | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:129:9:129:9 | ref arg call to operator* | smart_pointer.cpp:129:10:129:11 | p2 [inner post update] | |
| smart_pointer.cpp:129:10:129:11 | p2 | smart_pointer.cpp:129:8:129:8 | call to operator* | |
| smart_pointer.cpp:129:10:129:11 | p2 | smart_pointer.cpp:129:9:129:9 | call to operator* | TAINT |
| smart_pointer.cpp:129:10:129:11 | ref arg p2 | smart_pointer.cpp:124:90:124:91 | p2 | |
| smart_pointer.cpp:129:10:129:11 | ref arg p2 | smart_pointer.cpp:129:10:129:11 | p2 [inner post update] | |
| smart_pointer.cpp:132:53:132:54 | p1 | smart_pointer.cpp:132:53:132:54 | p1 | |
| smart_pointer.cpp:132:53:132:54 | p1 | smart_pointer.cpp:133:23:133:24 | p1 | |
| smart_pointer.cpp:132:53:132:54 | p1 | smart_pointer.cpp:134:8:134:9 | p1 | |
| smart_pointer.cpp:132:95:132:96 | p2 | smart_pointer.cpp:132:95:132:96 | p2 | |
| smart_pointer.cpp:132:95:132:96 | p2 | smart_pointer.cpp:136:18:136:19 | p2 | |
| smart_pointer.cpp:132:95:132:96 | p2 | smart_pointer.cpp:137:10:137:11 | p2 | |
| smart_pointer.cpp:133:23:133:24 | p1 | smart_pointer.cpp:133:25:133:25 | call to operator-> | |
| smart_pointer.cpp:133:23:133:24 | ref arg p1 | smart_pointer.cpp:132:53:132:54 | p1 | |
| smart_pointer.cpp:133:23:133:24 | ref arg p1 | smart_pointer.cpp:134:8:134:9 | p1 | |
| smart_pointer.cpp:133:25:133:25 | call to operator-> [post update] | smart_pointer.cpp:133:23:133:24 | ref arg p1 | TAINT |
| smart_pointer.cpp:134:8:134:9 | p1 | smart_pointer.cpp:134:10:134:10 | call to operator-> | |
| smart_pointer.cpp:134:8:134:9 | ref arg p1 | smart_pointer.cpp:132:53:132:54 | p1 | |
| smart_pointer.cpp:134:10:134:10 | call to operator-> [post update] | smart_pointer.cpp:134:8:134:9 | ref arg p1 | TAINT |
| smart_pointer.cpp:134:12:134:12 | q | smart_pointer.cpp:134:13:134:13 | call to operator-> | |
| smart_pointer.cpp:136:17:136:17 | ref arg call to operator* | smart_pointer.cpp:132:95:132:96 | p2 | |
| smart_pointer.cpp:136:17:136:17 | ref arg call to operator* | smart_pointer.cpp:136:18:136:19 | p2 [inner post update] | |
| smart_pointer.cpp:136:17:136:17 | ref arg call to operator* | smart_pointer.cpp:137:10:137:11 | p2 | |
| smart_pointer.cpp:136:18:136:19 | p2 | smart_pointer.cpp:136:17:136:17 | call to operator* | TAINT |
| smart_pointer.cpp:136:18:136:19 | ref arg p2 | smart_pointer.cpp:132:95:132:96 | p2 | |
| smart_pointer.cpp:136:18:136:19 | ref arg p2 | smart_pointer.cpp:136:18:136:19 | p2 [inner post update] | |
| smart_pointer.cpp:136:18:136:19 | ref arg p2 | smart_pointer.cpp:137:10:137:11 | p2 | |
| smart_pointer.cpp:137:9:137:9 | call to operator* | smart_pointer.cpp:137:8:137:8 | call to operator* | TAINT |
| smart_pointer.cpp:137:9:137:9 | ref arg call to operator* | smart_pointer.cpp:132:95:132:96 | p2 | |
| smart_pointer.cpp:137:9:137:9 | ref arg call to operator* | smart_pointer.cpp:137:10:137:11 | p2 [inner post update] | |
| smart_pointer.cpp:137:10:137:11 | p2 | smart_pointer.cpp:137:8:137:8 | call to operator* | |
| smart_pointer.cpp:137:10:137:11 | p2 | smart_pointer.cpp:137:9:137:9 | call to operator* | TAINT |
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:132:95:132:96 | p2 | |
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:137:10:137:11 | p2 [inner post update] | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | | | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | | | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | | | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | |
@@ -3432,125 +3560,125 @@
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT | | stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT | | stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:53:292:63 | 0 | stl.h:292:46:292:64 | (no string representation) | TAINT | | stl.h:292:53:292:63 | 0 | stl.h:292:46:292:64 | (no string representation) | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field first | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field first | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field first | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field first | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field first | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field second | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field second | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field second | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field second | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:388:9:388:9 | Unknown literal | stl.h:388:9:388:9 | constructor init of field second | TAINT | | stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:388:9:388:9 | constructor init of field first [post-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [post-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [post-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [post-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [post-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [pre-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [pre-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [pre-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [pre-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | constructor init of field first [pre-this] | stl.h:388:9:388:9 | constructor init of field second [pre-this] | | | stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:388:9:388:9 | this | stl.h:388:9:388:9 | constructor init of field first [pre-this] | | | stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:388:9:388:9 | this | stl.h:388:9:388:9 | constructor init of field first [pre-this] | | | stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:388:9:388:9 | this | stl.h:388:9:388:9 | constructor init of field first [pre-this] | | | stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:388:9:388:9 | this | stl.h:388:9:388:9 | constructor init of field first [pre-this] | | | stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:388:9:388:9 | this | stl.h:388:9:388:9 | constructor init of field first [pre-this] | | | stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:3 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:3 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:3 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:3 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:3 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:3:395:6 | this | stl.h:395:36:395:43 | constructor init of field first [pre-this] | | | stl.h:396:3:396:6 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:18:395:18 | x | stl.h:395:42:395:42 | x | | | stl.h:396:18:396:18 | x | stl.h:396:42:396:42 | x | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:31:395:31 | y | stl.h:395:53:395:53 | y | | | stl.h:396:31:396:31 | y | stl.h:396:53:396:53 | y | |
| stl.h:395:36:395:43 | call to unknown function | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:36:396:43 | call to unknown function | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [post-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [post-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:36:395:43 | constructor init of field first [pre-this] | stl.h:395:46:395:54 | constructor init of field second [pre-this] | | | stl.h:396:36:396:43 | constructor init of field first [pre-this] | stl.h:396:46:396:54 | constructor init of field second [pre-this] | |
| stl.h:395:42:395:42 | x | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:42:396:42 | x | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:42:395:42 | x | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:42:396:42 | x | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:42:395:42 | x | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:42:396:42 | x | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:42:395:42 | x | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:42:396:42 | x | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:42:395:42 | x | stl.h:395:36:395:43 | constructor init of field first | TAINT | | stl.h:396:42:396:42 | x | stl.h:396:36:396:43 | constructor init of field first | TAINT |
| stl.h:395:46:395:54 | call to unknown function | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:46:396:54 | call to unknown function | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:395:53:395:53 | y | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:53:396:53 | y | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:395:53:395:53 | y | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:53:396:53 | y | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:395:53:395:53 | y | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:53:396:53 | y | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:395:53:395:53 | y | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:53:396:53 | y | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:395:53:395:53 | y | stl.h:395:46:395:54 | constructor init of field second | TAINT | | stl.h:396:53:396:53 | y | stl.h:396:46:396:54 | constructor init of field second | TAINT |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:401:87:401:87 | x | | | stl.h:402:87:402:87 | x | stl.h:402:87:402:87 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:87:401:87 | x | stl.h:402:58:402:58 | x | | | stl.h:402:87:402:87 | x | stl.h:403:58:403:58 | x | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:401:95:401:95 | y | | | stl.h:402:95:402:95 | y | stl.h:402:95:402:95 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:401:95:401:95 | y | stl.h:402:79:402:79 | y | | | stl.h:402:95:402:95 | y | stl.h:403:79:403:79 | y | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:58:402:58 | x | stl.h:402:41:402:56 | call to forward | | | stl.h:403:58:403:58 | x | stl.h:403:41:403:56 | call to forward | |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:62:402:77 | call to forward | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:62:403:77 | call to forward | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:3:402:82 | call to pair | TAINT | | stl.h:403:79:403:79 | y | stl.h:403:3:403:82 | call to pair | TAINT |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| stl.h:402:79:402:79 | y | stl.h:402:62:402:77 | call to forward | | | stl.h:403:79:403:79 | y | stl.h:403:62:403:77 | call to forward | |
| string.cpp:25:12:25:17 | call to source | string.cpp:29:7:29:7 | a | | | string.cpp:25:12:25:17 | call to source | string.cpp:29:7:29:7 | a | |
| string.cpp:26:16:26:20 | 123 | string.cpp:26:16:26:21 | call to basic_string | TAINT | | string.cpp:26:16:26:20 | 123 | string.cpp:26:16:26:21 | call to basic_string | TAINT |
| string.cpp:26:16:26:21 | call to basic_string | string.cpp:30:7:30:7 | b | | | string.cpp:26:16:26:21 | call to basic_string | string.cpp:30:7:30:7 | b | |

View File

@@ -35,16 +35,16 @@ void test_reverse_taint_shared() {
std::shared_ptr<int> p = std::make_shared<int>(); std::shared_ptr<int> p = std::make_shared<int>();
*p = source(); *p = source();
sink(p); // $ MISSING: ast,ir sink(p); // $ ast MISSING: ir
sink(*p); // $ MISSING: ast,ir sink(*p); // $ ast MISSING: ir
} }
void test_reverse_taint_unique() { void test_reverse_taint_unique() {
std::unique_ptr<int> p = std::unique_ptr<int>(); std::unique_ptr<int> p = std::unique_ptr<int>();
*p = source(); *p = source();
sink(p); // $ MISSING: ast,ir sink(p); // $ ast MISSING: ir
sink(*p); // $ MISSING: ast,ir sink(*p); // $ ast MISSING: ir
} }
void test_shared_get() { void test_shared_get() {
@@ -67,6 +67,16 @@ void test_shared_field_member() {
sink(p->y); // not tainted sink(p->y); // not tainted
} }
void getNumber(std::shared_ptr<int> ptr) {
*ptr = source();
}
int test_from_issue_5190() {
std::shared_ptr<int> p(new int);
getNumber(p);
sink(*p); // $ ast MISSING: ir
}
struct B { struct B {
A a1; A a1;
A a2; A a2;
@@ -93,3 +103,36 @@ void reverse_taint_smart_pointer() {
taint_x(p.get()); taint_x(p.get());
sink(p->x); // $ ast MISSING: ir sink(p->x); // $ ast MISSING: ir
} }
struct C {
int z;
std::shared_ptr<A> q;
};
void taint_x_shared(std::shared_ptr<A> ptr) {
ptr->x = source();
}
void taint_x_shared_cref(const std::shared_ptr<A>& ptr) {
ptr->x = source();
}
void getNumberCRef(const std::shared_ptr<int>& ptr) {
*ptr = source();
}
int nested_shared_ptr_taint(std::shared_ptr<C> p1, std::unique_ptr<std::shared_ptr<int>> p2) {
taint_x_shared(p1->q);
sink(p1->q->x); // $ ast MISSING: ir
getNumber(*p2);
sink(**p2); // $ ast MISSING: ir
}
int nested_shared_ptr_taint_cref(std::shared_ptr<C> p1, std::unique_ptr<std::shared_ptr<int>> p2) {
taint_x_shared_cref(p1->q);
sink(p1->q->x); // $ ast MISSING: ir
getNumberCRef(*p2);
sink(**p2); // $ ast MISSING: ir
}

View File

@@ -349,6 +349,7 @@ namespace std {
public: public:
shared_ptr() noexcept; shared_ptr() noexcept;
explicit shared_ptr(T*); explicit shared_ptr(T*);
shared_ptr(const shared_ptr&) noexcept;
template<class U> shared_ptr(const shared_ptr<U>&) noexcept; template<class U> shared_ptr(const shared_ptr<U>&) noexcept;
template<class U> shared_ptr(shared_ptr<U>&&) noexcept; template<class U> shared_ptr(shared_ptr<U>&&) noexcept;

View File

@@ -42,7 +42,7 @@ bad_asts.cpp:
# 16| r16_3(int) = Constant[1] : # 16| r16_3(int) = Constant[1] :
# 16| r16_4(int) = Call[MemberFunction] : func:r16_2, this:r16_1, 0:r16_3 # 16| r16_4(int) = Call[MemberFunction] : func:r16_2, this:r16_1, 0:r16_3
# 16| mu16_5(unknown) = ^CallSideEffect : ~m? # 16| mu16_5(unknown) = ^CallSideEffect : ~m?
# 16| v16_6(void) = ^BufferReadSideEffect[-1] : &:r16_1, ~m? # 16| v16_6(void) = ^IndirectReadSideEffect[-1] : &:r16_1, ~m?
# 16| mu16_7(S) = ^IndirectMayWriteSideEffect[-1] : &:r16_1 # 16| mu16_7(S) = ^IndirectMayWriteSideEffect[-1] : &:r16_1
# 17| v17_1(void) = NoOp : # 17| v17_1(void) = NoOp :
# 14| v14_4(void) = ReturnVoid : # 14| v14_4(void) = ReturnVoid :
@@ -3385,47 +3385,46 @@ ir.cpp:
# 622| void CallMethods(String&, String*, String) # 622| void CallMethods(String&, String*, String)
# 622| Block 0 # 622| Block 0
# 622| v622_1(void) = EnterFunction : # 622| v622_1(void) = EnterFunction :
# 622| mu622_2(unknown) = AliasedDefinition : # 622| mu622_2(unknown) = AliasedDefinition :
# 622| mu622_3(unknown) = InitializeNonLocal : # 622| mu622_3(unknown) = InitializeNonLocal :
# 622| r622_4(glval<String &>) = VariableAddress[r] : # 622| r622_4(glval<String &>) = VariableAddress[r] :
# 622| mu622_5(String &) = InitializeParameter[r] : &:r622_4 # 622| mu622_5(String &) = InitializeParameter[r] : &:r622_4
# 622| r622_6(String &) = Load[r] : &:r622_4, ~m? # 622| r622_6(String &) = Load[r] : &:r622_4, ~m?
# 622| mu622_7(unknown) = InitializeIndirection[r] : &:r622_6 # 622| mu622_7(unknown) = InitializeIndirection[r] : &:r622_6
# 622| r622_8(glval<String *>) = VariableAddress[p] : # 622| r622_8(glval<String *>) = VariableAddress[p] :
# 622| mu622_9(String *) = InitializeParameter[p] : &:r622_8 # 622| mu622_9(String *) = InitializeParameter[p] : &:r622_8
# 622| r622_10(String *) = Load[p] : &:r622_8, ~m? # 622| r622_10(String *) = Load[p] : &:r622_8, ~m?
# 622| mu622_11(unknown) = InitializeIndirection[p] : &:r622_10 # 622| mu622_11(unknown) = InitializeIndirection[p] : &:r622_10
# 622| r622_12(glval<String>) = VariableAddress[s] : # 622| r622_12(glval<String>) = VariableAddress[s] :
# 622| mu622_13(String) = InitializeParameter[s] : &:r622_12 # 622| mu622_13(String) = InitializeParameter[s] : &:r622_12
# 623| r623_1(glval<String &>) = VariableAddress[r] : # 623| r623_1(glval<String &>) = VariableAddress[r] :
# 623| r623_2(String &) = Load[r] : &:r623_1, ~m? # 623| r623_2(String &) = Load[r] : &:r623_1, ~m?
# 623| r623_3(glval<String>) = CopyValue : r623_2 # 623| r623_3(glval<String>) = CopyValue : r623_2
# 623| r623_4(glval<String>) = Convert : r623_3 # 623| r623_4(glval<String>) = Convert : r623_3
# 623| r623_5(glval<unknown>) = FunctionAddress[c_str] : # 623| r623_5(glval<unknown>) = FunctionAddress[c_str] :
# 623| r623_6(char *) = Call[c_str] : func:r623_5, this:r623_4 # 623| r623_6(char *) = Call[c_str] : func:r623_5, this:r623_4
# 623| mu623_7(unknown) = ^CallSideEffect : ~m? # 623| mu623_7(unknown) = ^CallSideEffect : ~m?
# 623| v623_8(void) = ^BufferReadSideEffect[-1] : &:r623_4, ~m? # 623| v623_8(void) = ^IndirectReadSideEffect[-1] : &:r623_4, ~m?
# 624| r624_1(glval<String *>) = VariableAddress[p] : # 624| r624_1(glval<String *>) = VariableAddress[p] :
# 624| r624_2(String *) = Load[p] : &:r624_1, ~m? # 624| r624_2(String *) = Load[p] : &:r624_1, ~m?
# 624| r624_3(String *) = Convert : r624_2 # 624| r624_3(String *) = Convert : r624_2
# 624| r624_4(glval<unknown>) = FunctionAddress[c_str] : # 624| r624_4(glval<unknown>) = FunctionAddress[c_str] :
# 624| r624_5(char *) = Call[c_str] : func:r624_4, this:r624_3 # 624| r624_5(char *) = Call[c_str] : func:r624_4, this:r624_3
# 624| mu624_6(unknown) = ^CallSideEffect : ~m? # 624| mu624_6(unknown) = ^CallSideEffect : ~m?
# 624| v624_7(void) = ^BufferReadSideEffect[-1] : &:r624_3, ~m? # 624| v624_7(void) = ^IndirectReadSideEffect[-1] : &:r624_3, ~m?
# 624| mu624_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r624_3 # 625| r625_1(glval<String>) = VariableAddress[s] :
# 625| r625_1(glval<String>) = VariableAddress[s] : # 625| r625_2(glval<String>) = Convert : r625_1
# 625| r625_2(glval<String>) = Convert : r625_1 # 625| r625_3(glval<unknown>) = FunctionAddress[c_str] :
# 625| r625_3(glval<unknown>) = FunctionAddress[c_str] : # 625| r625_4(char *) = Call[c_str] : func:r625_3, this:r625_2
# 625| r625_4(char *) = Call[c_str] : func:r625_3, this:r625_2 # 625| mu625_5(unknown) = ^CallSideEffect : ~m?
# 625| mu625_5(unknown) = ^CallSideEffect : ~m? # 625| v625_6(void) = ^IndirectReadSideEffect[-1] : &:r625_2, ~m?
# 625| v625_6(void) = ^BufferReadSideEffect[-1] : &:r625_2, ~m? # 626| v626_1(void) = NoOp :
# 626| v626_1(void) = NoOp : # 622| v622_14(void) = ReturnIndirection[r] : &:r622_6, ~m?
# 622| v622_14(void) = ReturnIndirection[r] : &:r622_6, ~m? # 622| v622_15(void) = ReturnIndirection[p] : &:r622_10, ~m?
# 622| v622_15(void) = ReturnIndirection[p] : &:r622_10, ~m? # 622| v622_16(void) = ReturnVoid :
# 622| v622_16(void) = ReturnVoid : # 622| v622_17(void) = AliasedUse : ~m?
# 622| v622_17(void) = AliasedUse : ~m? # 622| v622_18(void) = ExitFunction :
# 622| v622_18(void) = ExitFunction :
# 628| void C::~C() # 628| void C::~C()
# 628| Block 0 # 628| Block 0
@@ -3575,7 +3574,7 @@ ir.cpp:
# 653| r653_4(int) = Constant[0] : # 653| r653_4(int) = Constant[0] :
# 653| r653_5(int) = Call[InstanceMemberFunction] : func:r653_3, this:r653_2, 0:r653_4 # 653| r653_5(int) = Call[InstanceMemberFunction] : func:r653_3, this:r653_2, 0:r653_4
# 653| mu653_6(unknown) = ^CallSideEffect : ~m? # 653| mu653_6(unknown) = ^CallSideEffect : ~m?
# 653| v653_7(void) = ^BufferReadSideEffect[-1] : &:r653_2, ~m? # 653| v653_7(void) = ^IndirectReadSideEffect[-1] : &:r653_2, ~m?
# 653| mu653_8(C) = ^IndirectMayWriteSideEffect[-1] : &:r653_2 # 653| mu653_8(C) = ^IndirectMayWriteSideEffect[-1] : &:r653_2
# 654| r654_1(glval<unknown>) = VariableAddress[#this] : # 654| r654_1(glval<unknown>) = VariableAddress[#this] :
# 654| r654_2(C *) = Load[#this] : &:r654_1, ~m? # 654| r654_2(C *) = Load[#this] : &:r654_1, ~m?
@@ -3584,7 +3583,7 @@ ir.cpp:
# 654| r654_5(int) = Constant[1] : # 654| r654_5(int) = Constant[1] :
# 654| r654_6(int) = Call[InstanceMemberFunction] : func:r654_4, this:r654_3, 0:r654_5 # 654| r654_6(int) = Call[InstanceMemberFunction] : func:r654_4, this:r654_3, 0:r654_5
# 654| mu654_7(unknown) = ^CallSideEffect : ~m? # 654| mu654_7(unknown) = ^CallSideEffect : ~m?
# 654| v654_8(void) = ^BufferReadSideEffect[-1] : &:r654_3, ~m? # 654| v654_8(void) = ^IndirectReadSideEffect[-1] : &:r654_3, ~m?
# 654| mu654_9(C) = ^IndirectMayWriteSideEffect[-1] : &:r654_3 # 654| mu654_9(C) = ^IndirectMayWriteSideEffect[-1] : &:r654_3
# 655| r655_1(glval<unknown>) = VariableAddress[#this] : # 655| r655_1(glval<unknown>) = VariableAddress[#this] :
# 655| r655_2(C *) = Load[#this] : &:r655_1, ~m? # 655| r655_2(C *) = Load[#this] : &:r655_1, ~m?
@@ -3592,7 +3591,7 @@ ir.cpp:
# 655| r655_4(int) = Constant[2] : # 655| r655_4(int) = Constant[2] :
# 655| r655_5(int) = Call[InstanceMemberFunction] : func:r655_3, this:r655_2, 0:r655_4 # 655| r655_5(int) = Call[InstanceMemberFunction] : func:r655_3, this:r655_2, 0:r655_4
# 655| mu655_6(unknown) = ^CallSideEffect : ~m? # 655| mu655_6(unknown) = ^CallSideEffect : ~m?
# 655| v655_7(void) = ^BufferReadSideEffect[-1] : &:r655_2, ~m? # 655| v655_7(void) = ^IndirectReadSideEffect[-1] : &:r655_2, ~m?
# 655| mu655_8(C) = ^IndirectMayWriteSideEffect[-1] : &:r655_2 # 655| mu655_8(C) = ^IndirectMayWriteSideEffect[-1] : &:r655_2
# 656| v656_1(void) = NoOp : # 656| v656_1(void) = NoOp :
# 652| v652_8(void) = ReturnIndirection[#this] : &:r652_6, ~m? # 652| v652_8(void) = ReturnIndirection[#this] : &:r652_6, ~m?
@@ -4006,7 +4005,7 @@ ir.cpp:
#-----| r0_6(String &) = CopyValue : r745_15 #-----| r0_6(String &) = CopyValue : r745_15
# 745| r745_16(String &) = Call[operator=] : func:r745_12, this:r745_11, 0:r0_6 # 745| r745_16(String &) = Call[operator=] : func:r745_12, this:r745_11, 0:r0_6
# 745| mu745_17(unknown) = ^CallSideEffect : ~m? # 745| mu745_17(unknown) = ^CallSideEffect : ~m?
# 745| v745_18(void) = ^BufferReadSideEffect[-1] : &:r745_11, ~m? # 745| v745_18(void) = ^IndirectReadSideEffect[-1] : &:r745_11, ~m?
#-----| v0_7(void) = ^BufferReadSideEffect[0] : &:r0_6, ~m? #-----| v0_7(void) = ^BufferReadSideEffect[0] : &:r0_6, ~m?
# 745| mu745_19(String) = ^IndirectMayWriteSideEffect[-1] : &:r745_11 # 745| mu745_19(String) = ^IndirectMayWriteSideEffect[-1] : &:r745_11
#-----| r0_8(glval<String>) = CopyValue : r745_16 #-----| r0_8(glval<String>) = CopyValue : r745_16
@@ -4113,7 +4112,7 @@ ir.cpp:
#-----| r0_8(Base &) = CopyValue : r754_14 #-----| r0_8(Base &) = CopyValue : r754_14
# 754| r754_15(Base &) = Call[operator=] : func:r754_10, this:r0_5, 0:r0_8 # 754| r754_15(Base &) = Call[operator=] : func:r754_10, this:r0_5, 0:r0_8
# 754| mu754_16(unknown) = ^CallSideEffect : ~m? # 754| mu754_16(unknown) = ^CallSideEffect : ~m?
#-----| v0_9(void) = ^BufferReadSideEffect[-1] : &:r0_5, ~m? #-----| v0_9(void) = ^IndirectReadSideEffect[-1] : &:r0_5, ~m?
#-----| v0_10(void) = ^BufferReadSideEffect[0] : &:r0_8, ~m? #-----| v0_10(void) = ^BufferReadSideEffect[0] : &:r0_8, ~m?
#-----| mu0_11(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_5 #-----| mu0_11(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_5
#-----| r0_12(glval<Base>) = CopyValue : r754_15 #-----| r0_12(glval<Base>) = CopyValue : r754_15
@@ -4129,7 +4128,7 @@ ir.cpp:
#-----| r0_14(String &) = CopyValue : r754_24 #-----| r0_14(String &) = CopyValue : r754_24
# 754| r754_25(String &) = Call[operator=] : func:r754_21, this:r754_20, 0:r0_14 # 754| r754_25(String &) = Call[operator=] : func:r754_21, this:r754_20, 0:r0_14
# 754| mu754_26(unknown) = ^CallSideEffect : ~m? # 754| mu754_26(unknown) = ^CallSideEffect : ~m?
# 754| v754_27(void) = ^BufferReadSideEffect[-1] : &:r754_20, ~m? # 754| v754_27(void) = ^IndirectReadSideEffect[-1] : &:r754_20, ~m?
#-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_14, ~m? #-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_14, ~m?
# 754| mu754_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r754_20 # 754| mu754_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r754_20
#-----| r0_16(glval<String>) = CopyValue : r754_25 #-----| r0_16(glval<String>) = CopyValue : r754_25
@@ -4220,7 +4219,7 @@ ir.cpp:
#-----| r0_8(Middle &) = CopyValue : r763_14 #-----| r0_8(Middle &) = CopyValue : r763_14
# 763| r763_15(Middle &) = Call[operator=] : func:r763_10, this:r0_5, 0:r0_8 # 763| r763_15(Middle &) = Call[operator=] : func:r763_10, this:r0_5, 0:r0_8
# 763| mu763_16(unknown) = ^CallSideEffect : ~m? # 763| mu763_16(unknown) = ^CallSideEffect : ~m?
#-----| v0_9(void) = ^BufferReadSideEffect[-1] : &:r0_5, ~m? #-----| v0_9(void) = ^IndirectReadSideEffect[-1] : &:r0_5, ~m?
#-----| v0_10(void) = ^BufferReadSideEffect[0] : &:r0_8, ~m? #-----| v0_10(void) = ^BufferReadSideEffect[0] : &:r0_8, ~m?
#-----| mu0_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_5 #-----| mu0_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_5
#-----| r0_12(glval<Middle>) = CopyValue : r763_15 #-----| r0_12(glval<Middle>) = CopyValue : r763_15
@@ -4236,7 +4235,7 @@ ir.cpp:
#-----| r0_14(String &) = CopyValue : r763_24 #-----| r0_14(String &) = CopyValue : r763_24
# 763| r763_25(String &) = Call[operator=] : func:r763_21, this:r763_20, 0:r0_14 # 763| r763_25(String &) = Call[operator=] : func:r763_21, this:r763_20, 0:r0_14
# 763| mu763_26(unknown) = ^CallSideEffect : ~m? # 763| mu763_26(unknown) = ^CallSideEffect : ~m?
# 763| v763_27(void) = ^BufferReadSideEffect[-1] : &:r763_20, ~m? # 763| v763_27(void) = ^IndirectReadSideEffect[-1] : &:r763_20, ~m?
#-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_14, ~m? #-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_14, ~m?
# 763| mu763_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r763_20 # 763| mu763_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r763_20
#-----| r0_16(glval<String>) = CopyValue : r763_25 #-----| r0_16(glval<String>) = CopyValue : r763_25
@@ -4505,7 +4504,7 @@ ir.cpp:
# 808| r808_5(Base &) = CopyValue : r808_4 # 808| r808_5(Base &) = CopyValue : r808_4
# 808| r808_6(Base &) = Call[operator=] : func:r808_2, this:r808_1, 0:r808_5 # 808| r808_6(Base &) = Call[operator=] : func:r808_2, this:r808_1, 0:r808_5
# 808| mu808_7(unknown) = ^CallSideEffect : ~m? # 808| mu808_7(unknown) = ^CallSideEffect : ~m?
# 808| v808_8(void) = ^BufferReadSideEffect[-1] : &:r808_1, ~m? # 808| v808_8(void) = ^IndirectReadSideEffect[-1] : &:r808_1, ~m?
# 808| v808_9(void) = ^BufferReadSideEffect[0] : &:r808_5, ~m? # 808| v808_9(void) = ^BufferReadSideEffect[0] : &:r808_5, ~m?
# 808| mu808_10(Base) = ^IndirectMayWriteSideEffect[-1] : &:r808_1 # 808| mu808_10(Base) = ^IndirectMayWriteSideEffect[-1] : &:r808_1
# 808| r808_11(glval<Base>) = CopyValue : r808_6 # 808| r808_11(glval<Base>) = CopyValue : r808_6
@@ -4525,7 +4524,7 @@ ir.cpp:
# 809| r809_14(Base &) = CopyValue : r809_13 # 809| r809_14(Base &) = CopyValue : r809_13
# 809| r809_15(Base &) = Call[operator=] : func:r809_2, this:r809_1, 0:r809_14 # 809| r809_15(Base &) = Call[operator=] : func:r809_2, this:r809_1, 0:r809_14
# 809| mu809_16(unknown) = ^CallSideEffect : ~m? # 809| mu809_16(unknown) = ^CallSideEffect : ~m?
# 809| v809_17(void) = ^BufferReadSideEffect[-1] : &:r809_1, ~m? # 809| v809_17(void) = ^IndirectReadSideEffect[-1] : &:r809_1, ~m?
# 809| v809_18(void) = ^BufferReadSideEffect[0] : &:r809_14, ~m? # 809| v809_18(void) = ^BufferReadSideEffect[0] : &:r809_14, ~m?
# 809| mu809_19(Base) = ^IndirectMayWriteSideEffect[-1] : &:r809_1 # 809| mu809_19(Base) = ^IndirectMayWriteSideEffect[-1] : &:r809_1
# 809| r809_20(glval<Base>) = CopyValue : r809_15 # 809| r809_20(glval<Base>) = CopyValue : r809_15
@@ -4545,7 +4544,7 @@ ir.cpp:
# 810| r810_14(Base &) = CopyValue : r810_13 # 810| r810_14(Base &) = CopyValue : r810_13
# 810| r810_15(Base &) = Call[operator=] : func:r810_2, this:r810_1, 0:r810_14 # 810| r810_15(Base &) = Call[operator=] : func:r810_2, this:r810_1, 0:r810_14
# 810| mu810_16(unknown) = ^CallSideEffect : ~m? # 810| mu810_16(unknown) = ^CallSideEffect : ~m?
# 810| v810_17(void) = ^BufferReadSideEffect[-1] : &:r810_1, ~m? # 810| v810_17(void) = ^IndirectReadSideEffect[-1] : &:r810_1, ~m?
# 810| v810_18(void) = ^BufferReadSideEffect[0] : &:r810_14, ~m? # 810| v810_18(void) = ^BufferReadSideEffect[0] : &:r810_14, ~m?
# 810| mu810_19(Base) = ^IndirectMayWriteSideEffect[-1] : &:r810_1 # 810| mu810_19(Base) = ^IndirectMayWriteSideEffect[-1] : &:r810_1
# 810| r810_20(glval<Base>) = CopyValue : r810_15 # 810| r810_20(glval<Base>) = CopyValue : r810_15
@@ -4577,7 +4576,7 @@ ir.cpp:
# 816| r816_6(Middle &) = CopyValue : r816_5 # 816| r816_6(Middle &) = CopyValue : r816_5
# 816| r816_7(Middle &) = Call[operator=] : func:r816_2, this:r816_1, 0:r816_6 # 816| r816_7(Middle &) = Call[operator=] : func:r816_2, this:r816_1, 0:r816_6
# 816| mu816_8(unknown) = ^CallSideEffect : ~m? # 816| mu816_8(unknown) = ^CallSideEffect : ~m?
# 816| v816_9(void) = ^BufferReadSideEffect[-1] : &:r816_1, ~m? # 816| v816_9(void) = ^IndirectReadSideEffect[-1] : &:r816_1, ~m?
# 816| v816_10(void) = ^BufferReadSideEffect[0] : &:r816_6, ~m? # 816| v816_10(void) = ^BufferReadSideEffect[0] : &:r816_6, ~m?
# 816| mu816_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r816_1 # 816| mu816_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r816_1
# 816| r816_12(glval<Middle>) = CopyValue : r816_7 # 816| r816_12(glval<Middle>) = CopyValue : r816_7
@@ -4589,7 +4588,7 @@ ir.cpp:
# 817| r817_6(Middle &) = CopyValue : r817_5 # 817| r817_6(Middle &) = CopyValue : r817_5
# 817| r817_7(Middle &) = Call[operator=] : func:r817_2, this:r817_1, 0:r817_6 # 817| r817_7(Middle &) = Call[operator=] : func:r817_2, this:r817_1, 0:r817_6
# 817| mu817_8(unknown) = ^CallSideEffect : ~m? # 817| mu817_8(unknown) = ^CallSideEffect : ~m?
# 817| v817_9(void) = ^BufferReadSideEffect[-1] : &:r817_1, ~m? # 817| v817_9(void) = ^IndirectReadSideEffect[-1] : &:r817_1, ~m?
# 817| v817_10(void) = ^BufferReadSideEffect[0] : &:r817_6, ~m? # 817| v817_10(void) = ^BufferReadSideEffect[0] : &:r817_6, ~m?
# 817| mu817_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r817_1 # 817| mu817_11(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r817_1
# 817| r817_12(glval<Middle>) = CopyValue : r817_7 # 817| r817_12(glval<Middle>) = CopyValue : r817_7
@@ -4616,7 +4615,7 @@ ir.cpp:
# 822| r822_6(Base &) = CopyValue : r822_5 # 822| r822_6(Base &) = CopyValue : r822_5
# 822| r822_7(Base &) = Call[operator=] : func:r822_2, this:r822_1, 0:r822_6 # 822| r822_7(Base &) = Call[operator=] : func:r822_2, this:r822_1, 0:r822_6
# 822| mu822_8(unknown) = ^CallSideEffect : ~m? # 822| mu822_8(unknown) = ^CallSideEffect : ~m?
# 822| v822_9(void) = ^BufferReadSideEffect[-1] : &:r822_1, ~m? # 822| v822_9(void) = ^IndirectReadSideEffect[-1] : &:r822_1, ~m?
# 822| v822_10(void) = ^BufferReadSideEffect[0] : &:r822_6, ~m? # 822| v822_10(void) = ^BufferReadSideEffect[0] : &:r822_6, ~m?
# 822| mu822_11(Base) = ^IndirectMayWriteSideEffect[-1] : &:r822_1 # 822| mu822_11(Base) = ^IndirectMayWriteSideEffect[-1] : &:r822_1
# 822| r822_12(glval<Base>) = CopyValue : r822_7 # 822| r822_12(glval<Base>) = CopyValue : r822_7
@@ -4637,7 +4636,7 @@ ir.cpp:
# 823| r823_15(Base &) = CopyValue : r823_14 # 823| r823_15(Base &) = CopyValue : r823_14
# 823| r823_16(Base &) = Call[operator=] : func:r823_2, this:r823_1, 0:r823_15 # 823| r823_16(Base &) = Call[operator=] : func:r823_2, this:r823_1, 0:r823_15
# 823| mu823_17(unknown) = ^CallSideEffect : ~m? # 823| mu823_17(unknown) = ^CallSideEffect : ~m?
# 823| v823_18(void) = ^BufferReadSideEffect[-1] : &:r823_1, ~m? # 823| v823_18(void) = ^IndirectReadSideEffect[-1] : &:r823_1, ~m?
# 823| v823_19(void) = ^BufferReadSideEffect[0] : &:r823_15, ~m? # 823| v823_19(void) = ^BufferReadSideEffect[0] : &:r823_15, ~m?
# 823| mu823_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r823_1 # 823| mu823_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r823_1
# 823| r823_21(glval<Base>) = CopyValue : r823_16 # 823| r823_21(glval<Base>) = CopyValue : r823_16
@@ -4658,7 +4657,7 @@ ir.cpp:
# 824| r824_15(Base &) = CopyValue : r824_14 # 824| r824_15(Base &) = CopyValue : r824_14
# 824| r824_16(Base &) = Call[operator=] : func:r824_2, this:r824_1, 0:r824_15 # 824| r824_16(Base &) = Call[operator=] : func:r824_2, this:r824_1, 0:r824_15
# 824| mu824_17(unknown) = ^CallSideEffect : ~m? # 824| mu824_17(unknown) = ^CallSideEffect : ~m?
# 824| v824_18(void) = ^BufferReadSideEffect[-1] : &:r824_1, ~m? # 824| v824_18(void) = ^IndirectReadSideEffect[-1] : &:r824_1, ~m?
# 824| v824_19(void) = ^BufferReadSideEffect[0] : &:r824_15, ~m? # 824| v824_19(void) = ^BufferReadSideEffect[0] : &:r824_15, ~m?
# 824| mu824_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r824_1 # 824| mu824_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r824_1
# 824| r824_21(glval<Base>) = CopyValue : r824_16 # 824| r824_21(glval<Base>) = CopyValue : r824_16
@@ -4694,7 +4693,7 @@ ir.cpp:
# 830| r830_7(Derived &) = CopyValue : r830_6 # 830| r830_7(Derived &) = CopyValue : r830_6
# 830| r830_8(Derived &) = Call[operator=] : func:r830_2, this:r830_1, 0:r830_7 # 830| r830_8(Derived &) = Call[operator=] : func:r830_2, this:r830_1, 0:r830_7
# 830| mu830_9(unknown) = ^CallSideEffect : ~m? # 830| mu830_9(unknown) = ^CallSideEffect : ~m?
# 830| v830_10(void) = ^BufferReadSideEffect[-1] : &:r830_1, ~m? # 830| v830_10(void) = ^IndirectReadSideEffect[-1] : &:r830_1, ~m?
# 830| v830_11(void) = ^BufferReadSideEffect[0] : &:r830_7, ~m? # 830| v830_11(void) = ^BufferReadSideEffect[0] : &:r830_7, ~m?
# 830| mu830_12(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r830_1 # 830| mu830_12(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r830_1
# 830| r830_13(glval<Derived>) = CopyValue : r830_8 # 830| r830_13(glval<Derived>) = CopyValue : r830_8
@@ -4707,7 +4706,7 @@ ir.cpp:
# 831| r831_7(Derived &) = CopyValue : r831_6 # 831| r831_7(Derived &) = CopyValue : r831_6
# 831| r831_8(Derived &) = Call[operator=] : func:r831_2, this:r831_1, 0:r831_7 # 831| r831_8(Derived &) = Call[operator=] : func:r831_2, this:r831_1, 0:r831_7
# 831| mu831_9(unknown) = ^CallSideEffect : ~m? # 831| mu831_9(unknown) = ^CallSideEffect : ~m?
# 831| v831_10(void) = ^BufferReadSideEffect[-1] : &:r831_1, ~m? # 831| v831_10(void) = ^IndirectReadSideEffect[-1] : &:r831_1, ~m?
# 831| v831_11(void) = ^BufferReadSideEffect[0] : &:r831_7, ~m? # 831| v831_11(void) = ^BufferReadSideEffect[0] : &:r831_7, ~m?
# 831| mu831_12(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r831_1 # 831| mu831_12(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r831_1
# 831| r831_13(glval<Derived>) = CopyValue : r831_8 # 831| r831_13(glval<Derived>) = CopyValue : r831_8
@@ -5688,7 +5687,7 @@ ir.cpp:
# 1044| r1044_4(float) = Constant[1.0] : # 1044| r1044_4(float) = Constant[1.0] :
# 1044| r1044_5(char) = Call[operator()] : func:r1044_3, this:r1044_2, 0:r1044_4 # 1044| r1044_5(char) = Call[operator()] : func:r1044_3, this:r1044_2, 0:r1044_4
# 1044| mu1044_6(unknown) = ^CallSideEffect : ~m? # 1044| mu1044_6(unknown) = ^CallSideEffect : ~m?
# 1044| v1044_7(void) = ^BufferReadSideEffect[-1] : &:r1044_2, ~m? # 1044| v1044_7(void) = ^IndirectReadSideEffect[-1] : &:r1044_2, ~m?
# 1045| r1045_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] : # 1045| r1045_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
# 1045| r1045_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:20] : # 1045| r1045_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:20] :
# 1045| mu1045_3(decltype([...](...){...})) = Uninitialized[#temp1045:20] : &:r1045_2 # 1045| mu1045_3(decltype([...](...){...})) = Uninitialized[#temp1045:20] : &:r1045_2
@@ -5709,7 +5708,7 @@ ir.cpp:
# 1046| r1046_4(float) = Constant[2.0] : # 1046| r1046_4(float) = Constant[2.0] :
# 1046| r1046_5(char) = Call[operator()] : func:r1046_3, this:r1046_2, 0:r1046_4 # 1046| r1046_5(char) = Call[operator()] : func:r1046_3, this:r1046_2, 0:r1046_4
# 1046| mu1046_6(unknown) = ^CallSideEffect : ~m? # 1046| mu1046_6(unknown) = ^CallSideEffect : ~m?
# 1046| v1046_7(void) = ^BufferReadSideEffect[-1] : &:r1046_2, ~m? # 1046| v1046_7(void) = ^IndirectReadSideEffect[-1] : &:r1046_2, ~m?
# 1047| r1047_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] : # 1047| r1047_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
# 1047| r1047_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1047:29] : # 1047| r1047_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1047:29] :
# 1047| mu1047_3(decltype([...](...){...})) = Uninitialized[#temp1047:29] : &:r1047_2 # 1047| mu1047_3(decltype([...](...){...})) = Uninitialized[#temp1047:29] : &:r1047_2
@@ -5727,7 +5726,7 @@ ir.cpp:
# 1048| r1048_4(float) = Constant[3.0] : # 1048| r1048_4(float) = Constant[3.0] :
# 1048| r1048_5(char) = Call[operator()] : func:r1048_3, this:r1048_2, 0:r1048_4 # 1048| r1048_5(char) = Call[operator()] : func:r1048_3, this:r1048_2, 0:r1048_4
# 1048| mu1048_6(unknown) = ^CallSideEffect : ~m? # 1048| mu1048_6(unknown) = ^CallSideEffect : ~m?
# 1048| v1048_7(void) = ^BufferReadSideEffect[-1] : &:r1048_2, ~m? # 1048| v1048_7(void) = ^IndirectReadSideEffect[-1] : &:r1048_2, ~m?
# 1049| r1049_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] : # 1049| r1049_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
# 1049| r1049_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1049:29] : # 1049| r1049_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1049:29] :
# 1049| mu1049_3(decltype([...](...){...})) = Uninitialized[#temp1049:29] : &:r1049_2 # 1049| mu1049_3(decltype([...](...){...})) = Uninitialized[#temp1049:29] : &:r1049_2
@@ -5744,7 +5743,7 @@ ir.cpp:
# 1050| r1050_4(float) = Constant[4.0] : # 1050| r1050_4(float) = Constant[4.0] :
# 1050| r1050_5(char) = Call[operator()] : func:r1050_3, this:r1050_2, 0:r1050_4 # 1050| r1050_5(char) = Call[operator()] : func:r1050_3, this:r1050_2, 0:r1050_4
# 1050| mu1050_6(unknown) = ^CallSideEffect : ~m? # 1050| mu1050_6(unknown) = ^CallSideEffect : ~m?
# 1050| v1050_7(void) = ^BufferReadSideEffect[-1] : &:r1050_2, ~m? # 1050| v1050_7(void) = ^IndirectReadSideEffect[-1] : &:r1050_2, ~m?
# 1051| r1051_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] : # 1051| r1051_1(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
# 1051| r1051_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1051:31] : # 1051| r1051_2(glval<decltype([...](...){...})>) = VariableAddress[#temp1051:31] :
# 1051| mu1051_3(decltype([...](...){...})) = Uninitialized[#temp1051:31] : &:r1051_2 # 1051| mu1051_3(decltype([...](...){...})) = Uninitialized[#temp1051:31] : &:r1051_2
@@ -5766,7 +5765,7 @@ ir.cpp:
# 1052| r1052_4(float) = Constant[5.0] : # 1052| r1052_4(float) = Constant[5.0] :
# 1052| r1052_5(char) = Call[operator()] : func:r1052_3, this:r1052_2, 0:r1052_4 # 1052| r1052_5(char) = Call[operator()] : func:r1052_3, this:r1052_2, 0:r1052_4
# 1052| mu1052_6(unknown) = ^CallSideEffect : ~m? # 1052| mu1052_6(unknown) = ^CallSideEffect : ~m?
# 1052| v1052_7(void) = ^BufferReadSideEffect[-1] : &:r1052_2, ~m? # 1052| v1052_7(void) = ^IndirectReadSideEffect[-1] : &:r1052_2, ~m?
# 1053| r1053_1(glval<int>) = VariableAddress[r] : # 1053| r1053_1(glval<int>) = VariableAddress[r] :
# 1053| r1053_2(glval<int>) = VariableAddress[x] : # 1053| r1053_2(glval<int>) = VariableAddress[x] :
# 1053| r1053_3(int) = Load[x] : &:r1053_2, ~m? # 1053| r1053_3(int) = Load[x] : &:r1053_2, ~m?
@@ -5804,7 +5803,7 @@ ir.cpp:
# 1055| r1055_4(float) = Constant[6.0] : # 1055| r1055_4(float) = Constant[6.0] :
# 1055| r1055_5(char) = Call[operator()] : func:r1055_3, this:r1055_2, 0:r1055_4 # 1055| r1055_5(char) = Call[operator()] : func:r1055_3, this:r1055_2, 0:r1055_4
# 1055| mu1055_6(unknown) = ^CallSideEffect : ~m? # 1055| mu1055_6(unknown) = ^CallSideEffect : ~m?
# 1055| v1055_7(void) = ^BufferReadSideEffect[-1] : &:r1055_2, ~m? # 1055| v1055_7(void) = ^IndirectReadSideEffect[-1] : &:r1055_2, ~m?
# 1056| v1056_1(void) = NoOp : # 1056| v1056_1(void) = NoOp :
# 1040| v1040_10(void) = ReturnIndirection[s] : &:r1040_8, ~m? # 1040| v1040_10(void) = ReturnIndirection[s] : &:r1040_8, ~m?
# 1040| v1040_11(void) = ReturnVoid : # 1040| v1040_11(void) = ReturnVoid :
@@ -5869,7 +5868,7 @@ ir.cpp:
# 1043| r1043_16(glval<unknown>) = FunctionAddress[c_str] : # 1043| r1043_16(glval<unknown>) = FunctionAddress[c_str] :
# 1043| r1043_17(char *) = Call[c_str] : func:r1043_16, this:r1043_15 # 1043| r1043_17(char *) = Call[c_str] : func:r1043_16, this:r1043_15
# 1043| mu1043_18(unknown) = ^CallSideEffect : ~m? # 1043| mu1043_18(unknown) = ^CallSideEffect : ~m?
# 1043| v1043_19(void) = ^BufferReadSideEffect[-1] : &:r1043_15, ~m? # 1043| v1043_19(void) = ^IndirectReadSideEffect[-1] : &:r1043_15, ~m?
# 1043| r1043_20(glval<unknown>) = VariableAddress[#this] : # 1043| r1043_20(glval<unknown>) = VariableAddress[#this] :
# 1043| r1043_21(lambda [] type at line 1043, col. 21 *) = Load[#this] : &:r1043_20, ~m? # 1043| r1043_21(lambda [] type at line 1043, col. 21 *) = Load[#this] : &:r1043_20, ~m?
# 1043| r1043_22(glval<int &>) = FieldAddress[x] : r1043_21 # 1043| r1043_22(glval<int &>) = FieldAddress[x] : r1043_21
@@ -5921,7 +5920,7 @@ ir.cpp:
# 1045| r1045_14(glval<unknown>) = FunctionAddress[c_str] : # 1045| r1045_14(glval<unknown>) = FunctionAddress[c_str] :
# 1045| r1045_15(char *) = Call[c_str] : func:r1045_14, this:r1045_13 # 1045| r1045_15(char *) = Call[c_str] : func:r1045_14, this:r1045_13
# 1045| mu1045_16(unknown) = ^CallSideEffect : ~m? # 1045| mu1045_16(unknown) = ^CallSideEffect : ~m?
# 1045| v1045_17(void) = ^BufferReadSideEffect[-1] : &:r1045_13, ~m? # 1045| v1045_17(void) = ^IndirectReadSideEffect[-1] : &:r1045_13, ~m?
# 1045| r1045_18(glval<unknown>) = VariableAddress[#this] : # 1045| r1045_18(glval<unknown>) = VariableAddress[#this] :
# 1045| r1045_19(lambda [] type at line 1045, col. 21 *) = Load[#this] : &:r1045_18, ~m? # 1045| r1045_19(lambda [] type at line 1045, col. 21 *) = Load[#this] : &:r1045_18, ~m?
# 1045| r1045_20(glval<int>) = FieldAddress[x] : r1045_19 # 1045| r1045_20(glval<int>) = FieldAddress[x] : r1045_19
@@ -5955,7 +5954,7 @@ ir.cpp:
# 1047| r1047_16(glval<unknown>) = FunctionAddress[c_str] : # 1047| r1047_16(glval<unknown>) = FunctionAddress[c_str] :
# 1047| r1047_17(char *) = Call[c_str] : func:r1047_16, this:r1047_15 # 1047| r1047_17(char *) = Call[c_str] : func:r1047_16, this:r1047_15
# 1047| mu1047_18(unknown) = ^CallSideEffect : ~m? # 1047| mu1047_18(unknown) = ^CallSideEffect : ~m?
# 1047| v1047_19(void) = ^BufferReadSideEffect[-1] : &:r1047_15, ~m? # 1047| v1047_19(void) = ^IndirectReadSideEffect[-1] : &:r1047_15, ~m?
# 1047| r1047_20(int) = Constant[0] : # 1047| r1047_20(int) = Constant[0] :
# 1047| r1047_21(glval<char>) = PointerAdd[1] : r1047_17, r1047_20 # 1047| r1047_21(glval<char>) = PointerAdd[1] : r1047_17, r1047_20
# 1047| r1047_22(char) = Load[?] : &:r1047_21, ~m? # 1047| r1047_22(char) = Load[?] : &:r1047_21, ~m?
@@ -6003,7 +6002,7 @@ ir.cpp:
# 1049| r1049_14(glval<unknown>) = FunctionAddress[c_str] : # 1049| r1049_14(glval<unknown>) = FunctionAddress[c_str] :
# 1049| r1049_15(char *) = Call[c_str] : func:r1049_14, this:r1049_13 # 1049| r1049_15(char *) = Call[c_str] : func:r1049_14, this:r1049_13
# 1049| mu1049_16(unknown) = ^CallSideEffect : ~m? # 1049| mu1049_16(unknown) = ^CallSideEffect : ~m?
# 1049| v1049_17(void) = ^BufferReadSideEffect[-1] : &:r1049_13, ~m? # 1049| v1049_17(void) = ^IndirectReadSideEffect[-1] : &:r1049_13, ~m?
# 1049| r1049_18(int) = Constant[0] : # 1049| r1049_18(int) = Constant[0] :
# 1049| r1049_19(glval<char>) = PointerAdd[1] : r1049_15, r1049_18 # 1049| r1049_19(glval<char>) = PointerAdd[1] : r1049_15, r1049_18
# 1049| r1049_20(char) = Load[?] : &:r1049_19, ~m? # 1049| r1049_20(char) = Load[?] : &:r1049_19, ~m?
@@ -6034,7 +6033,7 @@ ir.cpp:
# 1051| r1051_16(glval<unknown>) = FunctionAddress[c_str] : # 1051| r1051_16(glval<unknown>) = FunctionAddress[c_str] :
# 1051| r1051_17(char *) = Call[c_str] : func:r1051_16, this:r1051_15 # 1051| r1051_17(char *) = Call[c_str] : func:r1051_16, this:r1051_15
# 1051| mu1051_18(unknown) = ^CallSideEffect : ~m? # 1051| mu1051_18(unknown) = ^CallSideEffect : ~m?
# 1051| v1051_19(void) = ^BufferReadSideEffect[-1] : &:r1051_15, ~m? # 1051| v1051_19(void) = ^IndirectReadSideEffect[-1] : &:r1051_15, ~m?
# 1051| r1051_20(glval<unknown>) = VariableAddress[#this] : # 1051| r1051_20(glval<unknown>) = VariableAddress[#this] :
# 1051| r1051_21(lambda [] type at line 1051, col. 32 *) = Load[#this] : &:r1051_20, ~m? # 1051| r1051_21(lambda [] type at line 1051, col. 32 *) = Load[#this] : &:r1051_20, ~m?
# 1051| r1051_22(glval<int>) = FieldAddress[x] : r1051_21 # 1051| r1051_22(glval<int>) = FieldAddress[x] : r1051_21
@@ -6068,7 +6067,7 @@ ir.cpp:
# 1054| r1054_16(glval<unknown>) = FunctionAddress[c_str] : # 1054| r1054_16(glval<unknown>) = FunctionAddress[c_str] :
# 1054| r1054_17(char *) = Call[c_str] : func:r1054_16, this:r1054_15 # 1054| r1054_17(char *) = Call[c_str] : func:r1054_16, this:r1054_15
# 1054| mu1054_18(unknown) = ^CallSideEffect : ~m? # 1054| mu1054_18(unknown) = ^CallSideEffect : ~m?
# 1054| v1054_19(void) = ^BufferReadSideEffect[-1] : &:r1054_15, ~m? # 1054| v1054_19(void) = ^IndirectReadSideEffect[-1] : &:r1054_15, ~m?
# 1054| r1054_20(glval<unknown>) = VariableAddress[#this] : # 1054| r1054_20(glval<unknown>) = VariableAddress[#this] :
# 1054| r1054_21(lambda [] type at line 1054, col. 23 *) = Load[#this] : &:r1054_20, ~m? # 1054| r1054_21(lambda [] type at line 1054, col. 23 *) = Load[#this] : &:r1054_20, ~m?
# 1054| r1054_22(glval<int>) = FieldAddress[x] : r1054_21 # 1054| r1054_22(glval<int>) = FieldAddress[x] : r1054_21
@@ -6095,37 +6094,37 @@ ir.cpp:
# 1077| void RangeBasedFor(vector<int> const&) # 1077| void RangeBasedFor(vector<int> const&)
# 1077| Block 0 # 1077| Block 0
# 1077| v1077_1(void) = EnterFunction : # 1077| v1077_1(void) = EnterFunction :
# 1077| mu1077_2(unknown) = AliasedDefinition : # 1077| mu1077_2(unknown) = AliasedDefinition :
# 1077| mu1077_3(unknown) = InitializeNonLocal : # 1077| mu1077_3(unknown) = InitializeNonLocal :
# 1077| r1077_4(glval<vector<int> &>) = VariableAddress[v] : # 1077| r1077_4(glval<vector<int> &>) = VariableAddress[v] :
# 1077| mu1077_5(vector<int> &) = InitializeParameter[v] : &:r1077_4 # 1077| mu1077_5(vector<int> &) = InitializeParameter[v] : &:r1077_4
# 1077| r1077_6(vector<int> &) = Load[v] : &:r1077_4, ~m? # 1077| r1077_6(vector<int> &) = Load[v] : &:r1077_4, ~m?
# 1077| mu1077_7(unknown) = InitializeIndirection[v] : &:r1077_6 # 1077| mu1077_7(unknown) = InitializeIndirection[v] : &:r1077_6
# 1078| r1078_1(glval<vector<int> &>) = VariableAddress[(__range)] : # 1078| r1078_1(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1078| r1078_2(glval<vector<int> &>) = VariableAddress[v] : # 1078| r1078_2(glval<vector<int> &>) = VariableAddress[v] :
# 1078| r1078_3(vector<int> &) = Load[v] : &:r1078_2, ~m? # 1078| r1078_3(vector<int> &) = Load[v] : &:r1078_2, ~m?
# 1078| r1078_4(glval<vector<int>>) = CopyValue : r1078_3 # 1078| r1078_4(glval<vector<int>>) = CopyValue : r1078_3
# 1078| r1078_5(vector<int> &) = CopyValue : r1078_4 # 1078| r1078_5(vector<int> &) = CopyValue : r1078_4
# 1078| mu1078_6(vector<int> &) = Store[(__range)] : &:r1078_1, r1078_5 # 1078| mu1078_6(vector<int> &) = Store[(__range)] : &:r1078_1, r1078_5
# 1078| r1078_7(glval<iterator>) = VariableAddress[(__begin)] : # 1078| r1078_7(glval<iterator>) = VariableAddress[(__begin)] :
# 1078| r1078_8(glval<vector<int> &>) = VariableAddress[(__range)] : # 1078| r1078_8(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1078| r1078_9(vector<int> &) = Load[(__range)] : &:r1078_8, ~m? # 1078| r1078_9(vector<int> &) = Load[(__range)] : &:r1078_8, ~m?
#-----| r0_1(glval<vector<int>>) = CopyValue : r1078_9 #-----| r0_1(glval<vector<int>>) = CopyValue : r1078_9
# 1078| r1078_10(glval<unknown>) = FunctionAddress[begin] : # 1078| r1078_10(glval<unknown>) = FunctionAddress[begin] :
# 1078| r1078_11(iterator) = Call[begin] : func:r1078_10, this:r0_1 # 1078| r1078_11(iterator) = Call[begin] : func:r1078_10, this:r0_1
# 1078| mu1078_12(unknown) = ^CallSideEffect : ~m? # 1078| mu1078_12(unknown) = ^CallSideEffect : ~m?
#-----| v0_2(void) = ^BufferReadSideEffect[-1] : &:r0_1, ~m? #-----| v0_2(void) = ^IndirectReadSideEffect[-1] : &:r0_1, ~m?
# 1078| mu1078_13(iterator) = Store[(__begin)] : &:r1078_7, r1078_11 # 1078| mu1078_13(iterator) = Store[(__begin)] : &:r1078_7, r1078_11
# 1078| r1078_14(glval<iterator>) = VariableAddress[(__end)] : # 1078| r1078_14(glval<iterator>) = VariableAddress[(__end)] :
# 1078| r1078_15(glval<vector<int> &>) = VariableAddress[(__range)] : # 1078| r1078_15(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1078| r1078_16(vector<int> &) = Load[(__range)] : &:r1078_15, ~m? # 1078| r1078_16(vector<int> &) = Load[(__range)] : &:r1078_15, ~m?
#-----| r0_3(glval<vector<int>>) = CopyValue : r1078_16 #-----| r0_3(glval<vector<int>>) = CopyValue : r1078_16
# 1078| r1078_17(glval<unknown>) = FunctionAddress[end] : # 1078| r1078_17(glval<unknown>) = FunctionAddress[end] :
# 1078| r1078_18(iterator) = Call[end] : func:r1078_17, this:r0_3 # 1078| r1078_18(iterator) = Call[end] : func:r1078_17, this:r0_3
# 1078| mu1078_19(unknown) = ^CallSideEffect : ~m? # 1078| mu1078_19(unknown) = ^CallSideEffect : ~m?
#-----| v0_4(void) = ^BufferReadSideEffect[-1] : &:r0_3, ~m? #-----| v0_4(void) = ^IndirectReadSideEffect[-1] : &:r0_3, ~m?
# 1078| mu1078_20(iterator) = Store[(__end)] : &:r1078_14, r1078_18 # 1078| mu1078_20(iterator) = Store[(__end)] : &:r1078_14, r1078_18
#-----| Goto -> Block 1 #-----| Goto -> Block 1
# 1078| Block 1 # 1078| Block 1
@@ -6136,26 +6135,26 @@ ir.cpp:
# 1078| r1078_24(iterator) = Load[(__end)] : &:r1078_23, ~m? # 1078| r1078_24(iterator) = Load[(__end)] : &:r1078_23, ~m?
# 1078| r1078_25(bool) = Call[operator!=] : func:r1078_22, this:r0_5, 0:r1078_24 # 1078| r1078_25(bool) = Call[operator!=] : func:r1078_22, this:r0_5, 0:r1078_24
# 1078| mu1078_26(unknown) = ^CallSideEffect : ~m? # 1078| mu1078_26(unknown) = ^CallSideEffect : ~m?
#-----| v0_6(void) = ^BufferReadSideEffect[-1] : &:r0_5, ~m? #-----| v0_6(void) = ^IndirectReadSideEffect[-1] : &:r0_5, ~m?
# 1078| v1078_27(void) = ConditionalBranch : r1078_25 # 1078| v1078_27(void) = ConditionalBranch : r1078_25
#-----| False -> Block 5 #-----| False -> Block 5
#-----| True -> Block 2 #-----| True -> Block 2
# 1078| Block 2 # 1078| Block 2
# 1078| r1078_28(glval<int>) = VariableAddress[e] : # 1078| r1078_28(glval<int>) = VariableAddress[e] :
# 1078| r1078_29(glval<iterator>) = VariableAddress[(__begin)] : # 1078| r1078_29(glval<iterator>) = VariableAddress[(__begin)] :
#-----| r0_7(glval<iterator>) = Convert : r1078_29 #-----| r0_7(glval<iterator>) = Convert : r1078_29
# 1078| r1078_30(glval<unknown>) = FunctionAddress[operator*] : # 1078| r1078_30(glval<unknown>) = FunctionAddress[operator*] :
# 1078| r1078_31(int &) = Call[operator*] : func:r1078_30, this:r0_7 # 1078| r1078_31(int &) = Call[operator*] : func:r1078_30, this:r0_7
# 1078| mu1078_32(unknown) = ^CallSideEffect : ~m? # 1078| mu1078_32(unknown) = ^CallSideEffect : ~m?
#-----| v0_8(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~m? #-----| v0_8(void) = ^IndirectReadSideEffect[-1] : &:r0_7, ~m?
# 1078| r1078_33(int) = Load[?] : &:r1078_31, ~m? # 1078| r1078_33(int) = Load[?] : &:r1078_31, ~m?
# 1078| mu1078_34(int) = Store[e] : &:r1078_28, r1078_33 # 1078| mu1078_34(int) = Store[e] : &:r1078_28, r1078_33
# 1079| r1079_1(glval<int>) = VariableAddress[e] : # 1079| r1079_1(glval<int>) = VariableAddress[e] :
# 1079| r1079_2(int) = Load[e] : &:r1079_1, ~m? # 1079| r1079_2(int) = Load[e] : &:r1079_1, ~m?
# 1079| r1079_3(int) = Constant[0] : # 1079| r1079_3(int) = Constant[0] :
# 1079| r1079_4(bool) = CompareGT : r1079_2, r1079_3 # 1079| r1079_4(bool) = CompareGT : r1079_2, r1079_3
# 1079| v1079_5(void) = ConditionalBranch : r1079_4 # 1079| v1079_5(void) = ConditionalBranch : r1079_4
#-----| False -> Block 4 #-----| False -> Block 4
#-----| True -> Block 3 #-----| True -> Block 3
@@ -6169,36 +6168,36 @@ ir.cpp:
# 1078| r1078_37(glval<unknown>) = FunctionAddress[operator++] : # 1078| r1078_37(glval<unknown>) = FunctionAddress[operator++] :
# 1078| r1078_38(iterator &) = Call[operator++] : func:r1078_37, this:r1078_36 # 1078| r1078_38(iterator &) = Call[operator++] : func:r1078_37, this:r1078_36
# 1078| mu1078_39(unknown) = ^CallSideEffect : ~m? # 1078| mu1078_39(unknown) = ^CallSideEffect : ~m?
# 1078| v1078_40(void) = ^BufferReadSideEffect[-1] : &:r1078_36, ~m? # 1078| v1078_40(void) = ^IndirectReadSideEffect[-1] : &:r1078_36, ~m?
# 1078| mu1078_41(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1078_36 # 1078| mu1078_41(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1078_36
# 1078| r1078_42(glval<iterator>) = CopyValue : r1078_38 # 1078| r1078_42(glval<iterator>) = CopyValue : r1078_38
#-----| Goto (back edge) -> Block 1 #-----| Goto (back edge) -> Block 1
# 1084| Block 5 # 1084| Block 5
# 1084| r1084_1(glval<vector<int> &>) = VariableAddress[(__range)] : # 1084| r1084_1(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1084| r1084_2(glval<vector<int> &>) = VariableAddress[v] : # 1084| r1084_2(glval<vector<int> &>) = VariableAddress[v] :
# 1084| r1084_3(vector<int> &) = Load[v] : &:r1084_2, ~m? # 1084| r1084_3(vector<int> &) = Load[v] : &:r1084_2, ~m?
# 1084| r1084_4(glval<vector<int>>) = CopyValue : r1084_3 # 1084| r1084_4(glval<vector<int>>) = CopyValue : r1084_3
# 1084| r1084_5(vector<int> &) = CopyValue : r1084_4 # 1084| r1084_5(vector<int> &) = CopyValue : r1084_4
# 1084| mu1084_6(vector<int> &) = Store[(__range)] : &:r1084_1, r1084_5 # 1084| mu1084_6(vector<int> &) = Store[(__range)] : &:r1084_1, r1084_5
# 1084| r1084_7(glval<iterator>) = VariableAddress[(__begin)] : # 1084| r1084_7(glval<iterator>) = VariableAddress[(__begin)] :
# 1084| r1084_8(glval<vector<int> &>) = VariableAddress[(__range)] : # 1084| r1084_8(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1084| r1084_9(vector<int> &) = Load[(__range)] : &:r1084_8, ~m? # 1084| r1084_9(vector<int> &) = Load[(__range)] : &:r1084_8, ~m?
#-----| r0_9(glval<vector<int>>) = CopyValue : r1084_9 #-----| r0_9(glval<vector<int>>) = CopyValue : r1084_9
# 1084| r1084_10(glval<unknown>) = FunctionAddress[begin] : # 1084| r1084_10(glval<unknown>) = FunctionAddress[begin] :
# 1084| r1084_11(iterator) = Call[begin] : func:r1084_10, this:r0_9 # 1084| r1084_11(iterator) = Call[begin] : func:r1084_10, this:r0_9
# 1084| mu1084_12(unknown) = ^CallSideEffect : ~m? # 1084| mu1084_12(unknown) = ^CallSideEffect : ~m?
#-----| v0_10(void) = ^BufferReadSideEffect[-1] : &:r0_9, ~m? #-----| v0_10(void) = ^IndirectReadSideEffect[-1] : &:r0_9, ~m?
# 1084| mu1084_13(iterator) = Store[(__begin)] : &:r1084_7, r1084_11 # 1084| mu1084_13(iterator) = Store[(__begin)] : &:r1084_7, r1084_11
# 1084| r1084_14(glval<iterator>) = VariableAddress[(__end)] : # 1084| r1084_14(glval<iterator>) = VariableAddress[(__end)] :
# 1084| r1084_15(glval<vector<int> &>) = VariableAddress[(__range)] : # 1084| r1084_15(glval<vector<int> &>) = VariableAddress[(__range)] :
# 1084| r1084_16(vector<int> &) = Load[(__range)] : &:r1084_15, ~m? # 1084| r1084_16(vector<int> &) = Load[(__range)] : &:r1084_15, ~m?
#-----| r0_11(glval<vector<int>>) = CopyValue : r1084_16 #-----| r0_11(glval<vector<int>>) = CopyValue : r1084_16
# 1084| r1084_17(glval<unknown>) = FunctionAddress[end] : # 1084| r1084_17(glval<unknown>) = FunctionAddress[end] :
# 1084| r1084_18(iterator) = Call[end] : func:r1084_17, this:r0_11 # 1084| r1084_18(iterator) = Call[end] : func:r1084_17, this:r0_11
# 1084| mu1084_19(unknown) = ^CallSideEffect : ~m? # 1084| mu1084_19(unknown) = ^CallSideEffect : ~m?
#-----| v0_12(void) = ^BufferReadSideEffect[-1] : &:r0_11, ~m? #-----| v0_12(void) = ^IndirectReadSideEffect[-1] : &:r0_11, ~m?
# 1084| mu1084_20(iterator) = Store[(__end)] : &:r1084_14, r1084_18 # 1084| mu1084_20(iterator) = Store[(__end)] : &:r1084_14, r1084_18
#-----| Goto -> Block 6 #-----| Goto -> Block 6
# 1084| Block 6 # 1084| Block 6
@@ -6209,7 +6208,7 @@ ir.cpp:
# 1084| r1084_24(iterator) = Load[(__end)] : &:r1084_23, ~m? # 1084| r1084_24(iterator) = Load[(__end)] : &:r1084_23, ~m?
# 1084| r1084_25(bool) = Call[operator!=] : func:r1084_22, this:r0_13, 0:r1084_24 # 1084| r1084_25(bool) = Call[operator!=] : func:r1084_22, this:r0_13, 0:r1084_24
# 1084| mu1084_26(unknown) = ^CallSideEffect : ~m? # 1084| mu1084_26(unknown) = ^CallSideEffect : ~m?
#-----| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_13, ~m? #-----| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_13, ~m?
# 1084| v1084_27(void) = ConditionalBranch : r1084_25 # 1084| v1084_27(void) = ConditionalBranch : r1084_25
#-----| False -> Block 10 #-----| False -> Block 10
#-----| True -> Block 8 #-----| True -> Block 8
@@ -6219,29 +6218,29 @@ ir.cpp:
# 1084| r1084_29(glval<unknown>) = FunctionAddress[operator++] : # 1084| r1084_29(glval<unknown>) = FunctionAddress[operator++] :
# 1084| r1084_30(iterator &) = Call[operator++] : func:r1084_29, this:r1084_28 # 1084| r1084_30(iterator &) = Call[operator++] : func:r1084_29, this:r1084_28
# 1084| mu1084_31(unknown) = ^CallSideEffect : ~m? # 1084| mu1084_31(unknown) = ^CallSideEffect : ~m?
# 1084| v1084_32(void) = ^BufferReadSideEffect[-1] : &:r1084_28, ~m? # 1084| v1084_32(void) = ^IndirectReadSideEffect[-1] : &:r1084_28, ~m?
# 1084| mu1084_33(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1084_28 # 1084| mu1084_33(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1084_28
# 1084| r1084_34(glval<iterator>) = CopyValue : r1084_30 # 1084| r1084_34(glval<iterator>) = CopyValue : r1084_30
#-----| Goto (back edge) -> Block 6 #-----| Goto (back edge) -> Block 6
# 1084| Block 8 # 1084| Block 8
# 1084| r1084_35(glval<int &>) = VariableAddress[e] : # 1084| r1084_35(glval<int &>) = VariableAddress[e] :
# 1084| r1084_36(glval<iterator>) = VariableAddress[(__begin)] : # 1084| r1084_36(glval<iterator>) = VariableAddress[(__begin)] :
#-----| r0_15(glval<iterator>) = Convert : r1084_36 #-----| r0_15(glval<iterator>) = Convert : r1084_36
# 1084| r1084_37(glval<unknown>) = FunctionAddress[operator*] : # 1084| r1084_37(glval<unknown>) = FunctionAddress[operator*] :
# 1084| r1084_38(int &) = Call[operator*] : func:r1084_37, this:r0_15 # 1084| r1084_38(int &) = Call[operator*] : func:r1084_37, this:r0_15
# 1084| mu1084_39(unknown) = ^CallSideEffect : ~m? # 1084| mu1084_39(unknown) = ^CallSideEffect : ~m?
#-----| v0_16(void) = ^BufferReadSideEffect[-1] : &:r0_15, ~m? #-----| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_15, ~m?
# 1084| r1084_40(glval<int>) = CopyValue : r1084_38 # 1084| r1084_40(glval<int>) = CopyValue : r1084_38
# 1084| r1084_41(glval<int>) = Convert : r1084_40 # 1084| r1084_41(glval<int>) = Convert : r1084_40
# 1084| r1084_42(int &) = CopyValue : r1084_41 # 1084| r1084_42(int &) = CopyValue : r1084_41
# 1084| mu1084_43(int &) = Store[e] : &:r1084_35, r1084_42 # 1084| mu1084_43(int &) = Store[e] : &:r1084_35, r1084_42
# 1085| r1085_1(glval<int &>) = VariableAddress[e] : # 1085| r1085_1(glval<int &>) = VariableAddress[e] :
# 1085| r1085_2(int &) = Load[e] : &:r1085_1, ~m? # 1085| r1085_2(int &) = Load[e] : &:r1085_1, ~m?
# 1085| r1085_3(int) = Load[?] : &:r1085_2, ~m? # 1085| r1085_3(int) = Load[?] : &:r1085_2, ~m?
# 1085| r1085_4(int) = Constant[5] : # 1085| r1085_4(int) = Constant[5] :
# 1085| r1085_5(bool) = CompareLT : r1085_3, r1085_4 # 1085| r1085_5(bool) = CompareLT : r1085_3, r1085_4
# 1085| v1085_6(void) = ConditionalBranch : r1085_5 # 1085| v1085_6(void) = ConditionalBranch : r1085_5
#-----| False -> Block 7 #-----| False -> Block 7
#-----| True -> Block 9 #-----| True -> Block 9
@@ -7525,7 +7524,7 @@ ir.cpp:
# 1373| r1373_8(glval<unknown>) = FunctionAddress[c_str] : # 1373| r1373_8(glval<unknown>) = FunctionAddress[c_str] :
# 1373| r1373_9(char *) = Call[c_str] : func:r1373_8, this:r1373_7 # 1373| r1373_9(char *) = Call[c_str] : func:r1373_8, this:r1373_7
# 1373| mu1373_10(unknown) = ^CallSideEffect : ~m? # 1373| mu1373_10(unknown) = ^CallSideEffect : ~m?
# 1373| v1373_11(void) = ^BufferReadSideEffect[-1] : &:r1373_7, ~m? # 1373| v1373_11(void) = ^IndirectReadSideEffect[-1] : &:r1373_7, ~m?
# 1374| r1374_1(glval<String>) = VariableAddress[#temp1374:5] : # 1374| r1374_1(glval<String>) = VariableAddress[#temp1374:5] :
# 1374| r1374_2(glval<unknown>) = FunctionAddress[returnValue] : # 1374| r1374_2(glval<unknown>) = FunctionAddress[returnValue] :
# 1374| r1374_3(String) = Call[returnValue] : func:r1374_2 # 1374| r1374_3(String) = Call[returnValue] : func:r1374_2
@@ -7535,7 +7534,7 @@ ir.cpp:
# 1374| r1374_7(glval<unknown>) = FunctionAddress[c_str] : # 1374| r1374_7(glval<unknown>) = FunctionAddress[c_str] :
# 1374| r1374_8(char *) = Call[c_str] : func:r1374_7, this:r1374_6 # 1374| r1374_8(char *) = Call[c_str] : func:r1374_7, this:r1374_6
# 1374| mu1374_9(unknown) = ^CallSideEffect : ~m? # 1374| mu1374_9(unknown) = ^CallSideEffect : ~m?
# 1374| v1374_10(void) = ^BufferReadSideEffect[-1] : &:r1374_6, ~m? # 1374| v1374_10(void) = ^IndirectReadSideEffect[-1] : &:r1374_6, ~m?
# 1376| r1376_1(glval<String>) = VariableAddress[#temp1376:5] : # 1376| r1376_1(glval<String>) = VariableAddress[#temp1376:5] :
# 1376| r1376_2(glval<unknown>) = FunctionAddress[defaultConstruct] : # 1376| r1376_2(glval<unknown>) = FunctionAddress[defaultConstruct] :
# 1376| r1376_3(String) = Call[defaultConstruct] : func:r1376_2 # 1376| r1376_3(String) = Call[defaultConstruct] : func:r1376_2
@@ -7589,7 +7588,7 @@ ir.cpp:
# 1385| r1385_4(glval<unknown>) = FunctionAddress[method] : # 1385| r1385_4(glval<unknown>) = FunctionAddress[method] :
# 1385| v1385_5(void) = Call[method] : func:r1385_4, this:r1385_1 # 1385| v1385_5(void) = Call[method] : func:r1385_4, this:r1385_1
# 1385| mu1385_6(unknown) = ^CallSideEffect : ~m? # 1385| mu1385_6(unknown) = ^CallSideEffect : ~m?
# 1385| v1385_7(void) = ^BufferReadSideEffect[-1] : &:r1385_1, ~m? # 1385| v1385_7(void) = ^IndirectReadSideEffect[-1] : &:r1385_1, ~m?
# 1385| mu1385_8(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1385_1 # 1385| mu1385_8(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1385_1
# 1386| r1386_1(glval<destructor_only>) = VariableAddress[#temp1386:5] : # 1386| r1386_1(glval<destructor_only>) = VariableAddress[#temp1386:5] :
# 1386| r1386_2(glval<unknown>) = FunctionAddress[returnValue] : # 1386| r1386_2(glval<unknown>) = FunctionAddress[returnValue] :
@@ -7599,7 +7598,7 @@ ir.cpp:
# 1386| r1386_6(glval<unknown>) = FunctionAddress[method] : # 1386| r1386_6(glval<unknown>) = FunctionAddress[method] :
# 1386| v1386_7(void) = Call[method] : func:r1386_6, this:r1386_1 # 1386| v1386_7(void) = Call[method] : func:r1386_6, this:r1386_1
# 1386| mu1386_8(unknown) = ^CallSideEffect : ~m? # 1386| mu1386_8(unknown) = ^CallSideEffect : ~m?
# 1386| v1386_9(void) = ^BufferReadSideEffect[-1] : &:r1386_1, ~m? # 1386| v1386_9(void) = ^IndirectReadSideEffect[-1] : &:r1386_1, ~m?
# 1386| mu1386_10(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1386_1 # 1386| mu1386_10(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1386_1
# 1388| r1388_1(glval<destructor_only>) = VariableAddress[#temp1388:5] : # 1388| r1388_1(glval<destructor_only>) = VariableAddress[#temp1388:5] :
# 1388| r1388_2(glval<unknown>) = FunctionAddress[defaultConstruct] : # 1388| r1388_2(glval<unknown>) = FunctionAddress[defaultConstruct] :
@@ -7667,7 +7666,7 @@ ir.cpp:
# 1397| r1397_7(glval<unknown>) = FunctionAddress[method] : # 1397| r1397_7(glval<unknown>) = FunctionAddress[method] :
# 1397| v1397_8(void) = Call[method] : func:r1397_7, this:r1397_1 # 1397| v1397_8(void) = Call[method] : func:r1397_7, this:r1397_1
# 1397| mu1397_9(unknown) = ^CallSideEffect : ~m? # 1397| mu1397_9(unknown) = ^CallSideEffect : ~m?
# 1397| v1397_10(void) = ^BufferReadSideEffect[-1] : &:r1397_1, ~m? # 1397| v1397_10(void) = ^IndirectReadSideEffect[-1] : &:r1397_1, ~m?
# 1397| mu1397_11(copy_constructor) = ^IndirectMayWriteSideEffect[-1] : &:r1397_1 # 1397| mu1397_11(copy_constructor) = ^IndirectMayWriteSideEffect[-1] : &:r1397_1
# 1398| r1398_1(glval<copy_constructor>) = VariableAddress[#temp1398:5] : # 1398| r1398_1(glval<copy_constructor>) = VariableAddress[#temp1398:5] :
# 1398| r1398_2(glval<unknown>) = FunctionAddress[returnValue] : # 1398| r1398_2(glval<unknown>) = FunctionAddress[returnValue] :
@@ -7677,7 +7676,7 @@ ir.cpp:
# 1398| r1398_6(glval<unknown>) = FunctionAddress[method] : # 1398| r1398_6(glval<unknown>) = FunctionAddress[method] :
# 1398| v1398_7(void) = Call[method] : func:r1398_6, this:r1398_1 # 1398| v1398_7(void) = Call[method] : func:r1398_6, this:r1398_1
# 1398| mu1398_8(unknown) = ^CallSideEffect : ~m? # 1398| mu1398_8(unknown) = ^CallSideEffect : ~m?
# 1398| v1398_9(void) = ^BufferReadSideEffect[-1] : &:r1398_1, ~m? # 1398| v1398_9(void) = ^IndirectReadSideEffect[-1] : &:r1398_1, ~m?
# 1398| mu1398_10(copy_constructor) = ^IndirectMayWriteSideEffect[-1] : &:r1398_1 # 1398| mu1398_10(copy_constructor) = ^IndirectMayWriteSideEffect[-1] : &:r1398_1
# 1399| r1399_1(glval<copy_constructor>) = VariableAddress[#temp1399:5] : # 1399| r1399_1(glval<copy_constructor>) = VariableAddress[#temp1399:5] :
# 1399| r1399_2(glval<unknown>) = FunctionAddress[defaultConstruct] : # 1399| r1399_2(glval<unknown>) = FunctionAddress[defaultConstruct] :
@@ -7851,7 +7850,7 @@ ir.cpp:
# 1447| r1447_9(glval<unknown>) = FunctionAddress[f] : # 1447| r1447_9(glval<unknown>) = FunctionAddress[f] :
# 1447| r1447_10(float) = Call[f] : func:r1447_9, this:r1447_8 # 1447| r1447_10(float) = Call[f] : func:r1447_9, this:r1447_8
# 1447| mu1447_11(unknown) = ^CallSideEffect : ~m? # 1447| mu1447_11(unknown) = ^CallSideEffect : ~m?
# 1447| v1447_12(void) = ^BufferReadSideEffect[-1] : &:r1447_8, ~m? # 1447| v1447_12(void) = ^IndirectReadSideEffect[-1] : &:r1447_8, ~m?
# 1447| mu1447_13(float) = Store[f] : &:r1447_1, r1447_10 # 1447| mu1447_13(float) = Store[f] : &:r1447_1, r1447_10
# 1448| v1448_1(void) = NoOp : # 1448| v1448_1(void) = NoOp :
# 1443| v1443_4(void) = ReturnVoid : # 1443| v1443_4(void) = ReturnVoid :

View File

@@ -1059,7 +1059,7 @@ ssa.cpp:
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 # 241| m241_4(unknown) = ^CallSideEffect : ~m240_7
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 # 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4
# 241| v241_6(void) = ^BufferReadSideEffect[-1] : &:r241_1, ~m240_9 # 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 # 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7 # 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
@@ -1067,7 +1067,7 @@ ssa.cpp:
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 # 242| m242_4(unknown) = ^CallSideEffect : ~m241_5
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 # 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4
# 242| v242_6(void) = ^BufferReadSideEffect[-1] : &:r242_1, ~m241_8 # 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 # 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7 # 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
@@ -1084,7 +1084,7 @@ ssa.cpp:
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 # 244| m244_4(unknown) = ^CallSideEffect : ~m243_7
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 # 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4
# 244| v244_6(void) = ^BufferReadSideEffect[-1] : &:r244_1, ~m243_9 # 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 # 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7 # 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :

View File

@@ -1054,7 +1054,7 @@ ssa.cpp:
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 # 241| m241_4(unknown) = ^CallSideEffect : ~m240_7
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 # 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4
# 241| v241_6(void) = ^BufferReadSideEffect[-1] : &:r241_1, ~m240_9 # 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 # 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7 # 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
@@ -1062,7 +1062,7 @@ ssa.cpp:
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 # 242| m242_4(unknown) = ^CallSideEffect : ~m241_5
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 # 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4
# 242| v242_6(void) = ^BufferReadSideEffect[-1] : &:r242_1, ~m241_8 # 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 # 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7 # 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
@@ -1079,7 +1079,7 @@ ssa.cpp:
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 # 244| m244_4(unknown) = ^CallSideEffect : ~m243_7
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 # 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4
# 244| v244_6(void) = ^BufferReadSideEffect[-1] : &:r244_1, ~m243_9 # 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 # 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7 # 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :

View File

@@ -983,13 +983,13 @@ ssa.cpp:
# 241| r241_2(glval<unknown>) = FunctionAddress[g] : # 241| r241_2(glval<unknown>) = FunctionAddress[g] :
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| mu241_4(unknown) = ^CallSideEffect : ~m? # 241| mu241_4(unknown) = ^CallSideEffect : ~m?
# 241| v241_5(void) = ^BufferReadSideEffect[-1] : &:r241_1, ~m? # 241| v241_5(void) = ^IndirectReadSideEffect[-1] : &:r241_1, ~m?
# 241| mu241_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 # 241| mu241_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
# 242| r242_2(glval<unknown>) = FunctionAddress[g] : # 242| r242_2(glval<unknown>) = FunctionAddress[g] :
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| mu242_4(unknown) = ^CallSideEffect : ~m? # 242| mu242_4(unknown) = ^CallSideEffect : ~m?
# 242| v242_5(void) = ^BufferReadSideEffect[-1] : &:r242_1, ~m? # 242| v242_5(void) = ^IndirectReadSideEffect[-1] : &:r242_1, ~m?
# 242| mu242_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 # 242| mu242_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
# 243| mu243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| mu243_2(Constructible) = Uninitialized[c2] : &:r243_1
@@ -1002,7 +1002,7 @@ ssa.cpp:
# 244| r244_2(glval<unknown>) = FunctionAddress[g] : # 244| r244_2(glval<unknown>) = FunctionAddress[g] :
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| mu244_4(unknown) = ^CallSideEffect : ~m? # 244| mu244_4(unknown) = ^CallSideEffect : ~m?
# 244| v244_5(void) = ^BufferReadSideEffect[-1] : &:r244_1, ~m? # 244| v244_5(void) = ^IndirectReadSideEffect[-1] : &:r244_1, ~m?
# 244| mu244_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 # 244| mu244_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :
# 239| v239_4(void) = ReturnVoid : # 239| v239_4(void) = ReturnVoid :

View File

@@ -983,13 +983,13 @@ ssa.cpp:
# 241| r241_2(glval<unknown>) = FunctionAddress[g] : # 241| r241_2(glval<unknown>) = FunctionAddress[g] :
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| mu241_4(unknown) = ^CallSideEffect : ~m? # 241| mu241_4(unknown) = ^CallSideEffect : ~m?
# 241| v241_5(void) = ^BufferReadSideEffect[-1] : &:r241_1, ~m? # 241| v241_5(void) = ^IndirectReadSideEffect[-1] : &:r241_1, ~m?
# 241| mu241_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 # 241| mu241_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
# 242| r242_2(glval<unknown>) = FunctionAddress[g] : # 242| r242_2(glval<unknown>) = FunctionAddress[g] :
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| mu242_4(unknown) = ^CallSideEffect : ~m? # 242| mu242_4(unknown) = ^CallSideEffect : ~m?
# 242| v242_5(void) = ^BufferReadSideEffect[-1] : &:r242_1, ~m? # 242| v242_5(void) = ^IndirectReadSideEffect[-1] : &:r242_1, ~m?
# 242| mu242_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 # 242| mu242_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
# 243| mu243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| mu243_2(Constructible) = Uninitialized[c2] : &:r243_1
@@ -1002,7 +1002,7 @@ ssa.cpp:
# 244| r244_2(glval<unknown>) = FunctionAddress[g] : # 244| r244_2(glval<unknown>) = FunctionAddress[g] :
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| mu244_4(unknown) = ^CallSideEffect : ~m? # 244| mu244_4(unknown) = ^CallSideEffect : ~m?
# 244| v244_5(void) = ^BufferReadSideEffect[-1] : &:r244_1, ~m? # 244| v244_5(void) = ^IndirectReadSideEffect[-1] : &:r244_1, ~m?
# 244| mu244_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 # 244| mu244_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :
# 239| v239_4(void) = ReturnVoid : # 239| v239_4(void) = ReturnVoid :

View File

@@ -189,3 +189,30 @@ int *&conversionInFlow() {
int *&pRef = p; // has conversion in the middle of data flow int *&pRef = p; // has conversion in the middle of data flow
return pRef; // BAD [NOT DETECTED] return pRef; // BAD [NOT DETECTED]
} }
namespace std {
template<typename T>
class shared_ptr {
public:
shared_ptr() noexcept;
explicit shared_ptr(T*);
shared_ptr(const shared_ptr&) noexcept;
template<class U> shared_ptr(const shared_ptr<U>&) noexcept;
template<class U> shared_ptr(shared_ptr<U>&&) noexcept;
shared_ptr<T>& operator=(const shared_ptr<T>&) noexcept;
shared_ptr<T>& operator=(shared_ptr<T>&&) noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
T* get() const noexcept;
};
}
auto make_read_port()
{
auto port = std::shared_ptr<int>(new int);
auto ptr = port.get();
return ptr; // GOOD
}

View File

@@ -4,5 +4,4 @@
| test.c:59:3:59:5 | sc6 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:58:9:58:16 | 127 | Extreme value | | test.c:59:3:59:5 | sc6 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:58:9:58:16 | 127 | Extreme value |
| test.c:63:3:63:5 | sc8 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:62:9:62:16 | - ... | Extreme value | | test.c:63:3:63:5 | sc8 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:62:9:62:16 | - ... | Extreme value |
| test.c:75:3:75:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value | | test.c:75:3:75:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value |
| test.c:76:3:76:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value |
| test.c:124:9:124:9 | x | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:118:17:118:23 | 2147483647 | Extreme value | | test.c:124:9:124:9 | x | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:118:17:118:23 | 2147483647 | Extreme value |

View File

@@ -73,7 +73,7 @@ void test_negatives() {
sc1 = CHAR_MAX; sc1 = CHAR_MAX;
sc1 += 0; // GOOD [FALSE POSITIVE] sc1 += 0; // GOOD [FALSE POSITIVE]
sc1 += -1; // GOOD [FALSE POSITIVE] sc1 += -1; // GOOD
sc2 = CHAR_MIN; sc2 = CHAR_MIN;
sc2 += -1; // BAD [NOT DETECTED] sc2 += -1; // BAD [NOT DETECTED]
sc3 = CHAR_MIN; sc3 = CHAR_MIN;

View File

@@ -1,8 +1,5 @@
| test2.cpp:14:11:14:11 | v | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value | | test2.cpp:14:11:14:11 | v | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test2.cpp:14:11:14:11 | v | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value | | test2.cpp:14:11:14:11 | v | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
| test3.c:15:10:15:10 | x | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test3.c:11:15:11:18 | argv | User-provided value |
| test3.c:15:14:15:14 | y | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test3.c:11:15:11:18 | argv | User-provided value |
| test3.c:15:18:15:18 | z | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test3.c:11:15:11:18 | argv | User-provided value |
| test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value | | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value | | test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value | | test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |

View File

@@ -976,13 +976,11 @@ Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
TestAutobuilderScript(autobuilder, 0, 9); TestAutobuilderScript(autobuilder, 0, 9);
} }
[Fact] private void TestDotnetVersionWindows(Action action, int commandsRun)
public void TestDotnetVersionWindows()
{ {
actions.RunProcess["cmd.exe /C dotnet --list-sdks"] = 0; actions.RunProcess["cmd.exe /C dotnet --list-sdks"] = 0;
actions.RunProcessOut["cmd.exe /C dotnet --list-sdks"] = "2.1.3 [C:\\Program Files\\dotnet\\sdks]\n2.1.4 [C:\\Program Files\\dotnet\\sdks]"; actions.RunProcessOut["cmd.exe /C dotnet --list-sdks"] = "2.1.3 [C:\\Program Files\\dotnet\\sdks]\n2.1.4 [C:\\Program Files\\dotnet\\sdks]";
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -file C:\Project\install-dotnet.ps1 -Version 2.1.3 -InstallDir C:\Project\.dotnet"] = 0; action();
actions.RunProcess[@"cmd.exe /C del C:\Project\install-dotnet.ps1"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0;
@@ -1005,7 +1003,28 @@ Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.LoadXml[@"C:\Project\test.csproj"] = xml; actions.LoadXml[@"C:\Project\test.csproj"] = xml;
var autobuilder = CreateAutoBuilder(true, dotnetVersion: "2.1.3"); var autobuilder = CreateAutoBuilder(true, dotnetVersion: "2.1.3");
TestAutobuilderScript(autobuilder, 0, 7); TestAutobuilderScript(autobuilder, 0, commandsRun);
}
[Fact]
public void TestDotnetVersionWindowsWithPwsh()
{
TestDotnetVersionWindows(() =>
{
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
},
6);
}
[Fact]
public void TestDotnetVersionWindowsWithoutPwsh()
{
TestDotnetVersionWindows(() =>
{
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 1;
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
},
7);
} }
[Fact] [Fact]

View File

@@ -179,53 +179,20 @@ namespace Semmle.Autobuild.CSharp
if (builder.Actions.IsWindows()) if (builder.Actions.IsWindows())
{ {
var psScript = @"param([string]$Version, [string]$InstallDir)
add-type @"" var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy
{
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
{
return true;
}
}
""@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$Script = Invoke-WebRequest -useb 'https://dot.net/v1/dotnet-install.ps1'
$arguments = @{ BuildScript GetInstall(string pwsh) =>
Channel = 'release' new CommandBuilder(builder.Actions).
Version = $Version RunCommand(pwsh).
InstallDir = $InstallDir
}
$ScriptBlock = [scriptblock]::create("".{$($Script)} $(&{$args} @arguments)"")
Invoke-Command -ScriptBlock $ScriptBlock";
var psScriptFile = builder.Actions.PathCombine(builder.Options.RootDirectory, "install-dotnet.ps1");
builder.Actions.WriteAllText(psScriptFile, psScript);
var install = new CommandBuilder(builder.Actions).
RunCommand("powershell").
Argument("-NoProfile"). Argument("-NoProfile").
Argument("-ExecutionPolicy"). Argument("-ExecutionPolicy").
Argument("unrestricted"). Argument("unrestricted").
Argument("-file"). Argument("-Command").
Argument(psScriptFile). Argument("\"" + psCommand + "\"").
Argument("-Version"). Script;
Argument(version).
Argument("-InstallDir").
Argument(path);
var removeScript = new CommandBuilder(builder.Actions). return GetInstall("pwsh") | GetInstall("powershell");
RunCommand("del").
Argument(psScriptFile);
return install.Script & BuildScript.Try(removeScript.Script);
} }
else else
{ {

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* A new library, `Customizations.qll`, has been added, which allows for global customizations that affect all queries.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* `System.Console.Read` methods have been added as data flow sources of local user input.

View File

@@ -193,6 +193,16 @@ namespace Semmle.Extraction.CSharp.Entities
return Default.CreateGenerated(cx, parent, childIndex, location, parameter.Type.IsReferenceType ? ValueAsString(null) : null); return Default.CreateGenerated(cx, parent, childIndex, location, parameter.Type.IsReferenceType ? ValueAsString(null) : null);
} }
if (parameter.Type.SpecialType == SpecialType.System_Object)
{
// this can happen in VB.NET
cx.ExtractionError($"Extracting default argument value 'object {parameter.Name} = default' instead of 'object {parameter.Name} = {defaultValue}'. The latter is not supported in C#.",
null, null, severity: Util.Logging.Severity.Warning);
// we're generating a default expression:
return Default.CreateGenerated(cx, parent, childIndex, location, ValueAsString(null));
}
// const literal: // const literal:
return Literal.CreateGenerated(cx, parent, childIndex, parameter.Type, defaultValue, location); return Literal.CreateGenerated(cx, parent, childIndex, parameter.Type, defaultValue, location);
} }

View File

@@ -18,36 +18,6 @@ import csharp
import Dispose import Dispose
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
/**
* Gets an exception type that may be thrown during the execution of method `m`.
* Assumes any exception may be thrown by library types.
*/
Class getAThrownException(Method m) {
m.fromLibrary() and
result = any(SystemExceptionClass sc)
or
exists(ControlFlowElement cfe |
cfe = any(ThrowElement te | result = te.getExpr().getType()) or
cfe = any(MethodCall mc | result = getAThrownException(mc.getARuntimeTarget()))
|
cfe.getEnclosingCallable() = m and
not isTriedAgainstException(cfe, result)
)
}
/**
* Holds if control flow element is tried against throwing an exception of type
* `ec`.
*/
pragma[noinline]
predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
(cfe instanceof ThrowElement or cfe instanceof MethodCall) and
exists(TryStmt ts |
ts.getATriedElement() = cfe and
exists(ts.getAnExceptionHandler(ec))
)
}
private class DisposeCall extends MethodCall { private class DisposeCall extends MethodCall {
DisposeCall() { this.getTarget() instanceof DisposeMethod } DisposeCall() { this.getTarget() instanceof DisposeMethod }
} }
@@ -78,8 +48,17 @@ predicate disposeReachableFromDisposableCreation(DisposeCall disposeCall, Expr d
reachesDisposeCall(disposeCall, DataFlow::exprNode(disposableCreation)) reachesDisposeCall(disposeCall, DataFlow::exprNode(disposableCreation))
} }
class MethodCallThatMayThrow extends MethodCall { /**
MethodCallThatMayThrow() { exists(getAThrownException(this.getARuntimeTarget())) } * Holds if control flow element is tried against throwing an exception of type
* `ec`.
*/
pragma[noinline]
predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
(cfe instanceof ThrowElement or cfe instanceof MethodCall) and
exists(TryStmt ts |
ts.getATriedElement() = cfe and
exists(ts.getAnExceptionHandler(ec))
)
} }
ControlFlowElement getACatchOrFinallyClauseChild() { ControlFlowElement getACatchOrFinallyClauseChild() {
@@ -88,15 +67,71 @@ ControlFlowElement getACatchOrFinallyClauseChild() {
result = getACatchOrFinallyClauseChild().getAChild() result = getACatchOrFinallyClauseChild().getAChild()
} }
from DisposeCall disposeCall, Expr disposableCreation, MethodCallThatMayThrow callThatThrows private predicate candidate(DisposeCall disposeCall, Call call, Expr disposableCreation) {
where
disposeReachableFromDisposableCreation(disposeCall, disposableCreation) and disposeReachableFromDisposableCreation(disposeCall, disposableCreation) and
// The dispose call is not, itself, within a dispose method. // The dispose call is not, itself, within a dispose method.
not disposeCall.getEnclosingCallable() instanceof DisposeMethod and not disposeCall.getEnclosingCallable() instanceof DisposeMethod and
// Dispose call not within a finally or catch block // Dispose call not within a finally or catch block
not getACatchOrFinallyClauseChild() = disposeCall and not getACatchOrFinallyClauseChild() = disposeCall and
// At least one method call exists between the allocation and disposal that could throw // At least one method call exists between the allocation and disposal that could throw
disposableCreation.getAReachableElement() = callThatThrows and disposableCreation.getAReachableElement() = call and
callThatThrows.getAReachableElement() = disposeCall call.getAReachableElement() = disposeCall
}
private class RelevantMethod extends Method {
RelevantMethod() {
exists(Call call |
candidate(_, call, _) and
this = call.getARuntimeTarget()
)
or
exists(RelevantMethod other | other.calls(this))
}
pragma[noinline]
private RelevantMethod callsNoTry() {
exists(MethodCall mc |
result = mc.getARuntimeTarget() and
not isTriedAgainstException(mc, _) and
mc.getEnclosingCallable() = this
)
}
pragma[noinline]
private RelevantMethod callsInTry(MethodCall mc) {
result = mc.getARuntimeTarget() and
isTriedAgainstException(mc, _) and
mc.getEnclosingCallable() = this
}
/**
* Gets an exception type that may be thrown during the execution of this method.
* Assumes any exception may be thrown by library types.
*/
Class getAThrownException() {
this.fromLibrary() and
result instanceof SystemExceptionClass
or
exists(ControlFlowElement cfe |
result = cfe.(ThrowElement).getExpr().getType() and
cfe.getEnclosingCallable() = this
or
result = this.callsInTry(cfe).getAThrownException()
|
not isTriedAgainstException(cfe, result)
)
or
result = this.callsNoTry().getAThrownException()
}
}
class MethodCallThatMayThrow extends MethodCall {
MethodCallThatMayThrow() {
exists(this.getARuntimeTarget().(RelevantMethod).getAThrownException())
}
}
from DisposeCall disposeCall, Expr disposableCreation, MethodCallThatMayThrow callThatThrows
where candidate(disposeCall, callThatThrows, disposableCreation)
select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows, select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows,
callThatThrows.toString() callThatThrows.toString()

View File

@@ -0,0 +1,12 @@
/**
* Contains customizations to the standard library.
*
* This module is imported by `csharp.qll`, so any customizations defined here automatically
* apply to all queries.
*
* Typical examples of customizations include adding new subclasses of abstract classes such as
* the `RemoteFlowSource` and `SummarizedCallable` classes associated with the security queries
* to model frameworks that are not covered by the standard library.
*/
import csharp

View File

@@ -0,0 +1,11 @@
/**
* @id cs/summary/lines-of-code
* @name Total lines of code in the database
* @description The total number of lines of code across all files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
*/
import csharp
select sum(File f | f.fromSource() | f.getNumberOfLinesOfCode())

View File

@@ -2,6 +2,7 @@
* The default C# QL library. * The default C# QL library.
*/ */
import Customizations
import semmle.code.csharp.Attribute import semmle.code.csharp.Attribute
import semmle.code.csharp.Callable import semmle.code.csharp.Callable
import semmle.code.csharp.Comments import semmle.code.csharp.Comments

View File

@@ -187,5 +187,11 @@ cached
Declaration definitionOf(Use use, string kind) { Declaration definitionOf(Use use, string kind) {
result = use.getDefinition() and result = use.getDefinition() and
result.fromSource() and result.fromSource() and
kind = use.getUseType() kind = use.getUseType() and
// Some entities have many locations. This can arise for files that
// are duplicated multiple times in the database at different
// locations. Rather than letting the result set explode, we just
// exclude results that are "too ambiguous" -- we could also arbitrarily
// pick one location later on.
strictcount(result.getLocation()) < 10
} }

View File

@@ -57,7 +57,8 @@ private Element getRealParent(Expr expr) { result = expr.getParent() }
*/ */
predicate isIRConstant(Expr expr) { exists(expr.getValue()) } predicate isIRConstant(Expr expr) { exists(expr.getValue()) }
// Pulled out to work around QL-796 // Pulled out for performance. See
// https://github.com/github/codeql-coreql-team/issues/1044.
private predicate isOrphan(Expr expr) { not exists(getRealParent(expr)) } private predicate isOrphan(Expr expr) { not exists(getRealParent(expr)) }
/** /**

View File

@@ -316,6 +316,15 @@ private module SsaDefReaches {
) )
} }
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) {
exists(ssaDefRank(def, v, bb, _, _)) exists(ssaDefRank(def, v, bb, _, _))
} }
@@ -351,8 +360,7 @@ private module SsaDefReaches {
*/ */
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1
variableRead(bb2, i2, _, _)
} }
} }
@@ -434,15 +442,22 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2
bb2 = bb1 bb2 = bb1
) )
or or
exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2) defAdjacentRead(def, bb1, bb2, i2)
} }
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead( private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) { ) {
adjacentDefRead(def, bb1, i1, bb2, i2) and exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
exists(SourceVariable v | v = def.getSourceVariable() |
ssaRef(bb1, i1, v, SsaDef()) ssaRef(bb1, i1, v, SsaDef())
or or
variableRead(bb1, i1, v, true) variableRead(bb1, i1, v, true)
@@ -475,17 +490,19 @@ predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, Ba
*/ */
pragma[nomagic] pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write // Next reference to `v` inside `bb` is a write
next.definesAt(v, bb, j) and exists(int rnk, int j |
rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or or
// Can reach a write using one or more steps // Can reach a write using one or more steps
rnk = maxSsaRefRank(bb, v) and lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 | exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and varBlockReaches(def, bb, bb2) and
next.definesAt(v, bb2, j) and 1 = ssaDefRank(next, v, bb2, _, SsaDef())
1 = ssaRefRank(bb2, j, v, SsaDef())
) )
) )
} }
@@ -539,7 +556,8 @@ pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) { predicate lastRef(Definition def, BasicBlock bb, int i) {
lastRefRedef(def, bb, i, _) lastRefRedef(def, bb, i, _)
or or
exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | lastSsaRef(def, _, bb, i) and
(
// Can reach exit directly // Can reach exit directly
bb instanceof ExitBasicBlock bb instanceof ExitBasicBlock
or or

View File

@@ -49,6 +49,7 @@ module Stages {
cached cached
module DataFlowStage { module DataFlowStage {
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
@@ -78,6 +79,8 @@ module Stages {
or or
exists(CallContext cc) exists(CallContext cc)
or or
exists(any(DataFlowCall c).getEnclosingCallable())
or
forceCachingInSameStageRev() forceCachingInSameStageRev()
} }
} }

View File

@@ -192,7 +192,7 @@ class File extends Container, @file {
override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
/** Holds if this file contains source code. */ /** Holds if this file contains source code. */
predicate fromSource() { this.getNumberOfLinesOfCode() > 0 } predicate fromSource() { files(this, _, _, "cs", _) }
/** Holds if this file is a library. */ /** Holds if this file is a library. */
predicate fromLibrary() { predicate fromLibrary() {

View File

@@ -316,6 +316,15 @@ private module SsaDefReaches {
) )
} }
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) {
exists(ssaDefRank(def, v, bb, _, _)) exists(ssaDefRank(def, v, bb, _, _))
} }
@@ -351,8 +360,7 @@ private module SsaDefReaches {
*/ */
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1
variableRead(bb2, i2, _, _)
} }
} }
@@ -434,15 +442,22 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2
bb2 = bb1 bb2 = bb1
) )
or or
exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2) defAdjacentRead(def, bb1, bb2, i2)
} }
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead( private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) { ) {
adjacentDefRead(def, bb1, i1, bb2, i2) and exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
exists(SourceVariable v | v = def.getSourceVariable() |
ssaRef(bb1, i1, v, SsaDef()) ssaRef(bb1, i1, v, SsaDef())
or or
variableRead(bb1, i1, v, true) variableRead(bb1, i1, v, true)
@@ -475,17 +490,19 @@ predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, Ba
*/ */
pragma[nomagic] pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write // Next reference to `v` inside `bb` is a write
next.definesAt(v, bb, j) and exists(int rnk, int j |
rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or or
// Can reach a write using one or more steps // Can reach a write using one or more steps
rnk = maxSsaRefRank(bb, v) and lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 | exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and varBlockReaches(def, bb, bb2) and
next.definesAt(v, bb2, j) and 1 = ssaDefRank(next, v, bb2, _, SsaDef())
1 = ssaRefRank(bb2, j, v, SsaDef())
) )
) )
} }
@@ -539,7 +556,8 @@ pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) { predicate lastRef(Definition def, BasicBlock bb, int i) {
lastRefRedef(def, bb, i, _) lastRefRedef(def, bb, i, _)
or or
exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | lastSsaRef(def, _, bb, i) and
(
// Can reach exit directly // Can reach exit directly
bb instanceof ExitBasicBlock bb instanceof ExitBasicBlock
or or

View File

@@ -4,6 +4,7 @@ private import dotnet
private import DataFlowPublic private import DataFlowPublic
private import DataFlowPrivate private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.Caching
private import semmle.code.csharp.dataflow.FlowSummary private import semmle.code.csharp.dataflow.FlowSummary
private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.frameworks.system.Collections private import semmle.code.csharp.frameworks.system.Collections
@@ -69,8 +70,6 @@ private predicate transitiveCapturedCallTarget(ControlFlow::Nodes::ElementNode c
cached cached
private module Cached { private module Cached {
private import semmle.code.csharp.Caching
cached cached
newtype TReturnKind = newtype TReturnKind =
TNormalReturnKind() { Stages::DataFlowStage::forceCachingInSameStage() } or TNormalReturnKind() { Stages::DataFlowStage::forceCachingInSameStage() } or
@@ -247,6 +246,7 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlow::Node getNode(); abstract DataFlow::Node getNode();
/** Gets the enclosing callable of this call. */ /** Gets the enclosing callable of this call. */
cached
abstract DataFlowCallable getEnclosingCallable(); abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying expression, if any. */ /** Gets the underlying expression, if any. */
@@ -280,7 +280,10 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn } override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
override DataFlowCallable getEnclosingCallable() { result = cfn.getEnclosingCallable() } override DataFlowCallable getEnclosingCallable() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = cfn.getEnclosingCallable()
}
override string toString() { result = cfn.toString() } override string toString() { result = cfn.toString() }

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,11 +2133,8 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
exists(Cc cc0 | localFlowEntry(node, config) and
cc = pragma[only_bind_into](cc0) and result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node))
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3132,7 +3129,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -21,9 +21,11 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
abstract class NodeImpl extends Node { abstract class NodeImpl extends Node {
/** Do not call: use `getEnclosingCallable()` instead. */ /** Do not call: use `getEnclosingCallable()` instead. */
cached
abstract DataFlowCallable getEnclosingCallableImpl(); abstract DataFlowCallable getEnclosingCallableImpl();
/** Do not call: use `getType()` instead. */ /** Do not call: use `getType()` instead. */
cached
abstract DotNet::Type getTypeImpl(); abstract DotNet::Type getTypeImpl();
/** Gets the type of this node used for type pruning. */ /** Gets the type of this node used for type pruning. */
@@ -39,27 +41,39 @@ abstract class NodeImpl extends Node {
} }
/** Do not call: use `getControlFlowNode()` instead. */ /** Do not call: use `getControlFlowNode()` instead. */
cached
abstract ControlFlow::Node getControlFlowNodeImpl(); abstract ControlFlow::Node getControlFlowNodeImpl();
/** Do not call: use `getLocation()` instead. */ /** Do not call: use `getLocation()` instead. */
cached
abstract Location getLocationImpl(); abstract Location getLocationImpl();
/** Do not call: use `toString()` instead. */ /** Do not call: use `toString()` instead. */
cached
abstract string toStringImpl(); abstract string toStringImpl();
} }
private class ExprNodeImpl extends ExprNode, NodeImpl { private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() { override DataFlowCallable getEnclosingCallableImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getExpr().getEnclosingCallable() result = this.getExpr().getEnclosingCallable()
} }
override DotNet::Type getTypeImpl() { result = this.getExpr().getType() } override DotNet::Type getTypeImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getExpr().getType()
}
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() { this = TExprNode(result) } override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and this = TExprNode(result)
}
override Location getLocationImpl() { result = this.getExpr().getLocation() } override Location getLocationImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and result = this.getExpr().getLocation()
}
override string toStringImpl() { override string toStringImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getControlFlowNode().toString() result = this.getControlFlowNode().toString()
or or
exists(CIL::Expr e | exists(CIL::Expr e |
@@ -967,6 +981,16 @@ private module Cached {
or or
n.asExpr() = any(WithExpr we).getInitializer() n.asExpr() = any(WithExpr we).getInitializer()
} }
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNodeImpl).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNodeImpl).argumentOf(call, pos)
}
} }
import Cached import Cached
@@ -992,8 +1016,6 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
} }
abstract class ParameterNodeImpl extends NodeImpl { abstract class ParameterNodeImpl extends NodeImpl {
abstract DotNet::Parameter getParameter();
abstract predicate isParameterOf(DataFlowCallable c, int i); abstract predicate isParameterOf(DataFlowCallable c, int i);
} }
@@ -1010,11 +1032,9 @@ private module ParameterNodes {
/** Gets the SSA definition corresponding to this parameter, if any. */ /** Gets the SSA definition corresponding to this parameter, if any. */
Ssa::ExplicitDefinition getSsaDefinition() { Ssa::ExplicitDefinition getSsaDefinition() {
result.getADefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter() = result.getADefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter() =
this.getParameter() parameter
} }
override DotNet::Parameter getParameter() { result = parameter }
override predicate isParameterOf(DataFlowCallable c, int i) { c.getParameter(i) = parameter } override predicate isParameterOf(DataFlowCallable c, int i) { c.getParameter(i) = parameter }
override DataFlowCallable getEnclosingCallableImpl() { result = parameter.getCallable() } override DataFlowCallable getEnclosingCallableImpl() { result = parameter.getCallable() }
@@ -1037,8 +1057,6 @@ private module ParameterNodes {
/** Gets the callable containing this implicit instance parameter. */ /** Gets the callable containing this implicit instance parameter. */
Callable getCallable() { result = callable } Callable getCallable() { result = callable }
override DotNet::Parameter getParameter() { none() }
override predicate isParameterOf(DataFlowCallable c, int pos) { callable = c and pos = -1 } override predicate isParameterOf(DataFlowCallable c, int pos) { callable = c and pos = -1 }
override DataFlowCallable getEnclosingCallableImpl() { result = callable } override DataFlowCallable getEnclosingCallableImpl() { result = callable }
@@ -1113,8 +1131,6 @@ private module ParameterNodes {
/** Gets the captured variable that this implicit parameter models. */ /** Gets the captured variable that this implicit parameter models. */
LocalScopeVariable getVariable() { result = def.getVariable() } LocalScopeVariable getVariable() { result = def.getVariable() }
override DotNet::Parameter getParameter() { none() }
override predicate isParameterOf(DataFlowCallable c, int i) { override predicate isParameterOf(DataFlowCallable c, int i) {
i = getParameterPosition(def) and i = getParameterPosition(def) and
c = this.getEnclosingCallable() c = this.getEnclosingCallable()
@@ -1125,13 +1141,15 @@ private module ParameterNodes {
import ParameterNodes import ParameterNodes
/** A data-flow node that represents a call argument. */ /** A data-flow node that represents a call argument. */
abstract class ArgumentNode extends Node { class ArgumentNode extends Node {
/** Holds if this argument occurs at the given position in the given call. */ ArgumentNode() { argumentNode(this, _, _) }
cached
abstract predicate argumentOf(DataFlowCall call, int pos);
/** Gets the call in which this node is an argument. */ /** Holds if this argument occurs at the given position in the given call. */
final DataFlowCall getCall() { this.argumentOf(result, _) } final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
abstract private class ArgumentNodeImpl extends Node {
abstract predicate argumentOf(DataFlowCall call, int pos);
} }
private module ArgumentNodes { private module ArgumentNodes {
@@ -1149,7 +1167,7 @@ private module ArgumentNodes {
} }
/** A data-flow node that represents an explicit call argument. */ /** A data-flow node that represents an explicit call argument. */
class ExplicitArgumentNode extends ArgumentNode { class ExplicitArgumentNode extends ArgumentNodeImpl {
ExplicitArgumentNode() { ExplicitArgumentNode() {
this.asExpr() instanceof Argument this.asExpr() instanceof Argument
or or
@@ -1157,7 +1175,6 @@ private module ArgumentNodes {
} }
override predicate argumentOf(DataFlowCall call, int pos) { override predicate argumentOf(DataFlowCall call, int pos) {
Stages::DataFlowStage::forceCachingInSameStage() and
exists(ArgumentConfiguration x, Expr c, Argument arg | exists(ArgumentConfiguration x, Expr c, Argument arg |
arg = this.asExpr() and arg = this.asExpr() and
c = call.getExpr() and c = call.getExpr() and
@@ -1189,7 +1206,8 @@ private module ArgumentNodes {
* } } * } }
* ``` * ```
*/ */
class ImplicitCapturedArgumentNode extends ArgumentNode, NodeImpl, TImplicitCapturedArgumentNode { class ImplicitCapturedArgumentNode extends ArgumentNodeImpl, NodeImpl,
TImplicitCapturedArgumentNode {
private LocalScopeVariable v; private LocalScopeVariable v;
private ControlFlow::Nodes::ElementNode cfn; private ControlFlow::Nodes::ElementNode cfn;
@@ -1231,7 +1249,7 @@ private module ArgumentNodes {
* A node that corresponds to the value of an object creation (`new C()`) before * A node that corresponds to the value of an object creation (`new C()`) before
* the constructor has run. * the constructor has run.
*/ */
class MallocNode extends ArgumentNode, NodeImpl, TMallocNode { class MallocNode extends ArgumentNodeImpl, NodeImpl, TMallocNode {
private ControlFlow::Nodes::ElementNode cfn; private ControlFlow::Nodes::ElementNode cfn;
MallocNode() { this = TMallocNode(cfn) } MallocNode() { this = TMallocNode(cfn) }
@@ -1266,7 +1284,7 @@ private module ArgumentNodes {
* and that argument is itself a compatible array, for example * and that argument is itself a compatible array, for example
* `Foo(new[] { "a", "b", "c" })`. * `Foo(new[] { "a", "b", "c" })`.
*/ */
class ParamsArgumentNode extends ArgumentNode, NodeImpl, TParamsArgumentNode { class ParamsArgumentNode extends ArgumentNodeImpl, NodeImpl, TParamsArgumentNode {
private ControlFlow::Node callCfn; private ControlFlow::Node callCfn;
ParamsArgumentNode() { this = TParamsArgumentNode(callCfn) } ParamsArgumentNode() { this = TParamsArgumentNode(callCfn) }
@@ -1291,7 +1309,7 @@ private module ArgumentNodes {
override string toStringImpl() { result = "[implicit array creation] " + callCfn } override string toStringImpl() { result = "[implicit array creation] " + callCfn }
} }
private class SummaryArgumentNode extends SummaryNode, ArgumentNode { private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
private DataFlowCall c; private DataFlowCall c;
private int i; private int i;
@@ -1324,10 +1342,7 @@ private module ReturnNodes {
) )
} }
override NormalReturnKind getKind() { override NormalReturnKind getKind() { exists(result) }
any(DotNet::Callable c).canReturn(this.getExpr()) and
exists(result)
}
} }
/** /**
@@ -1744,7 +1759,10 @@ class DataFlowType extends Gvn::GvnType {
} }
/** Gets the type of `n` used for type pruning. */ /** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(NodeImpl n) { result = n.getDataFlowType() } pragma[inline]
Gvn::GvnType getNodeType(NodeImpl n) {
pragma[only_bind_into](result) = pragma[only_bind_out](n).getDataFlowType()
}
/** Gets a string representation of a `DataFlowType`. */ /** Gets a string representation of a `DataFlowType`. */
string ppReprType(DataFlowType t) { result = t.toString() } string ppReprType(DataFlowType t) { result = t.toString() }
@@ -1819,7 +1837,8 @@ private module PostUpdateNodes {
* Such a node acts as both a post-update node for the `MallocNode`, as well as * Such a node acts as both a post-update node for the `MallocNode`, as well as
* a pre-update node for the `ObjectCreationNode`. * a pre-update node for the `ObjectCreationNode`.
*/ */
class ObjectInitializerNode extends PostUpdateNode, NodeImpl, ArgumentNode, TObjectInitializerNode { class ObjectInitializerNode extends PostUpdateNode, NodeImpl, ArgumentNodeImpl,
TObjectInitializerNode {
private ObjectCreation oc; private ObjectCreation oc;
private ControlFlow::Nodes::ElementNode cfn; private ControlFlow::Nodes::ElementNode cfn;

View File

@@ -3,7 +3,6 @@ private import cil
private import dotnet private import dotnet
private import DataFlowDispatch private import DataFlowDispatch
private import DataFlowPrivate private import DataFlowPrivate
private import semmle.code.csharp.Caching
private import semmle.code.csharp.controlflow.Guards private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.Unification private import semmle.code.csharp.Unification
@@ -38,38 +37,21 @@ class Node extends TNode {
} }
/** Gets the type of this node. */ /** Gets the type of this node. */
cached final DotNet::Type getType() { result = this.(NodeImpl).getTypeImpl() }
final DotNet::Type getType() {
Stages::DataFlowStage::forceCachingInSameStage() and result = this.(NodeImpl).getTypeImpl()
}
/** Gets the enclosing callable of this node. */ /** Gets the enclosing callable of this node. */
cached
final DataFlowCallable getEnclosingCallable() { final DataFlowCallable getEnclosingCallable() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.(NodeImpl).getEnclosingCallableImpl() result = this.(NodeImpl).getEnclosingCallableImpl()
} }
/** Gets the control flow node corresponding to this node, if any. */ /** Gets the control flow node corresponding to this node, if any. */
cached final ControlFlow::Node getControlFlowNode() { result = this.(NodeImpl).getControlFlowNodeImpl() }
final ControlFlow::Node getControlFlowNode() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.(NodeImpl).getControlFlowNodeImpl()
}
/** Gets a textual representation of this node. */ /** Gets a textual representation of this node. */
cached final string toString() { result = this.(NodeImpl).toStringImpl() }
final string toString() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.(NodeImpl).toStringImpl()
}
/** Gets the location of this node. */ /** Gets the location of this node. */
cached final Location getLocation() { result = this.(NodeImpl).getLocationImpl() }
final Location getLocation() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.(NodeImpl).getLocationImpl()
}
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
@@ -81,7 +63,7 @@ class Node extends TNode {
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
} }
} }
@@ -117,18 +99,18 @@ class ExprNode extends Node {
* flow graph. * flow graph.
*/ */
class ParameterNode extends Node { class ParameterNode extends Node {
private ParameterNodeImpl p; ParameterNode() { parameterNode(this, _, _) }
ParameterNode() { this = p }
/** Gets the parameter corresponding to this node, if any. */ /** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter getParameter() { result = p.getParameter() } DotNet::Parameter getParameter() {
exists(DataFlowCallable c, int i | this.isParameterOf(c, i) and result = c.getParameter(i))
}
/** /**
* Holds if this node is the parameter of callable `c` at the specified * Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position. * (zero-based) position.
*/ */
predicate isParameterOf(DataFlowCallable c, int i) { p.isParameterOf(c, i) } predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
} }
/** A definition, viewed as a node in a data flow graph. */ /** A definition, viewed as a node in a data flow graph. */
@@ -166,6 +148,7 @@ predicate localFlowStep = localFlowStepImpl/2;
* Holds if data flows from `source` to `sink` in zero or more local * Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps. * (intra-procedural) steps.
*/ */
pragma[inline]
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/** /**

View File

@@ -446,7 +446,19 @@ module Private {
summary(c, inputContents, outputContents, preservesValue) and summary(c, inputContents, outputContents, preservesValue) and
pred = summaryNodeInputState(c, inputContents) and pred = summaryNodeInputState(c, inputContents) and
succ = summaryNodeOutputState(c, outputContents) succ = summaryNodeOutputState(c, outputContents)
|
preservesValue = true
or
preservesValue = false and not summary(c, inputContents, outputContents, true)
) )
or
// If flow through a method updates a parameter from some input A, and that
// parameter also is returned through B, then we'd like a combined flow from A
// to B as well. As an example, this simplifies modeling of fluent methods:
// for `StringBuilder.append(x)` with a specified value flow from qualifier to
// return value and taint flow from argument 0 to the qualifier, then this
// allows us to infer taint flow from argument 0 to the return value.
summaryPostUpdateNode(pred, succ) and preservesValue = true
} }
/** /**

View File

@@ -268,56 +268,146 @@ private module CallGraph {
) )
} }
/**
* A simple flow step that does not take flow through fields or flow out
* of callables into account.
*/
pragma[nomagic]
private predicate delegateFlowStep(Expr pred, Expr succ) { private predicate delegateFlowStep(Expr pred, Expr succ) {
Steps::stepClosed(pred, succ) Steps::stepClosed(pred, succ)
or or
exists(Call call, Callable callable |
callable.getUnboundDeclaration().canReturn(pred) and
call = succ
|
callable = call.getTarget() or
callable = call.getTarget().(Method).getAnOverrider+() or
callable = call.getTarget().(Method).getAnUltimateImplementor() or
callable = getARuntimeDelegateTarget(call, false)
)
or
pred = succ.(DelegateCreation).getArgument() pred = succ.(DelegateCreation).getArgument()
or or
exists(AssignableDefinition def, Assignable a |
a instanceof Field or
a instanceof Property
|
a = def.getTarget() and
succ.(AssignableRead) = a.getAnAccess() and
pred = def.getSource()
)
or
exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() |
pred = ae.getRValue() pred = ae.getRValue()
) )
} }
private predicate reachesDelegateCall(Expr e) { private predicate delegateCreationReaches(Callable c, Expr e) {
delegateCall(_, e, _) delegateCreation(e, c, _)
or or
exists(Expr mid | reachesDelegateCall(mid) | delegateFlowStep(e, mid)) exists(Expr mid |
delegateCreationReaches(c, mid) and
delegateFlowStep(mid, e)
)
} }
pragma[nomagic] private predicate reachesDelegateCall(Expr e, Call c, boolean libraryDelegateCall) {
private predicate delegateFlowStepReaches(Expr pred, Expr succ) { delegateCall(c, e, libraryDelegateCall)
delegateFlowStep(pred, succ) and or
reachesDelegateCall(succ) exists(Expr mid |
reachesDelegateCall(mid, c, libraryDelegateCall) and
delegateFlowStep(e, mid)
)
} }
private Expr delegateCallSource(Callable c) { /**
delegateCreation(result, c, _) * A "busy" flow element, that is, a node in the data-flow graph that typically
or * has a large fan-in or a large fan-out (or both).
delegateFlowStepReaches(delegateCallSource(c), result) *
* For such busy elements, we do not track flow directly from all delegate
* creations, but instead we first perform a flow analysis between busy elements,
* and then only in the end join up with delegate creations and delegate calls.
*/
abstract private class BusyFlowElement extends Element {
pragma[nomagic]
abstract Expr getAnInput();
pragma[nomagic]
abstract Expr getAnOutput();
/** Holds if this element can be reached from expression `e`. */
pragma[nomagic]
private predicate exprReaches(Expr e) {
this.reachesCall(_) and
e = this.getAnInput()
or
exists(Expr mid |
this.exprReaches(mid) and
delegateFlowStep(e, mid)
)
}
/**
* Holds if this element can reach a delegate call `c` directly without
* passing through another busy element.
*/
pragma[nomagic]
predicate delegateCall(Call c, boolean libraryDelegateCall) {
reachesDelegateCall(this.getAnOutput(), c, libraryDelegateCall)
}
pragma[nomagic]
private BusyFlowElement getASuccessor() { result.exprReaches(this.getAnOutput()) }
/**
* Holds if this element reaches another busy element `other`,
* which can reach a delegate call directly without passing
* through another busy element.
*/
pragma[nomagic]
private predicate reachesCall(BusyFlowElement other) {
this = other and
other.delegateCall(_, _)
or
this.getASuccessor().reachesCall(other)
}
/** Holds if this element is reached by a delegate creation for `c`. */
pragma[nomagic]
predicate isReachedBy(Callable c) {
exists(BusyFlowElement pred |
pred.reachesCall(this) and
delegateCreationReaches(c, pred.getAnInput())
)
}
}
private class TFieldOrProperty = @field or @property;
private class FieldOrPropertyFlow extends BusyFlowElement, Assignable, TFieldOrProperty {
final override Expr getAnInput() {
exists(Assignable target |
target = this.getUnboundDeclaration() and
result = target.getAnAssignedValue()
)
}
final override AssignableRead getAnOutput() {
exists(Assignable target |
target = this.getUnboundDeclaration() and
result = target.getAnAccess()
)
}
}
private class CallOutputFlow extends BusyFlowElement, Callable {
final override Expr getAnInput() { this.canReturn(result) }
final override Call getAnOutput() {
exists(Callable target | this = target.getUnboundDeclaration() |
target = result.getTarget() or
target = result.getTarget().(Method).getAnOverrider+() or
target = result.getTarget().(Method).getAnUltimateImplementor() or
target = getARuntimeDelegateTarget(result, false)
)
}
} }
/** Gets a run-time target for the delegate call `c`. */ /** Gets a run-time target for the delegate call `c`. */
pragma[nomagic]
Callable getARuntimeDelegateTarget(Call c, boolean libraryDelegateCall) { Callable getARuntimeDelegateTarget(Call c, boolean libraryDelegateCall) {
delegateCall(c, delegateCallSource(result), libraryDelegateCall) // directly resolvable without going through a "busy" element
exists(Expr e |
delegateCreationReaches(result, e) and
delegateCall(c, e, libraryDelegateCall)
)
or
// resolvable by going through one or more "busy" elements
exists(BusyFlowElement busy |
busy.isReachedBy(result) and
busy.delegateCall(c, libraryDelegateCall)
)
} }
} }

View File

@@ -316,6 +316,15 @@ private module SsaDefReaches {
) )
} }
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) {
exists(ssaDefRank(def, v, bb, _, _)) exists(ssaDefRank(def, v, bb, _, _))
} }
@@ -351,8 +360,7 @@ private module SsaDefReaches {
*/ */
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1
variableRead(bb2, i2, _, _)
} }
} }
@@ -434,15 +442,22 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2
bb2 = bb1 bb2 = bb1
) )
or or
exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2) defAdjacentRead(def, bb1, bb2, i2)
} }
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead( private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) { ) {
adjacentDefRead(def, bb1, i1, bb2, i2) and exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
exists(SourceVariable v | v = def.getSourceVariable() |
ssaRef(bb1, i1, v, SsaDef()) ssaRef(bb1, i1, v, SsaDef())
or or
variableRead(bb1, i1, v, true) variableRead(bb1, i1, v, true)
@@ -475,17 +490,19 @@ predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, Ba
*/ */
pragma[nomagic] pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write // Next reference to `v` inside `bb` is a write
next.definesAt(v, bb, j) and exists(int rnk, int j |
rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or or
// Can reach a write using one or more steps // Can reach a write using one or more steps
rnk = maxSsaRefRank(bb, v) and lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 | exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and varBlockReaches(def, bb, bb2) and
next.definesAt(v, bb2, j) and 1 = ssaDefRank(next, v, bb2, _, SsaDef())
1 = ssaRefRank(bb2, j, v, SsaDef())
) )
) )
} }
@@ -539,7 +556,8 @@ pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) { predicate lastRef(Definition def, BasicBlock bb, int i) {
lastRefRedef(def, bb, i, _) lastRefRedef(def, bb, i, _)
or or
exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | lastSsaRef(def, _, bb, i) and
(
// Can reach exit directly // Can reach exit directly
bb instanceof ExitBasicBlock bb instanceof ExitBasicBlock
or or

View File

@@ -316,6 +316,15 @@ private module SsaDefReaches {
) )
} }
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) {
exists(ssaDefRank(def, v, bb, _, _)) exists(ssaDefRank(def, v, bb, _, _))
} }
@@ -351,8 +360,7 @@ private module SsaDefReaches {
*/ */
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1
variableRead(bb2, i2, _, _)
} }
} }
@@ -434,15 +442,22 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2
bb2 = bb1 bb2 = bb1
) )
or or
exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2) defAdjacentRead(def, bb1, bb2, i2)
} }
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead( private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) { ) {
adjacentDefRead(def, bb1, i1, bb2, i2) and exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
exists(SourceVariable v | v = def.getSourceVariable() |
ssaRef(bb1, i1, v, SsaDef()) ssaRef(bb1, i1, v, SsaDef())
or or
variableRead(bb1, i1, v, true) variableRead(bb1, i1, v, true)
@@ -475,17 +490,19 @@ predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, Ba
*/ */
pragma[nomagic] pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write // Next reference to `v` inside `bb` is a write
next.definesAt(v, bb, j) and exists(int rnk, int j |
rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or or
// Can reach a write using one or more steps // Can reach a write using one or more steps
rnk = maxSsaRefRank(bb, v) and lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 | exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and varBlockReaches(def, bb, bb2) and
next.definesAt(v, bb2, j) and 1 = ssaDefRank(next, v, bb2, _, SsaDef())
1 = ssaRefRank(bb2, j, v, SsaDef())
) )
) )
} }
@@ -539,7 +556,8 @@ pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) { predicate lastRef(Definition def, BasicBlock bb, int i) {
lastRefRedef(def, bb, i, _) lastRefRedef(def, bb, i, _)
or or
exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | lastSsaRef(def, _, bb, i) and
(
// Can reach exit directly // Can reach exit directly
bb instanceof ExitBasicBlock bb instanceof ExitBasicBlock
or or

View File

@@ -233,71 +233,61 @@ private module Internal {
} }
pragma[noinline] pragma[noinline]
private predicate hasOverrider(OverridableCallable oc, ValueOrRefType t) { private predicate hasOverrider(OverridableCallable oc, Gvn::GvnType t) {
exists(oc.getAnOverrider(t)) exists(oc.getAnOverrider(any(ValueOrRefType t0 | Gvn::getGlobalValueNumber(t0) = t)))
} }
pragma[noinline] pragma[noinline]
private predicate hasCallable(OverridableCallable source, ValueOrRefType t, OverridableCallable c) { private predicate hasCallable(OverridableCallable source, Gvn::GvnType t, OverridableCallable c) {
c.getUnboundDeclaration() = source and c.getUnboundDeclaration() = source and
t.hasCallable(c) and any(ValueOrRefType t0 | Gvn::getGlobalValueNumber(t0) = t).hasCallable(c) and
hasOverrider(c, t) and hasOverrider(c, t) and
hasQualifierTypeOverridden0(t, _) and source = any(DispatchMethodOrAccessorCall call).getAStaticTargetExt()
hasQualifierTypeOverridden1(source, _)
}
pragma[noinline]
private Unification::ConstrainedTypeParameter getAConstrainedTypeParameterQualifierType(
DispatchMethodOrAccessorCall call
) {
result = getAPossibleType(call.getQualifier(), false)
}
pragma[noinline]
private predicate constrainedTypeParameterQualifierTypeSubsumes(
ValueOrRefType t, Unification::ConstrainedTypeParameter tp
) {
tp = getAConstrainedTypeParameterQualifierType(_) and
tp.subsumes(t)
}
pragma[noinline]
private predicate hasQualifierTypeOverridden0(ValueOrRefType t, DispatchMethodOrAccessorCall call) {
hasOverrider(_, t) and
(
exists(Type t0, Type t1 |
t0 = getAPossibleType(call.getQualifier(), false) and
t1 = [t0, t0.(Unification::UnconstrainedTypeParameter).getAnUltimatelySuppliedType()]
|
t = t1
or
Unification::subsumes(t1, t)
)
or
constrainedTypeParameterQualifierTypeSubsumes(t,
getAConstrainedTypeParameterQualifierType(call))
)
}
pragma[noinline]
private predicate hasQualifierTypeOverridden1(
OverridableCallable c, DispatchMethodOrAccessorCall call
) {
exists(OverridableCallable target | call.getAStaticTarget() = target |
c = target.getUnboundDeclaration()
or
c = target.getAnUltimateImplementor().getUnboundDeclaration()
)
} }
abstract private class DispatchMethodOrAccessorCall extends DispatchCallImpl { abstract private class DispatchMethodOrAccessorCall extends DispatchCallImpl {
pragma[noinline]
OverridableCallable getAStaticTargetExt() {
exists(OverridableCallable target | this.getAStaticTarget() = target |
result = target.getUnboundDeclaration()
or
result = target.getAnUltimateImplementor().getUnboundDeclaration()
)
}
pragma[nomagic] pragma[nomagic]
predicate hasQualifierTypeInherited(Type t) { t = getAPossibleType(this.getQualifier(), _) } predicate hasQualifierTypeInherited(Type t) { t = getAPossibleType(this.getQualifier(), _) }
pragma[noinline]
private predicate hasSubsumedQualifierType(Gvn::GvnType t) {
hasOverrider(_, t) and
exists(Type t0 |
t0 = getAPossibleType(this.getQualifier(), false) and
not t0 instanceof TypeParameter
|
t = Gvn::getGlobalValueNumber(t0)
or
Gvn::subsumes(Gvn::getGlobalValueNumber(t0), t)
)
}
pragma[noinline]
private predicate hasConstrainedTypeParameterQualifierType(
Unification::ConstrainedTypeParameter tp
) {
tp = getAPossibleType(this.getQualifier(), false)
}
pragma[noinline]
private predicate hasUnconstrainedTypeParameterQualifierType() {
getAPossibleType(this.getQualifier(), false) instanceof
Unification::UnconstrainedTypeParameter
}
pragma[nomagic] pragma[nomagic]
predicate hasQualifierTypeOverridden(ValueOrRefType t, OverridableCallable c) { predicate hasSubsumedQualifierTypeOverridden(Gvn::GvnType t, OverridableCallable c) {
hasQualifierTypeOverridden0(t, this) and this.hasSubsumedQualifierType(t) and
hasCallable(any(OverridableCallable oc | hasQualifierTypeOverridden1(oc, this)), t, c) hasCallable(any(OverridableCallable oc | oc = this.getAStaticTargetExt()), t, c)
} }
/** /**
@@ -357,12 +347,33 @@ private module Internal {
} }
pragma[nomagic] pragma[nomagic]
private Callable getASubsumedStaticTarget0(Type t) { private predicate contextArgHasConstrainedTypeParameterType(
DispatchCall ctx, Unification::ConstrainedTypeParameter tp
) {
this.contextArgHasType(ctx, tp, false)
}
pragma[nomagic]
private predicate contextArgHasUnconstrainedTypeParameterType(DispatchCall ctx) {
this.contextArgHasType(ctx, any(Unification::UnconstrainedTypeParameter t), false)
}
pragma[nomagic]
private predicate contextArgHasNonTypeParameterType(DispatchCall ctx, Gvn::GvnType t) {
exists(Type t0 |
this.contextArgHasType(ctx, t0, false) and
not t0 instanceof TypeParameter and
t = Gvn::getGlobalValueNumber(t0)
)
}
pragma[nomagic]
private Callable getASubsumedStaticTarget0(Gvn::GvnType t) {
exists(Callable staticTarget, Type declType | exists(Callable staticTarget, Type declType |
staticTarget = this.getAStaticTarget() and staticTarget = this.getAStaticTarget() and
declType = staticTarget.getDeclaringType() and declType = staticTarget.getDeclaringType() and
result = staticTarget.getUnboundDeclaration() and result = staticTarget.getUnboundDeclaration() and
Unification::subsumes(declType, t) Gvn::subsumes(Gvn::getGlobalValueNumber(declType), t)
) )
} }
@@ -375,7 +386,8 @@ private module Internal {
private Callable getASubsumedStaticTarget() { private Callable getASubsumedStaticTarget() {
result = this.getAStaticTarget() result = this.getAStaticTarget()
or or
result.getUnboundDeclaration() = this.getASubsumedStaticTarget0(result.getDeclaringType()) result.getUnboundDeclaration() =
this.getASubsumedStaticTarget0(Gvn::getGlobalValueNumber(result.getDeclaringType()))
} }
/** /**
@@ -426,6 +438,12 @@ private module Internal {
) )
} }
pragma[noinline]
NonConstructedOverridableCallable getAViableOverrider0() {
getAPossibleType(this.getQualifier(), false) instanceof TypeParameter and
result.getAConstructingCallableOrSelf() = this.getAStaticTargetExt()
}
/** /**
* Gets a callable that is defined in a subtype of the qualifier type of this * Gets a callable that is defined in a subtype of the qualifier type of this
* call, and which overrides a static target of this call. * call, and which overrides a static target of this call.
@@ -468,9 +486,22 @@ private module Internal {
*/ */
private RuntimeCallable getAViableOverrider() { private RuntimeCallable getAViableOverrider() {
exists(ValueOrRefType t, NonConstructedOverridableCallable c | exists(ValueOrRefType t, NonConstructedOverridableCallable c |
this.hasQualifierTypeOverridden(t, c.getAConstructingCallableOrSelf()) and this.hasSubsumedQualifierTypeOverridden(Gvn::getGlobalValueNumber(t),
c.getAConstructingCallableOrSelf()) and
result = c.getAnOverrider(t) result = c.getAnOverrider(t)
) )
or
exists(NonConstructedOverridableCallable c |
c = this.getAViableOverrider0() and
result = c.getAnOverrider(_)
|
this.hasUnconstrainedTypeParameterQualifierType()
or
exists(Unification::ConstrainedTypeParameter tp |
this.hasConstrainedTypeParameterQualifierType(tp) and
tp.subsumes(result.getDeclaringType())
)
)
} }
override RuntimeCallable getADynamicTarget() { override RuntimeCallable getADynamicTarget() {
@@ -510,36 +541,40 @@ private module Internal {
} }
pragma[nomagic] pragma[nomagic]
private RuntimeCallable getAViableOverriderInCallContext0( private RuntimeCallable getAViableOverriderInCallContext0(Gvn::GvnType t) {
NonConstructedOverridableCallable c, ValueOrRefType t exists(NonConstructedOverridableCallable c |
) { result = this.getAViableOverrider() and
result = this.getAViableOverrider() and this.contextArgHasType(_, _, false) and
this.contextArgHasType(_, _, false) and result = c.getAnOverrider(any(Type t0 | t = Gvn::getGlobalValueNumber(t0))) and
result = c.getAnOverrider(t) this.getAStaticTarget() = c.getAConstructingCallableOrSelf()
)
} }
pragma[nomagic] pragma[nomagic]
private RuntimeCallable getAViableOverriderInCallContext1( private predicate contextArgHasSubsumedType(DispatchCall ctx, Gvn::GvnType t) {
NonConstructedOverridableCallable c, DispatchCall ctx hasOverrider(_, t) and
) { exists(Gvn::GvnType t0 | this.contextArgHasNonTypeParameterType(ctx, t0) |
exists(ValueOrRefType t | t = t0
result = this.getAViableOverriderInCallContext0(c, t) and or
exists(Type t0, Type t1 | Gvn::subsumes(t0, t)
this.contextArgHasType(ctx, t0, false) and
t1 = [t0, t0.(Unification::UnconstrainedTypeParameter).getAnUltimatelySuppliedType()]
|
t = t1
or
Unification::subsumes(t1, t)
)
) )
} }
pragma[nomagic] pragma[nomagic]
private RuntimeCallable getAViableOverriderInCallContext(DispatchCall ctx) { private RuntimeCallable getAViableOverriderInCallContext(DispatchCall ctx) {
exists(NonConstructedOverridableCallable c | exists(Gvn::GvnType t |
result = this.getAViableOverriderInCallContext1(c, ctx) and result = this.getAViableOverriderInCallContext0(t) and
this.getAStaticTarget() = c.getAConstructingCallableOrSelf() this.contextArgHasSubsumedType(ctx, t)
)
or
result = this.getAViableOverrider() and
(
this.contextArgHasUnconstrainedTypeParameterType(ctx)
or
exists(Unification::ConstrainedTypeParameter tp |
this.contextArgHasConstrainedTypeParameterType(ctx, tp) and
tp.subsumes(result.getDeclaringType())
)
) )
} }

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