Compare commits

..

367 Commits

Author SHA1 Message Date
Dave Bartolomeo
712d71856b Merge pull request #7401 from github/release-prep/2.7.4
Release preparation for version 2.7.4
2021-12-14 16:42:33 -05:00
github-actions[bot]
59da2cdf69 Release preparation for version 2.7.4 2021-12-14 21:35:09 +00:00
Dave Bartolomeo
6664a3814a Merge pull request #7398 from github/dbartol/fix-change-notes
Fix change notes
2021-12-14 13:53:08 -05:00
Dave Bartolomeo
fa40d59332 Move older change notes to old-change-notes
Now that change notes are per-package, new change notes should be created in the `change-notes` folder under the affected pack (e.g., `cpp/ql/src/change-notes` for C++ query change notes. I've moved all of the change note files that were added before we started publishing them in packs to an `old-change-notes` directory under each language, to reduce the temptation to add new change notes there.

I'm working on a document to describe how and when to create change notes for packs separately.
2021-12-14 12:35:04 -05:00
Dave Bartolomeo
a62f181d42 Move new change notes to appropriate packs 2021-12-14 12:05:15 -05:00
Erik Krogh Kristensen
de4458346f Merge pull request #7344 from SZFsir/main
JS: Improve inter-procedural type inference for FunctionExpr
2021-12-13 21:58:53 +01:00
Nick Rolfe
dc27089714 Merge pull request #7375 from github/nickrolfe/cargo_update
Ruby: update crate versions
2021-12-13 18:16:29 +00:00
Dave Bartolomeo
7732c0885f Merge pull request #7374 from aeisenberg/aesenberg/upgrades-semver
Fix semver for upgrades references
2021-12-13 13:06:59 -05:00
Andrew Eisenberg
0669ef505e Fix semver for upgrades references
Ensure the version range is flexible enough to handle
future version changes.
2021-12-13 09:03:33 -08:00
Aditya Sharad
372f099850 Merge pull request #7323 from adityasharad/atm/perf-debugging-std-lib
JS: Performance improvements to libraries using regex matching
2021-12-13 08:53:11 -08:00
Nick Rolfe
b18f7a9bd7 Ruby: update crate versions 2021-12-13 15:37:35 +00:00
Michael Nebel
c0b61d7f73 Merge pull request #7370 from michaelnebel/csharp-mad-textreader
C#: Flow summaries for virtual members in abstract classes should also apply to overrides.
2021-12-13 15:00:54 +01:00
Alex Ford
124aac23c6 Merge pull request #7371 from github/ruby/comment-new-syntax
Ruby: use Ruby object instantiation syntax in a comment
2021-12-13 13:23:03 +00:00
Alex Ford
4ae92667e1 Ruby: use Ruby object instantiation syntax in a comment 2021-12-13 12:54:45 +00:00
Michael Nebel
ba23393c0d C#: Update test as we now also implicitly gets flow summary for StreamReader. 2021-12-13 13:51:53 +01:00
Michael Nebel
a6eba04793 C#: Convert System.IO.TextReader flow to CSV format. 2021-12-13 13:51:18 +01:00
Michael Nebel
88bb8a2704 C#: Update flow summaries test cases. 2021-12-13 13:14:49 +01:00
Michael Nebel
d699ca9aa8 C#: Flow summaries should also apply for overides or virtual members in abstract classes. 2021-12-13 13:09:40 +01:00
Michael Nebel
7ff2ee695d Merge pull request #7348 from michaelnebel/csharp-mad-as-csv-json
C#: Convert flow summaries for JSon.NET
2021-12-13 11:57:55 +01:00
JrXnm
efc9e67ec2 Update javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll
Fix multiple declare may mismatch issue

Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-12-13 18:36:06 +08:00
JrXnm
fad95d8935 Update javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll
Commit coding style suggestion

Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-12-13 18:32:11 +08:00
Michael Nebel
f32d464c0f C#: Ensure bi-directional import for External flow. 2021-12-13 10:50:49 +01:00
Michael Nebel
327cf444f4 C#: Convert Newtonsoft.JSon.Linq.JObject and Newtonsoft.JSon.Linq.JToken flow to CSV format. 2021-12-13 10:50:49 +01:00
Michael Nebel
f3c0eadbce C#: Fix the existing callableFlow for JObject to target the inherited ToString methods from JToken. 2021-12-13 10:50:49 +01:00
Michael Nebel
58f36e4b31 C#: Convert NewtonSoft.Json.JSonSerializer flow to CSV format. 2021-12-13 10:50:49 +01:00
Michael Nebel
90e49508a3 C#: Convert Newtonsoft.Json.JsonConvert flow to CSV format. 2021-12-13 10:50:48 +01:00
Michael Nebel
a4bea05fa7 Merge pull request #7342 from michaelnebel/csharp-mad-as-csv3
C#: More Flow summaries in CSV format.
2021-12-13 10:32:28 +01:00
Michael Nebel
be1e75471e C#: Ensure bi-directional import for external flow. 2021-12-13 09:23:11 +01:00
Michael Nebel
1cab177f8a C#: Convert System.Web.HttpUtility flow to CSV format. 2021-12-13 09:19:41 +01:00
Michael Nebel
0e0c3e3937 C#: Convert System.Web.HttpServerUtility flow to CSV format. 2021-12-13 09:19:41 +01:00
Michael Nebel
6301e726ee C#: Update HttpServerUtility stub with HtmlEncode method and update flow summaries test. 2021-12-13 09:19:41 +01:00
Michael Nebel
1cd37dddf5 C#: Convert System.Net.WebUtility flow to CSV format. 2021-12-13 09:19:41 +01:00
Michael Nebel
07a4f5f748 C#: Update FlowSummaries test as the bogus flow summaries for the KeyValuePair default constructor has been removed. 2021-12-13 09:19:41 +01:00
Michael Nebel
679aad138e C#: Convert System.Collections.Generic.KeyValuePair flow to CSV format. 2021-12-13 09:19:36 +01:00
Michael Nebel
42bf866fb3 C#: Convert System.Web.UI.WebControls.Textbox flow to CSV format. 2021-12-13 09:18:34 +01:00
Michael Nebel
9604ed883c C#: Convert System.NET.IPHostEntry flow to CSV format. 2021-12-13 09:17:27 +01:00
Michael Nebel
d804893a49 C#: Convert System.Net.Cookie flow to CSV format. 2021-12-13 09:16:05 +01:00
Michael Nebel
03fb244545 C#: Convert System.Web.HttpCookie flow to CSV format. 2021-12-13 09:13:14 +01:00
Michael Nebel
a6360215f3 Merge pull request #7304 from michaelnebel/csharp-mad-as-csv2
C#: Convert flow summaries to CSV format.
2021-12-13 08:56:06 +01:00
Harry Maclean
0ca9852cc8 Merge pull request #7325 from github/hmac/action-controller-private-methods
Ruby: Don't count private methods as Rails actions
2021-12-13 20:47:22 +13:00
Harry Maclean
e1d290d4c0 Ruby: Don't count private methods as Rails actions
Private instance methods on ActionController classes aren't valid
request handlers. Routing to them will raise an exception.
2021-12-13 15:36:55 +13:00
Aditya Sharad
1857de1f33 JS: Speed up detection of jQuery marker comments
Combine two regexes into a single one.
This saves up to 5s on large databases by reducing the number
of separate scans of the comments table before regex matching.

The combined regex is slightly more permissive than the
original two, since it allows a combination of the two
matched formats. A string that matches one of the original
regexes will match the combined regex.
2021-12-10 15:30:02 -08:00
Nick Rolfe
b80a84c156 Merge pull request #7341 from github/nickrolfe/cookies 2021-12-10 19:52:23 +00:00
Aditya Sharad
6a1aea740f JS: Avoid scanning individual comment lines to find generated code markers
Some subclasses of GeneratedCodeMarkerComment regex match against `getLine(_)`.
When evaluated, this results in multiple scans (one per subclass that uses it)
of all comment lines in the database, before regex matching against those lines.

To make these scans smaller, regex match against the entire comment text
without splitting them into lines.
This is achieved using `?m` (multiline) and line boundaries in the regexes.
2021-12-10 11:41:54 -08:00
Aditya Sharad
c9a87234ef JS: Factor helper predicate to improve SensitiveWrite performance 2021-12-10 11:41:53 -08:00
Andrew Eisenberg
66c1629974 Merge pull request #7285 from github/post-release-prep-2.7.3-ddd4ccbb
Post-release preparation 2.7.3
2021-12-10 09:59:45 -08:00
Nick Rolfe
b6c5b4d213 Ruby: define ActionViewCookiesCall 2021-12-10 16:36:26 +00:00
yoff
d8857c7ce8 Merge pull request #7246 from tausbn/python/import-star-flow
Python: Support flow through `import *`
2021-12-10 16:34:32 +01:00
Henry Mercer
a46787ea07 Merge pull request #7351 from github/henrymercer/js-atm-heuristic-sinks-improvements
JS: Improve handling of heuristic sinks in endpoint filters
2021-12-10 14:56:45 +00:00
Rasmus Wriedt Larsen
bd9b96e154 Merge pull request #7331 from tausbn/python-fix-bad-callsite-points-to-join
Python: Fix bad `callsite_points_to` join
2021-12-10 15:39:49 +01:00
Rasmus Wriedt Larsen
8ee020f79c Merge pull request #7332 from tausbn/python-fix-bad-scope-entry-points-to-join
Python: Fix bad `scope_entry_points_to` join
2021-12-10 15:33:13 +01:00
Henry Mercer
6e167040f5 Merge pull request #7307 from adityasharad/atm/perf-debugging
JS/ATM: Various compilation fixes and performance improvements
2021-12-10 11:00:27 +00:00
Tom Hvitved
657cd89286 Merge pull request #7347 from hvitved/cfg/more-consistency-tests
Shared CFG: Add two more consistency queries
2021-12-10 10:50:39 +01:00
Michael Nebel
afa58f5676 C#: Ensure bi-directional importing of external flow for System.Text. 2021-12-10 10:28:35 +01:00
Arthur Baars
13f7fd88f1 Merge pull request #7283 from aibaars/ruby-pattern-matching-cfg
Ruby: pattern matching: CFG
2021-12-10 10:24:38 +01:00
Anders Schack-Mulligen
634ed91904 Merge pull request #7346 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-12-10 10:12:23 +01:00
Tom Hvitved
cf42427f54 Merge pull request #7321 from hvitved/csharp/cil/unique-type
C#: Avoid CIL instructions with multiple types
2021-12-10 09:58:06 +01:00
Tom Hvitved
f7f3890b40 Merge pull request #7320 from hvitved/csharp/unknown-type
C#: Populate `UnknownType`
2021-12-10 09:57:55 +01:00
Tom Hvitved
70f76d06c7 Shared CFG: Add two more consistency queries 2021-12-10 09:56:50 +01:00
Tom Hvitved
45c0d4a3b2 Merge pull request #7343 from hvitved/cfg/consistency-test
Shared CFG: Add another consistency test
2021-12-10 09:49:05 +01:00
github-actions[bot]
7e5bfa5aa0 Add changed framework coverage reports 2021-12-10 00:09:34 +00:00
Aditya Sharad
271b23ba8f JS: Expand explanatory comment about version placeholders 2021-12-09 13:43:08 -08:00
Aditya Sharad
0c3daabc51 JS: Fix broken regex matching predicate
The receiver string and the regex were in the wrong order,
leading to test failures when looking for matching comments.
2021-12-09 13:42:33 -08:00
Chris Smowton
753d886b0d Merge pull request #6319 from haby0/java/MyBatisSqlInjection
[Java] CWE-089 MyBatis Mapper Sql Injection
2021-12-09 19:57:18 +00:00
Taus
6d247bfdf9 Merge pull request #7330 from tausbn/python-fix-bad-adjacentuseuse-join
Python: Fix bad join in SSA
2021-12-09 20:55:45 +01:00
Erik Krogh Kristensen
e7209d1ee1 Merge pull request #7216 from erik-krogh/ts45
JS: Add support for TypeScript 4.5
2021-12-09 20:33:52 +01:00
Chris Smowton
75f3ebf051 Fix OTHER XML tag 2021-12-09 17:55:03 +00:00
Chris Smowton
9f69c75c50 Fix XML tag 2021-12-09 17:44:49 +00:00
Chris Smowton
2cd70b96cd Fix doctype 2021-12-09 17:44:08 +00:00
JrXnm
1a1a7413c2 JS: Improv inter-procedural type inference for FunctionExpr 2021-12-10 01:09:49 +08:00
Michael Nebel
d60b90acd3 C#: Manual update of System.String and System.Convert flow summaries. 2021-12-09 16:34:42 +01:00
Michael Nebel
e879ca7a3b C#: Convert System.Convert flow to CSV format. 2021-12-09 16:34:42 +01:00
Michael Nebel
15b4b218c8 C#: Convert System.Nullable<> flow to CSV format. 2021-12-09 16:34:42 +01:00
Michael Nebel
bbab0e582a C#: Convert System.Lazy<> flow to CSV format. 2021-12-09 16:34:42 +01:00
Michael Nebel
9e61dfb41f C#: Convert System.Text.StringBuilder flow to CSV format. 2021-12-09 16:34:41 +01:00
Michael Nebel
5a26346ba5 C#: Allow the use of pointer types in CSV validation. 2021-12-09 16:34:41 +01:00
Michael Nebel
5376eb89b3 C#: Convert System.String flow to CSV format. 2021-12-09 16:34:41 +01:00
Michael Nebel
df482a9603 Merge pull request #7314 from michaelnebel/csharp-stubs-dataflow-global
C#: Update tests dataflow/global tests to use stubs.
2021-12-09 16:31:39 +01:00
Chris Smowton
470256da85 Copyedit 2021-12-09 15:10:07 +00:00
Tony Torralba
8bba3eb2b6 Merge pull request #6823 from atorralba/atorralba/android-notification-models
Android: Add models for `android.app.Notification` builders
2021-12-09 16:01:44 +01:00
Henry Mercer
f08f07e19e JS: Improve handling of heuristic sinks in endpoint filters
Previously heuristic sinks were always included, to avoid us filtering
them out due to not being an argument to an external library call.
In this commit we move the argument to an external library call
filtering to the query-specific endpoint filters.
This lets us filter out heuristic sinks if they match one of the other
endpoint filters, reducing FPs.
2021-12-09 15:00:54 +00:00
Chris Smowton
d0a19fffee Copyedit 2021-12-09 14:58:29 +00:00
Tom Hvitved
7e99426141 C#: Address review comments 2021-12-09 15:51:54 +01:00
Tom Hvitved
2bf5966fe3 C#: Address review comment 2021-12-09 15:44:43 +01:00
Arthur Baars
fd4915a564 Ruby: CFG: add default implementation for getAnInnerCompatibleCompletion 2021-12-09 15:23:26 +01:00
Arthur Baars
9d288c90a5 Ruby: CFG: better return type for getAMatchingSuccessorType 2021-12-09 15:23:26 +01:00
Arthur Baars
a7b3f1370f Ruby: CFG: add test case 2021-12-09 15:23:26 +01:00
Arthur Baars
d0aa307bd3 Ruby: CFG: fix multiple successors failure for default parameters 2021-12-09 15:23:26 +01:00
Tom Hvitved
b887165005 Ruby: Code review suggestions 2021-12-09 15:23:26 +01:00
Arthur Baars
3689481c18 Ruby: CFG: make Completion.isValidFor work for getSugared AST nodes 2021-12-09 15:23:26 +01:00
Arthur Baars
660e52f2bf Ruby: CFG: make VariableReferencePattern a PreOrder node 2021-12-09 15:23:26 +01:00
Arthur Baars
e9e3ef3ea2 Ruby: 'self' is not really a local variable 2021-12-09 15:23:26 +01:00
Arthur Baars
799c945299 Ruby: fix CFG for AsPattern 2021-12-09 15:23:26 +01:00
Arthur Baars
95f8f85aa2 Ruby: fix allowed completions for desugared CasePatterns 2021-12-09 15:23:26 +01:00
Arthur Baars
aacba0b522 Ruby: CFG: add test cases for pattern matching 2021-12-09 15:23:26 +01:00
Arthur Baars
513fe09dbb Treat class names in array/find/hash patterns as sub-patterns 2021-12-09 15:23:26 +01:00
Arthur Baars
d17c055139 CFG 2021-12-09 15:23:25 +01:00
Arthur Baars
44a615839d Add test case with rest variable and no prefix elements 2021-12-09 15:23:25 +01:00
Arthur Baars
f08eb8e616 Revert "Temporarily allow CFG inconsistencies"
This reverts commit dca1e34cd8.
2021-12-09 15:23:25 +01:00
Michael Nebel
69f42b9c74 C#: Update remaining tests. 2021-12-09 15:21:08 +01:00
Tony Torralba
38250b0821 Remove unnecessary implicit read step 2021-12-09 15:18:38 +01:00
Tom Hvitved
cbc96dba8a Shared CFG: Add another consistency test
Finds nodes with multiple normal successors, where one is the special simple
successor. For example, this would flag a node that has both a "simple" and
a "true" successor.
2021-12-09 15:08:19 +01:00
Tony Torralba
522a4bb9fa Propagate extras through build methods 2021-12-09 14:56:52 +01:00
yoff
8e11c2c476 Merge pull request #7259 from RasmusWL/even-more-path-injection-sinks
Python: Add more path-injection sinks from `os` and `tempfile` modules
2021-12-09 14:46:41 +01:00
Michael Nebel
992801b7cb C#: Update GetAnOutNode test. 2021-12-09 13:55:04 +01:00
Tom Hvitved
9ffa236c51 Merge pull request #7288 from hvitved/cfg/enclosing-scope
Shared CFG: Include CFG scope in `TElementNode`
2021-12-09 13:39:48 +01:00
Tony Torralba
c0c40cc05b Remove synthetic fields 2021-12-09 13:34:41 +01:00
Tony Torralba
3a3c7fc59e Fix stub 2021-12-09 13:34:41 +01:00
Tony Torralba
f209ff4f76 Use synthetic fields to improve taint precision 2021-12-09 13:34:39 +01:00
Tony Torralba
b7f7c5ba20 Change format of fluent models to make review easier 2021-12-09 13:33:19 +01:00
Tony Torralba
f63ffb0630 Add models for Notification builders 2021-12-09 13:33:17 +01:00
Tom Hvitved
069cf9d17f C#: Exclude stubs in GetAnOutNode.ql test 2021-12-09 13:33:14 +01:00
Tom Hvitved
cbd21edc99 C#: Override File::isFromSource in tests to exclude stubs 2021-12-09 13:33:14 +01:00
Michael Nebel
2f85735b6a C#: Use stubs instead of dll's in the dataflow global tests. 2021-12-09 13:25:11 +01:00
Tom Hvitved
69ba2e6f8c Merge pull request #7337 from michaelnebel/csharp-synthetic-field
C#: Introduce synthetic fields and use them in Task<>.
2021-12-09 13:18:44 +01:00
Nick Rolfe
d46564caa6 Ruby: treat ActionController#cookies as a remote flow source 2021-12-09 12:13:17 +00:00
Nick Rolfe
f6a8b9a7e5 Ruby: add cookies call to frameworks test 2021-12-09 12:07:04 +00:00
Taus
b871342e83 Python: A small further performance improvement
Unrolling the transitive closure had slightly better performance here.

Also, we exclude names of builtins, since those will be handled by a
separate case of `isDefinedLocally`.
2021-12-09 10:29:55 +00:00
Michael Nebel
13347cd102 C#: Add Ql docs to synthetic fields. 2021-12-09 10:34:31 +01:00
Michael Nebel
9f4b965202 C#: Update the flow summaries produced for Task<> after introduction of synthetic fields. 2021-12-09 10:11:49 +01:00
Michael Nebel
d70d1fbf81 C#: Add support for the use of synthetic fields in flow summary CSV. 2021-12-09 10:11:48 +01:00
Michael Nebel
a43704ab43 C#: Update dataflow/global tests based on synthetic fields. 2021-12-09 10:11:48 +01:00
Michael Nebel
063398f24d C#: Use synthetic fields for Task instead of referring to private fields. 2021-12-09 10:11:48 +01:00
Michael Nebel
60f3ff8c33 C#: Introduce type for Synthetic fields. 2021-12-09 10:11:48 +01:00
haby0
8bcbf8e30f rename isMybatisCollectionTypeSqlInjection 2021-12-09 09:16:33 +08:00
Taus
8517eff0f7 Python: Fix bad performance
A few changes, all bundled together:

- We were getting a lot of magic applied to the predicates in the
  `ImportStar` module, and this was causing needless re-evaluation.
  To address this, the easiest solution was to simply cache the entire
  module.
- In order to separate this from the dataflow analysis and make it
  dependent only on control flow, `potentialImportStarBase` was changed
  to return a `ControlFlowNode`.
- `isDefinedLocally` was defined on control flow nodes, which meant we
  were duplicating a lot of tuples due to control flow splitting, to no
  actual benefit.

Finally, there was a really bad join in `isDefinedLocally` that was
fixed by separating out a helper predicate. This is a case where we
could use a three-way join, since the join between the `Scope`, the
`name` string and the `Name` is big no matter what.

If we join `scope_defines_name` with `n.getId()`, we'll get `Name`s
belonging to irrelevant scopes.

If we join `scope_defines_name` with the enclosing scope of the `Name`
`n`, then we'll get this also for `Name`s that don't share their `getId`
with the local variable defined in the scope.

If we join `n.getId()` with `n.getScope()...` then we'll get all
enclosing scopes for each `Name`.

The last of these is what we currently have. It's not terrible, but not
great either. (Though thankfully it's rare to have lots of enclosing
scopes.)
2021-12-08 22:53:45 +00:00
Tom Hvitved
b49ca6a24c Merge pull request #7335 from hvitved/ruby/dataflow/hide-desugared-nodes
Ruby: Hide desugared nodes in data-flow paths
2021-12-08 17:39:48 +01:00
haby0
a18aad8536 Fix one 2021-12-08 21:03:17 +08:00
Anders Schack-Mulligen
38d0bb4a60 Merge pull request #7260 from hvitved/dataflow/argument-parameter-matching
Data flow: Introduce `ParameterPosition` and `ArgumentPosition`
2021-12-08 12:49:08 +01:00
haby0
1d321c692b Refactor isMybatisXmlOrAnnotationSqlInjection 2021-12-08 18:59:55 +08:00
Alex Ford
ede1503cc6 Merge pull request #7328 from github/ruby/customizations
Ruby: add `Customizations.qll` file
2021-12-08 10:54:23 +00:00
Tom Hvitved
283173ad02 Address review comments 2021-12-08 11:26:44 +01:00
Erik Krogh Kristensen
3145e8f9b7 add upgrade script 2021-12-08 10:53:47 +01:00
Erik Krogh Kristensen
1956405d17 Merge pull request #7284 from erik-krogh/myApply-part1
JS: remove paths without unmatched returns from polynomial-redos
2021-12-08 10:46:03 +01:00
Tom Hvitved
5735bb698d Ruby: Hide desugared nodes in data-flow paths 2021-12-08 09:00:16 +01:00
yoff
0e33f730b1 Merge pull request #7329 from tausbn/tausbn/python-fix-syntax-error-locations
Python: Fix syntax error locations
2021-12-07 22:45:35 +01:00
Alex Ford
ea7063f3c6 Ruby: make Customizations import private 2021-12-07 19:43:08 +00:00
Tom Hvitved
490872173a Data flow: Sync files 2021-12-07 20:29:18 +01:00
Tom Hvitved
07ca1c2ec0 Data flow: Adjust parameterMatch join-orders 2021-12-07 20:29:00 +01:00
Taus
e7c298d903 Python: Fix bad scope_entry_points_to join
From `pritomrajkhowa/LoopBound`:

```
Definitions.ql-7:PointsTo::PointsToInternal::scope_entry_points_to#ffff#antijoin_rhs#2 ........... 55.1s
```

specifically

```
(443s) Tuple counts for PointsTo::PointsToInternal::scope_entry_points_to#ffff#antijoin_rhs#2/3@74a7cart after 55.1s:
184070    ~0%        {3} r1 = JOIN PointsTo::PointsToInternal::scope_entry_points_to#ffff#shared#1 WITH Variables::GlobalVariable#class#f ON FIRST 1 OUTPUT Lhs.0 'arg2', Lhs.1 'arg0', Lhs.2 'arg1'
184070    ~0%        {3} r2 = STREAM DEDUP r1
919966523 ~2%        {4} r3 = JOIN r2 WITH Essa::EssaDefinition::getSourceVariable_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'arg0', Lhs.2 'arg1', Lhs.0 'arg2'
4281779   ~2293%     {3} r4 = JOIN r3 WITH Essa::EssaVariable::getScope_dispred#ff ON FIRST 2 OUTPUT Lhs.1 'arg0', Lhs.2 'arg1', Lhs.3 'arg2'
                    return r4
```

First, this is an `antijoin`, so there's likely some negation involved.
Also, there's mention of `GlobalVariable`, `getScope`, and
`getSourceVariable`, none of which appear in `scope_entry_points_to`, so
it's likely that something got inlined.

Taking a closer look at the predicates mentioned in the body, we spot
`undefined_variable` as a likely culprit.

Evaluating this predicate in isolation reveals that it's not terribly
big, so we could try just marking it with `pragma[noinline]` (I opted
for the slightly more solid `nomagic`) and see how that fares. I also
checked that `builtin_not_in_outer_scope` was similarly small, and
made that one un-inlineable as well.

The result? Well, I can't even show you. Both `scope_entry_points_to`
and `undefined_variable` are so fast that they don't appear in the
clause timing report (so they can at most take 3.5s each to evaluate, as
that is the smallest timing in the list).
2021-12-07 18:51:44 +00:00
Taus
b502ca1ea7 Python: Fix bad callsite_points_to join
From `pritomrajkhowa/LoopBound`:

```
Definitions.ql-7:PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#join_rhs#3 ........... 5m53s
```

specifically

```
(767s) Tuple counts for PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#join_rhs#3/3@f8f86764 after 5m53s:
832806293 ~0%     {4} r1 = JOIN PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#shared#1 WITH PointsTo::InterProceduralPointsTo::var_at_exit#fff ON FIRST 1 OUTPUT Lhs.0, Lhs.1 'arg1', Rhs.1 'arg2', Rhs.2 'arg0'
832806293 ~0%     {3} r2 = JOIN r1 WITH Essa::TEssaNodeRefinement#ffff_03#join_rhs ON FIRST 2 OUTPUT Lhs.3 'arg0', Lhs.1 'arg1', Lhs.2 'arg2'
                return r2
```

This one is a bit tricky to unpack. Where is this `shared#1` defined?

```
EVALUATE NONRECURSIVE RELATION:
SYNTHETIC PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#shared#1(int arg0, numbered_tuple arg1) :-
    SENTINEL PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#shared
    SENTINEL Definitions::EscapingAssignmentGlobalVariable#class#f
    SENTINEL Essa::TEssaNodeRefinement#ffff_03#join_rhs
    {2} r1 = JOIN PointsTo::InterProceduralPointsTo::callsite_points_to#ffff#shared WITH Definitions::EscapingAssignmentGlobalVariable#class#f ON FIRST 1 OUTPUT Lhs.0 'arg0', Lhs.1 'arg1'
    {2} r2 = STREAM DEDUP r1
    {2} r3 = JOIN r2 WITH Essa::TEssaNodeRefinement#ffff_03#join_rhs ON FIRST 2 OUTPUT Lhs.0 'arg0', Lhs.1 'arg1'
    {2} r4 = STREAM DEDUP r3
    return r4
```

Looking at `callsite_points_to`, we see a likely candidate in `srcvar`.
It is guarded with an `instanceof` check for
`EscapingAssignmentGlobalVariable` (which lines up nicely with the
sentinel on its charpred) and `getSourceVariable` is just a projection
of `TEssaNodeRefinement`.

So let's try unbinding `srcvar` to prevent an early join.

The timing is now:

```
Definitions.ql-7:PointsTo::InterProceduralPointsTo::callsite_points_to#ffff ...................... 31.3s (2554 evaluations with max 101ms in PointsTo::InterProceduralPointsTo::callsite_points_to#ffff/4@i516#581fap5w)
```
(Showing the tuple counts doesn't make sense here, since all of the
`shared` and `join_rhs` predicates have been smooshed around.)
2021-12-07 18:25:53 +00:00
Taus
a716482c1f Python: Fix bad join in SSA
On `pritomrajkhowa/LoopBound`:

```
Definitions.ql-3:SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentUseUse#ff ................. 4m35s
```

specifically

```
(376s) Tuple counts for SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentUseUse#ff/2@be04e9kp after 4m58s:
388843     ~0%     {4} r1 = JOIN Essa::TPhiFunction#fff_2#join_rhs WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::definesAt#ffff ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Rhs.2, Rhs.3
3629812090 ~1%     {7} r2 = JOIN r1 WITH SsaCompute::SsaComputeImpl::variableUse#ffff ON FIRST 1 OUTPUT Lhs.0, Rhs.2, Rhs.3, Lhs.2, Lhs.3, Lhs.1, Rhs.1 'use1'
0          ~0%     {2} r3 = JOIN r2 WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentVarRefs#fffff ON FIRST 5 OUTPUT Lhs.5, Lhs.6 'use1'
0          ~0%     {2} r4 = JOIN r3 WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::firstUse#ff ON FIRST 1 OUTPUT Lhs.1 'use1', Rhs.1 'use2'

897141     ~0%     {2} r5 = SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentUseUseSameVar#ff UNION r4
                    return r5
```

Clearly we do not want to join on the variable so soon. So we unbind it
and get

```
(78s) Tuple counts for SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentUseUse#ff/2@40e0e6uv after 434ms:
3377959 ~2%     {4} r1 = SCAN SsaCompute::SsaComputeImpl::variableUse#ffff OUTPUT In.0, In.2, In.3, In.1 'use1'
1026855 ~2%     {4} r2 = JOIN r1 WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentVarRefs#fffff ON FIRST 3 OUTPUT Lhs.0, Rhs.3, Rhs.4, Lhs.3 'use1'
129484  ~0%     {2} r3 = JOIN r2 WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::definesAt#ffff_1230#join_rhs ON FIRST 3 OUTPUT Rhs.3, Lhs.3 'use1'
0       ~0%     {2} r4 = JOIN r3 WITH Essa::TPhiFunction#fff_2#join_rhs ON FIRST 1 OUTPUT Lhs.0, Lhs.1 'use1'
0       ~0%     {2} r5 = JOIN r4 WITH SsaCompute::SsaComputeImpl::AdjacentUsesImpl::firstUse#ff ON FIRST 1 OUTPUT Lhs.1 'use1', Rhs.1 'use2'

897141  ~0%     {2} r6 = SsaCompute::SsaComputeImpl::AdjacentUsesImpl::adjacentUseUseSameVar#ff UNION r5
                return r6
```
2021-12-07 18:19:47 +00:00
Taus
59bac04d8f Python: Fix Python 2 failures 2021-12-07 18:00:46 +00:00
Taus
ffc858e34d Python: Add missing file 2021-12-07 17:29:35 +00:00
Alex Ford
bf0ecded04 Merge pull request #7326 from github/ginsbach/FixInstanceof
fix dependency cycle by removing superfluous classes
2021-12-07 17:05:26 +00:00
Taus
7437cd4d85 Python: Fix syntax error locations 2021-12-07 16:51:33 +00:00
Alex Ford
f85a47d41f Ruby: add Customizations.qll file 2021-12-07 15:37:04 +00:00
Tom Hvitved
a2dc505c26 Merge pull request #7317 from hvitved/ruby/param-node-refactor
Ruby: Restructure `ParameterNode(Impl)`
2021-12-07 16:29:49 +01:00
Tom Hvitved
5183290439 Merge pull request #7315 from hvitved/ruby/inline-flow-test
Ruby: Add `InlineFlowTest.qll`
2021-12-07 16:29:34 +01:00
Henry Mercer
322e39446d JS: Autoformat 2021-12-07 14:17:11 +00:00
Henry Mercer
016727d6b6 JS: Fix occasional duplicate body tokens
0e31439 introduces some occasional duplicate tokens due to duplicate AST
node attributes. The long-term fix is to update `CodeToFeatures.qll`,
but for the short-term, we update the concatenation to concatenate
unique (location, token) pairs.
2021-12-07 14:16:48 +00:00
Philip Ginsbach
b2c1b55c0c rephrase extensions as aliases 2021-12-07 13:09:25 +00:00
Tom Hvitved
b17a93eaad Merge pull request #7316 from hvitved/ruby/is-private-join
Ruby: Tweak `Method::isPrivate` join-orders
2021-12-07 13:58:19 +01:00
Tom Hvitved
4d797d6b3d Merge pull request #7324 from github/hmac/empty-else-cfg
Ruby: Include empty StmtSequences in CFG
2021-12-07 13:19:15 +01:00
Philip Ginsbach
da43984ba4 fix dependency cycle by removing superfluous classes 2021-12-07 11:59:04 +00:00
Rasmus Wriedt Larsen
ee23799a59 Merge pull request #7319 from RasmusWL/js-cwe-328
JS: Tag queries with CWE-328
2021-12-07 11:40:33 +01:00
Anders Schack-Mulligen
6c739b67fa Merge pull request #7318 from RasmusWL/java-cwe-328
Java: Tag queries with CWE-328
2021-12-07 11:39:48 +01:00
Erik Krogh Kristensen
3c59aa319e Merge pull request #7245 from erik-krogh/explicit-this-all-the-places
All langs: apply the explicit-this patch to all remaining code
2021-12-07 10:40:26 +01:00
Taus
7cd9369d91 Python: Autoformat 2021-12-07 09:29:24 +00:00
Taus
33a9f86f54 Python: Change integer in trois.py 2021-12-07 08:54:07 +00:00
Taus
dd33f4f4d2 Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-12-07 09:48:53 +01:00
Harry Maclean
6f42153eac Ruby: Include empty StmtSequences in CFG
Empty StmtSequences appear, for example, in the `else` branch of `if`
statements like the following:

    foo

    if cond
      bar
    else
    end

    baz

Before this change, the CFG for this code would look like this:

        foo
         │
         │
         ▼
        cond
         │
    true │
         ▼
        bar
         │
         │
         ▼
         if
         │
         │
         ▼
        baz

i.e. there is linear flow through the condition, the `then` branch, and
out of the if. This doesn't account for the possibility that the
condition is false and `bar` is not executed. After this change, the CFG
looks like this:

          foo
           │
           │
           ▼
          cond
         │    │
    true │    │ false
         ▼    │
        bar   │
         │    │
         │    │
         ▼    ▼
           if
           │
           │
           ▼
          baz

i.e. we correctly account for the `false` condition.
2021-12-07 16:01:50 +13:00
Geoffrey White
4e68a4670b Merge pull request #7322 from MathiasVP/fix-performance-of-unused-static-functions
C++: Fix performance of 'cpp/unused-static-function'.
2021-12-06 17:30:51 +00:00
Mathias Vorreiter Pedersen
4765772725 C++: Fix performance of 'cpp/unused-static-function'. 2021-12-06 16:41:10 +00:00
Tom Hvitved
243b92b28c C#: Avoid CIL instructions with multiple types 2021-12-06 14:42:41 +01:00
Tom Hvitved
60c0bcf8f7 C#: Include dup instructions in CIL ExprMissingType consistency test 2021-12-06 14:37:07 +01:00
Tom Hvitved
c39fe59a04 C#: Populate UnknownType 2021-12-06 14:09:17 +01:00
Rasmus Wriedt Larsen
7ae1047fda JS: Tag queries with CWE-328
CWE-328: Use of Weak Hash, see https://cwe.mitre.org/data/definitions/328.html
2021-12-06 14:02:24 +01:00
Rasmus Wriedt Larsen
ff9ed0d4fb Java: Tag queries with CWE-328
CWE-328: Use of Weak Hash, see https://cwe.mitre.org/data/definitions/328.html

Since weak hash functions (md5/sha1) are considered for the
`java/weak-cryptographic-algorithm` query. See
caeeebf572/java/ql/lib/semmle/code/java/security/Encryption.qll (L148)

To keep things consistent between `java/weak-cryptographic-algorithm`
and `java/potentially-weak-cryptographic-algorithm`, I also added the
tag to the latter.
2021-12-06 13:59:00 +01:00
Tom Hvitved
5dbbb86d46 Ruby: Restructure ParameterNode(Impl) 2021-12-06 13:43:19 +01:00
Tom Hvitved
728e3abee5 Ruby: Tweak Method::isPrivate join-orders 2021-12-06 13:36:48 +01:00
Tom Hvitved
36569f997f Ruby: Add InlineFlowTest.qll 2021-12-06 13:35:07 +01:00
Mathias Vorreiter Pedersen
6b1ac73a46 Merge pull request #7177 from ihsinme/ihsinme-patch-6141
fix request for cpp exceptions
2021-12-06 09:24:59 +00:00
Anders Schack-Mulligen
de1269f18f Merge pull request #7308 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-12-06 09:58:49 +01:00
github-actions[bot]
c46ede02e6 Add changed framework coverage reports 2021-12-06 00:09:47 +00:00
Alex Ford
6adfea2365 Merge pull request #7163 from github/ruby/file-reader-extend
Ruby: Extend `FileSystemReadAccess` to include more potential sources of input from the filesystem
2021-12-05 23:32:43 +00:00
haby0
daf6a4ce07 Partial modification 2 2021-12-04 17:45:02 +08:00
Aditya Sharad
f68a40f82b JS: Simplify calculation of token features for endpoints
Use a `strictcount` to identify whether there is exactly one feature or not.
If so, we use it. If not, we use the empty string.
Add context to ensure we filter the set of data flow nodes down to only
the set of endpoint nodes.

This performance optimisation avoids calculating the Cartesian product
of data flow nodes and feature names, but it does not avoid calculating
the (slightly smaller) Cartesian product of endpoint nodes and feature names.
Product size = number of endpoint nodes * number of feature names.
At time of writing there are 8 feature names.
2021-12-03 14:20:27 -08:00
Aditya Sharad
fac2769d85 JS: Replace an exists+concat with an equivalent strictconcat 2021-12-03 14:20:26 -08:00
Aditya Sharad
0e31439b7e JS: Simplify aggregation of tokens into entity strings
Change the cutoff logic from `count` to `strictcount`, since we know it only applies
to a non-empty set of results.

Use a single `strictconcat` aggregate to combine tokens in order of location,
instead of computing a `rank` followed by a `concat`.

Strictness introduces a slight change of behaviour because missing tokens will now result
in no results from the predicate rather than an empty feature string.
2021-12-03 14:20:26 -08:00
Aditya Sharad
2a3b5fc2b2 JS: Performance optimisation for matching framework libraries with their marker comments
The `matchMarkerComment` predicate performs badly on any codebase with
a moderately large number of comments, because the current implementation
has to first compute the Cartesian product between the set of comments
and the set of framework library comment regexes.

Instead, match first against a single regex:
the union of all framework library comment regexes.
This computes a more benign Cartesian product, the same size as the set of comments.

See inline comments for more details.
2021-12-03 14:20:26 -08:00
Aditya Sharad
d0840afb80 JS: Fix compilation errors in EndpointFeatures library
Use the LabelParameter API instead of manually constructing the edge label.
2021-12-03 14:20:17 -08:00
Arthur Baars
9f48ae656f Merge pull request #7306 from aibaars/ruby-parenthesized-pattern
Ruby: parenthesized patterns
2021-12-03 19:18:09 +01:00
Arthur Baars
0805daaa56 Update ruby/ql/lib/codeql/ruby/ast/Pattern.qll
Add missing backticks
2021-12-03 18:44:21 +01:00
Arthur Baars
51998294ad Ruby: add AST classes for parenthesized patterns 2021-12-03 18:13:53 +01:00
Tony Torralba
4ae99592a3 Merge pull request #6801 from atorralba/atorralba/android_slice_models
Android: Add `androidx.slice.builders` models
2021-12-03 17:44:09 +01:00
Arthur Baars
205233b42f Add trivial upgrade 2021-12-03 17:04:00 +01:00
Arthur Baars
3e1ebb954f Ruby: update generated dbscheme and library 2021-12-03 17:02:08 +01:00
Arthur Baars
0cec59e043 Ruby: update tree-sitter grammar 2021-12-03 17:01:12 +01:00
Tony Torralba
8ffa195538 Merge branch 'main' into atorralba/android_slice_models 2021-12-03 16:59:33 +01:00
Nick Rolfe
5a2ef8321c Merge pull request #7120 from github/nickrolfe/regexp_g_anchor
Ruby/Python: parse anchors in regexes as special characters
2021-12-03 15:24:38 +00:00
Michael Nebel
4128f56aa9 Merge pull request #7289 from michaelnebel/csharp-mad-as-csv
C#: Convert some of the existing flow summaries to CSV
2021-12-03 15:09:36 +01:00
haby0
6c6113b85b Partial modification 2021-12-03 18:59:24 +08:00
Arthur Baars
802faf1197 Merge pull request #7296 from intrigus-lgtm/patch-7
Fix QL Doc typo.
2021-12-03 11:54:22 +01:00
Michael Nebel
7ad52e1365 C#: Address review comments from hvitved. 2021-12-03 11:12:31 +01:00
Michael Nebel
f00b62df76 C#: Convert System.Uri flow to CSV format. 2021-12-03 11:10:24 +01:00
Michael Nebel
90baef83ee C#: Add flow summaries for another TryParse method in System.Boolean. 2021-12-03 11:10:24 +01:00
Michael Nebel
8eb041c172 C#: Convert System.Boolean flow to CSV format. 2021-12-03 11:10:24 +01:00
Tom Hvitved
520f598d49 Merge pull request #7301 from hvitved/ruby/cfg-disjunct-test
Ruby: Add CFG test for `||`
2021-12-03 09:57:40 +01:00
Tom Hvitved
d9704d7b39 Ruby: Adapt to shared CFG changes 2021-12-03 09:37:41 +01:00
Tom Hvitved
42f6dfc197 Sync files 2021-12-03 09:37:41 +01:00
Tom Hvitved
404f4a81a7 C#: Include CFG scope in TElementNode 2021-12-03 09:37:41 +01:00
Tom Hvitved
50dd4e7ee7 Ruby: Add CFG test for || 2021-12-03 09:16:11 +01:00
Arthur Baars
f2800abee4 Merge pull request #7299 from github/nickrolfe/clippy_fixes
Ruby: extractor: fix warnings from Clippy
2021-12-02 18:52:22 +01:00
Taus
7f44cebed7 Python: Add missing hidden flow
The easiest way to implement this was to change the definition of
`module_export` to account for chains of `import *`. We reuse the
machinery from `ImportStar.qll` for this, naturally.
2021-12-02 17:11:56 +00:00
Taus
4138296ec6 Python: Add test for "hidden" import * flow
TL;DR: We were missing out on flow in the following situation:

`mod1.py`:
```python
foo = SOURCE
```

`mod2.py`:
```python
from mod1 import *
```

`test.py`:
```python
from mod2 import foo
SINK(foo)
```

This is because there's no node at which a read of `foo` takes place
within `test.py`, and so the added reads make no difference.

Unfortunately, this means the previous test was a bit too simplistic,
since it only looks for module variable reads and writes. Because of
this, we change the test to be a more traditional "all flow" style
(though restricted to `CfgNode`s).
2021-12-02 17:05:54 +00:00
Nick Rolfe
991d659cb2 Ruby: use unwrap_or_else to construct object only when needed 2021-12-02 16:30:45 +00:00
Nick Rolfe
976faf97d1 Ruby: remove redundant closure 2021-12-02 16:29:59 +00:00
Michael Nebel
19c34be1ea Merge pull request #7297 from michaelnebel/csharp-accessor-flow
C#: Make it possible to define flow for property backing methods.
2021-12-02 16:24:19 +01:00
Michael Nebel
102b5e05e1 Merge pull request #7290 from michaelnebel/csharp-modify-flow-summaries-test
C#: Modify printing of flow summaries in test.
2021-12-02 16:22:47 +01:00
Geoffrey White
2b349b3024 Merge pull request #7295 from geoffw0/cwe260
C++: Add CWE tags to some queries.
2021-12-02 14:41:34 +00:00
intrigus
2c4ccb79a1 Fix QL Doc typos. 2021-12-02 15:30:29 +01:00
Geoffrey White
3043ac850c C++: Update security-severity tags. 2021-12-02 14:04:49 +00:00
Michael Nebel
f6c36b469a C#: Include test case for override of property. 2021-12-02 15:04:01 +01:00
Michael Nebel
f190d60912 C#: Make it possible to describe flow for properties using their backing methods. 2021-12-02 15:02:22 +01:00
Geoffrey White
eccba57536 C++: Add CWE-327 tag to cpp/boost/use-of-deprecated-hardcoded-security-protocol. 2021-12-02 12:32:14 +00:00
Geoffrey White
7aa6c62050 C++: Add CWE-326 tag to cpp/boost/tls-settings-misconfiguration. 2021-12-02 12:29:42 +00:00
Nick Rolfe
05415768c9 Merge remote-tracking branch 'origin/main' into nickrolfe/regexp_g_anchor 2021-12-02 12:07:13 +00:00
yoff
f10f053c36 Merge pull request #7228 from RasmusWL/fastapi-improvements
Python: FastAPI improvements
2021-12-02 12:58:53 +01:00
Geoffrey White
913d8361ba C++: Add CWE-260 tag to cpp/cleartext-storage-file. 2021-12-02 11:54:51 +00:00
yoff
4609b2060a Merge pull request #7217 from RasmusWL/more-path-injection-fps
Python: Add `x in <var>` test for StringConstCompare
2021-12-02 12:35:33 +01:00
Michael Nebel
8f3be9fbfd C#: Update flow summaries test according to new printing format. 2021-12-02 11:28:06 +01:00
Michael Nebel
edf7724579 C#: Remove trailing whitespace after comma, when priting callable in CSV format. 2021-12-02 11:24:42 +01:00
Michael Nebel
37644d30d2 Merge pull request #7281 from michaelnebel/csharp-flowsummaries-filtered
C#: Filtered flow summaries
2021-12-02 11:23:36 +01:00
Erik Krogh Kristensen
6327fced6f remove paths without unmatched returns from polynomial-redos 2021-12-02 10:03:28 +01:00
Michael Nebel
ad281c0365 C#: Sync FlowSummaryImpl files. 2021-12-02 09:03:00 +01:00
Michael Nebel
a8f673ffa4 C#: Add a test that only prints 'base' flow summaries. 2021-12-02 09:03:00 +01:00
Michael Nebel
e08c734c40 C#: Refactoring to allow override of the flow summaries reported by a test. 2021-12-02 08:54:59 +01:00
Michael Nebel
55c17f453f Merge pull request #7280 from michaelnebel/csharp-newtonsoft-flowsummary
C#: Include the NewtonSoft.JSon stubs in the flow summaries test.
2021-12-02 08:47:58 +01:00
github-actions[bot]
87b968f337 Post-release preparation 2.7.3 2021-12-02 00:46:55 +00:00
Mathias Vorreiter Pedersen
9f8326a3fa Merge pull request #7243 from geoffw0/sslquery2
C++: New query for SSL certificates not checked
2021-12-01 15:02:19 +00:00
Erik Krogh Kristensen
a077345227 Merge pull request #7180 from erik-krogh/apiLabel2
JS: Make the edges of API-graphs into IPA types
2021-12-01 15:33:04 +01:00
Erik Krogh Kristensen
73f2f52ed8 use the TYPE_ONLY_IMPORT context 2021-12-01 14:54:16 +01:00
Erik Krogh Kristensen
739906b60c rename @import_or_export_declaration to @type_keyword_operand 2021-12-01 14:47:11 +01:00
Michael Nebel
9e10aee8a1 C#: Update the flow summaries test. 2021-12-01 14:34:32 +01:00
Michael Nebel
cc2914be3c C#: Include NewtonSoft.Json stubs into the flow summaries test. 2021-12-01 14:34:04 +01:00
Erik Krogh Kristensen
de53727ab3 remove spurious whitespace
Co-authored-by: Asger F <asgerf@github.com>
2021-12-01 14:29:57 +01:00
Erik Krogh Kristensen
0a3d62c92a rename mod -> module 2021-12-01 13:48:16 +01:00
Erik Krogh Kristensen
148da611c6 make the ApiLabel class non-abstract 2021-12-01 13:45:52 +01:00
Tom Hvitved
aad55ffbd6 Merge pull request #7279 from hvitved/csharp/json-net-fix-summaries
C#: Fix `Newtonsoft.Json.JsonSerializer.{Deserialize,Serialize}` summaries
2021-12-01 13:15:10 +01:00
Michael Nebel
75f9a947b3 Merge pull request #7257 from michaelnebel/csharp-nuget-packages
C#: Use .NET Core Nuget package stub i test
2021-12-01 13:04:24 +01:00
Michael Nebel
ed706d9bc1 Merge pull request #7269 from michaelnebel/chspar-nuget-stub-script
C#: Update the make_stubs_nuget script
2021-12-01 13:04:02 +01:00
Arthur Baars
e41cd810d3 Merge pull request #7154 from aibaars/ruby-pattern-matching
Ruby: pattern matching
2021-12-01 12:47:22 +01:00
Tom Hvitved
93e291cb3e C#: Fix Newtonsoft.Json.JsonSerializer.{Deserialize,Serialize} summaries 2021-12-01 11:41:16 +01:00
Anders Schack-Mulligen
cde853c095 Merge pull request #7270 from aschackmull/dataflow/stage2-refactor
Dataflow: Stage 2 refactor
2021-12-01 11:09:08 +01:00
haby0
6742beae1b use <code> tags 2021-12-01 16:24:46 +08:00
Tom Hvitved
31374b485c Data flow: Update documentation 2021-12-01 09:01:06 +01:00
Tom Hvitved
e410244fe0 Python: Implement ParameterPosition et al 2021-12-01 08:51:22 +01:00
Tom Hvitved
bb8f4bb7c1 Ruby: Implement ParameterPosition et al 2021-12-01 08:51:22 +01:00
Tom Hvitved
ae6501d906 Java: Implement ParameterPosition et al 2021-12-01 08:51:22 +01:00
haby0
08be8edbce Modify according to suggestions 2021-12-01 11:57:57 +08:00
Geoffrey White
4b221bd964 C++: Use guard.controls. 2021-11-30 15:44:48 +00:00
Michael Nebel
186ba428cf C#: Remove workdir as error message when format fails. 2021-11-30 15:57:53 +01:00
Michael Nebel
1243d40bb2 Revert "C#: Update the stub for Microsoft.NETCore.App by creating as a dependency for NewtonSoft.JSon"
This reverts commit 8a6a8fc28a.
2021-11-30 15:49:31 +01:00
Tom Hvitved
35a67845cf C++: Implement ParameterPosition et al 2021-11-30 15:34:16 +01:00
Michael Nebel
59b71df2d6 C#: Use stubs for the CWE-601 testcase. 2021-11-30 15:32:19 +01:00
Michael Nebel
0b4d0d2772 C#: Use stubs for the CWE-838 testcase 2021-11-30 15:32:19 +01:00
Michael Nebel
bab8cfb62a C# Generate stubs for System.Data.SqlClient 2021-11-30 15:32:19 +01:00
Michael Nebel
a5b6889478 C# Update flow summaries test. 2021-11-30 15:32:19 +01:00
Michael Nebel
5dd2d20176 C#: Remove overlapping declaration of System.Web.HttpUtility 2021-11-30 15:32:18 +01:00
Michael Nebel
7d6664f14d C#: Use NuGet package generated stubs for dependencies for flow summaries test 2021-11-30 15:32:18 +01:00
Tom Hvitved
540ecf3c21 Data flow: Sync files 2021-11-30 15:20:20 +01:00
Tom Hvitved
755085e9fe C#: Introduce ParameterPosition and ArgumentPosition 2021-11-30 15:20:20 +01:00
Michael Nebel
2589034242 C#: Execute commands with the tempDir as the working directory 2021-11-30 14:42:21 +01:00
Arthur Baars
830908b5c8 Address comments 2021-11-30 13:57:18 +01:00
Anders Schack-Mulligen
3e914ef2ff Dataflow: Sync. 2021-11-30 13:52:52 +01:00
Anders Schack-Mulligen
fc05825c73 Dataflow: Make stage 2 equal to stages 3 and 4. 2021-11-30 13:52:31 +01:00
Michael Nebel
8a6a8fc28a C#: Update the stub for Microsoft.NETCore.App by creating as a dependency for NewtonSoft.JSon 2021-11-30 13:29:35 +01:00
Michael Nebel
0619453c2f C#: Explicitly set .NET 5.0 as target framework in class lib and hardcode compilation to use version 5.0.402 of the SDK 2021-11-30 13:28:48 +01:00
Paolo Tranquilli
b40c77d419 Merge pull request #7267 from github/redsun82/cpp-overrunning-write-precision-split
C++: add some more range analysis tests
2021-11-30 12:54:48 +01:00
Paolo Tranquilli
3f218c903b C++: add some more range analysis tests
Add more covering for integer conversions and some unsigned bit
manipulation.
2021-11-30 11:29:02 +00:00
Geoffrey White
8f270b665c C++: Fix test comments. 2021-11-30 08:56:24 +00:00
Tony Torralba
c91b6f7ce9 Merge pull request #7266 from github/workflow/coverage/update
Update CSV framework coverage reports
2021-11-30 09:07:09 +01:00
Mathias Vorreiter Pedersen
f4555ed1a2 Merge pull request #7242 from geoffw0/sslquery 2021-11-30 07:01:33 +00:00
github-actions[bot]
66e086f92f Add changed framework coverage reports 2021-11-30 00:09:58 +00:00
Arthur Baars
1e026ef45e AST: merge Case and CaseMatch classes 2021-11-29 16:00:17 +01:00
Rasmus Wriedt Larsen
cbd7434a7e Python: Add modeling of tempfile module 2021-11-29 15:08:36 +01:00
Rasmus Wriedt Larsen
b68538376c Python: Add tests of tempfile module 2021-11-29 15:08:36 +01:00
Rasmus Wriedt Larsen
3bcf6d68ce Python: Refactor os FileSystemAccess change-note
I think it's more readable to have only one to cover all of these
changes, even though they came in through different PRs.
2021-11-29 15:08:18 +01:00
Arthur Baars
f8a62c4c82 Address comments 2021-11-29 15:06:16 +01:00
Rasmus Wriedt Larsen
58f92764f7 Python: Model more file access from os module 2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
fd23fa94a5 Python: Remove dubious fstat* modeling
These operate on file descriptors, and not on paths. file descriptors
doesn't fit into the rest of our modeling, so I would rather remove them
than to make it look like it's properly handled.

I also did not include any of the functions that work on file
descriptors when looking through all of `os`. So this keeps everything
consistent at least ;)
2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
e79b8f3e23 Python: Treat os.exec*, os.spawn*, and os.posix_spawn* as FileSystemAccess 2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
d2d5cce787 Python: Recognize keyword arguments for os.*spawn* calls 2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
14590436f9 Python: Expand tests for os.exec*, os.spawn*, and os.posix_spawn* 2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
50d3592ad3 Python: Add more complete tests of os module
I went through https://docs.python.org/3.10/library/os.html in order,
and added all the functions that works on paths.

`lstat` and `statvfs` were already modeled, but did not have any tests.
2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
a91208fd2c Python: Fix kwarg modeling for os.path.isdir 2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
36f14b31bc Python: Add explicit tests for kwargs
I also renamed the arguments to match what the keyword argument is
called. It doesn't matter too much for these specific tests, but for the
tests I'm about to add, it makes things a lot easier to get an overview
of.

Oh, and a test failure :O
2021-11-29 14:54:02 +01:00
Rasmus Wriedt Larsen
82602014ad Python: Minor refactor to use os.path.<func>
Since that's the idiomatic way to use this module
2021-11-29 14:54:02 +01:00
Geoffrey White
88fb1a18cb C++: Correct the doc. 2021-11-29 13:09:12 +00:00
Erik Krogh Kristensen
fdcc144a98 add test for import assertions 2021-11-29 13:51:28 +01:00
Erik Krogh Kristensen
591aeff906 add TypeScript test for new private field syntax 2021-11-29 13:51:28 +01:00
Erik Krogh Kristensen
19bbe6d276 add JavaScript support for new private fields syntax 2021-11-29 13:51:25 +01:00
Erik Krogh Kristensen
d1a7feebc4 disable import resolution on type-only import specifiers 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
d946802057 add support for type-only import specifiers 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
57399b733e add test for String types as Discriminants 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
0e890fd788 add test for the Awaited type 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
eef3905c46 update expected output. The TypeScript compiler now emits types in more cases 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
9ce248c829 update to TypeScript 4.5.2 2021-11-29 13:49:10 +01:00
Erik Krogh Kristensen
c13cad7e87 Merge branch 'main' into apiLabel2 2021-11-29 13:43:11 +01:00
Geoffrey White
d79337774d Update cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.qhelp
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-11-29 12:33:05 +00:00
haby0
db04a0dadf New model: SQL injection in MyBatis annotations 2021-11-28 14:43:57 +08:00
Erik Krogh Kristensen
74158f1e3a revert explicit-this that caused non-monotonic recursion 2021-11-26 21:37:46 +01:00
Taus
09a11f4166 Python: Update ImpliesDataflow test
Turns out that now we can resolve the convoluted imports. Hurray!
2021-11-26 14:47:25 +00:00
Taus
6c3aabe1df Python: Support flow through import *
Adds result for `ModuleVariableNode::getARead` corresponding to reads
that go through (chains of) `import *`.

This required a bit of a change to _which_ module variables we define.
Previously, we only included variables that were accessed elsewhere in
the same file, but now we must ensure to also include variables that may
be accessed through `import *`.
2021-11-26 13:49:08 +00:00
Taus
c3e495efe9 Python: Refactor built-ins and import * logic
Moves this from the API graphs implementation into separate files.
2021-11-26 13:49:08 +00:00
Taus
03b6ee3833 Python: Add import * test
This test shows off a few things:

- transitive chains of `import *`
- multiple modules exporting the same name (to test for cross-talk)
2021-11-26 13:49:08 +00:00
Erik Krogh Kristensen
6ff8d4de5c add all remaining explicit this 2021-11-26 13:50:10 +01:00
Geoffrey White
f96968975b C++: Change note. 2021-11-25 15:49:41 +00:00
Geoffrey White
e98ab5d2c2 C++: Add security-severity tag and provisional precision. 2021-11-25 15:49:40 +00:00
Geoffrey White
e9ce29664e C++: Qldoc. 2021-11-25 15:48:12 +00:00
Geoffrey White
1d358c5f77 C++: Change note. 2021-11-25 14:04:47 +00:00
Geoffrey White
f5b40731d6 C++: Add security-severity tag and provisional precision. 2021-11-25 13:59:21 +00:00
Arthur Baars
e801d9636a Ruby: add ruby/ruby to the dataset-measure CI job 2021-11-25 14:10:15 +01:00
Arthur Baars
8b0bc677f4 Remove PatternGuard class 2021-11-25 13:50:19 +01:00
Arthur Baars
dca1e34cd8 Temporarily allow CFG inconsistencies 2021-11-25 13:42:59 +01:00
Arthur Baars
16e1e97ff0 Add test data for case-in expressions 2021-11-25 13:25:33 +01:00
Arthur Baars
af4c3122ca Test case for **nil parameter 2021-11-25 13:25:00 +01:00
Arthur Baars
078a2aa03b Update AST library 2021-11-25 13:24:51 +01:00
Arthur Baars
ec0bd24b64 Update diagnostic tests 2021-11-25 12:55:50 +01:00
Arthur Baars
5b560b12e9 Create upgrade script 2021-11-25 12:55:43 +01:00
haby0
04a3f76a8b Eliminate false positives of Mybatis Configuration Variable 2021-11-25 15:47:37 +08:00
haby0
d36a7ed10e add test case 2021-11-25 15:47:32 +08:00
haby0
99c8b291b2 add sink 2021-11-25 15:47:32 +08:00
haby0
b8732859de Add isSanitizerGuard, verify file path 2021-11-25 15:47:31 +08:00
haby0
31400df0d4 Modify sink and improve SQL injection detection 2021-11-25 15:47:30 +08:00
haby0
69690a2509 Modify sinks 2021-11-25 15:47:30 +08:00
haby0
4438f8c58c Add MyBatis Mapper Sql Injection 2021-11-25 15:47:29 +08:00
Geoffrey White
4c5faaf985 C++: Autoformat result not checked query. 2021-11-24 18:26:39 +00:00
Geoffrey White
8abaf1247a C++: Clean up result not checked query. 2021-11-24 18:26:39 +00:00
Geoffrey White
5ffbf563b8 C++: Add metadata for result not checked query. 2021-11-24 18:26:38 +00:00
Geoffrey White
72a03257e7 C++: Add qhelp for result not checked query. 2021-11-24 18:26:38 +00:00
Geoffrey White
5eb814fd8b C++: Prototype SSL result not checked query. 2021-11-24 18:26:37 +00:00
Geoffrey White
7869733ab5 C++: Autoformat result conflation query. 2021-11-24 18:25:58 +00:00
Geoffrey White
88b6bd9478 C++: Switch result conflation query to a slightly simpler dataflow-only approach. 2021-11-24 18:25:57 +00:00
Geoffrey White
ce2b86b9e3 C++: Add metadata for result conflation query. 2021-11-24 18:25:57 +00:00
Geoffrey White
2eae6a3e9a C++: Add qhelp for result conflation query. 2021-11-24 18:25:56 +00:00
Geoffrey White
6afcbce421 C++: Prototype SSL result conflation query. 2021-11-24 18:22:24 +00:00
Arthur Baars
5d0dfe8c04 Re-generate library and dbscheme 2021-11-24 17:18:04 +01:00
Arthur Baars
e7524dea69 Update tree-sitter-ruby 2021-11-24 17:18:03 +01:00
Rasmus Wriedt Larsen
1411804e58 Python: Allow custom fastapi.APIRouter subclasses 2021-11-24 13:46:38 +01:00
Rasmus Wriedt Larsen
d493cfdf3a Python: Model FastAPI FileResponse as FileSystemAccess
This was an oversight from our initial FastAPI modeling work.
2021-11-24 11:44:51 +01:00
Rasmus Wriedt Larsen
baafd9f8ba Python: Add an other path injection FP
Along with the root cause, which is the `StringConstCompare`
BarrierGuard, that does only allows `in <iterable literal>` and not
`in <variable referencing iterable literal>`
2021-11-23 12:59:15 +01:00
ihsinme
70081defdc Update FindIncorrectlyUsedExceptions.expected 2021-11-23 09:56:02 +03:00
ihsinme
62ae702e07 Update FindIncorrectlyUsedExceptions.ql 2021-11-23 09:55:43 +03:00
Erik Krogh Kristensen
e9df860431 refactor implementation to make Label implementations private 2021-11-22 12:17:19 +01:00
Erik Krogh Kristensen
6060f2e3e3 remove unused alias edge 2021-11-22 09:03:40 +01:00
Erik Krogh Kristensen
c369b28a2a optimizations in global data flow 2021-11-22 09:03:40 +01:00
Erik Krogh Kristensen
f39872e649 cache more predicates 2021-11-22 09:03:36 +01:00
Erik Krogh Kristensen
089d030bc2 make ApiLabel into a IPA type, and cache the public API of ApiGraphs 2021-11-22 09:03:33 +01:00
Nick Rolfe
df6ba43cca Python: treat \A, \Z, \b, \B as special chars, not escapes 2021-11-19 15:49:53 +00:00
Nick Rolfe
f63c768d9f Ruby: parse \G, \b, and \B anchors as special characters, not escapes 2021-11-19 14:20:51 +00:00
ihsinme
6d27585b92 Update FindIncorrectlyUsedExceptions.ql 2021-11-19 16:59:00 +03:00
ihsinme
418adb824c Update FindIncorrectlyUsedExceptions.ql 2021-11-19 16:04:04 +03:00
ihsinme
fd73f4094f Update FindIncorrectlyUsedExceptions.ql 2021-11-19 10:54:02 +03:00
Alex Ford
1ec935dee6 Ruby: make documentation of IOReader and FileReader less ambiguous 2021-11-18 14:35:44 +00:00
Alex Ford
bd940712de Update ruby/ql/lib/codeql/ruby/frameworks/Files.qll
Co-authored-by: Harry Maclean <hmac@github.com>
2021-11-18 14:18:39 +00:00
Alex Ford
9a74f18ac5 Ruby: take File::try_convert as a potential file instance instantiation 2021-11-17 23:19:13 +00:00
Alex Ford
ce004e9c1e Ruby: don't interpret File#try_convert as a method that reads from a file/IO 2021-11-17 23:01:19 +00:00
Alex Ford
12a3251649 Ruby: extend FileSystemReadAccess and restructure some Files.qll classes 2021-11-17 23:01:18 +00:00
Tony Torralba
9d50511ea4 Fix stubs 2021-10-18 09:27:53 +02:00
Tony Torralba
5deb996b33 Merge branch 'main' into atorralba/android_slice_models 2021-10-18 08:41:48 +02:00
Tony Torralba
91efb61e97 Use synthetic fields to improve taint precision 2021-10-07 17:03:08 +02:00
Tony Torralba
0325c07bd9 Reorganize fluent models 2021-10-07 17:03:07 +02:00
Tony Torralba
ffa77f0a76 Fix QLDoc 2021-10-07 17:03:07 +02:00
Tony Torralba
588dedc265 Add stubs 2021-10-07 17:03:05 +02:00
Tony Torralba
1a04ad98bc Add Android Slice models 2021-10-07 17:01:16 +02:00
996 changed files with 35055 additions and 6486 deletions

View File

@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
repo: [rails/rails, discourse/discourse, spree/spree]
repo: [rails/rails, discourse/discourse, spree/spree, ruby/ruby]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@@ -1,4 +0,0 @@
lgtm,codescanning
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
`isFromSystemMacroDefinition` for identifying code that originates from a
macro outside the project being analyzed.

View File

@@ -1,2 +0,0 @@
lgtm,codescanning
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.

View File

@@ -1,3 +1,5 @@
## 0.0.5
## 0.0.4
### New Features

View File

@@ -0,0 +1 @@
## 0.0.5

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.4
lastReleaseVersion: 0.0.5

View File

@@ -1,8 +1,8 @@
name: codeql/cpp-all
version: 0.0.5-dev
version: 0.0.5
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
library: true
dependencies:
codeql/cpp-upgrades: 0.0.3
codeql/cpp-upgrades: ^0.0.3

View File

@@ -626,9 +626,9 @@ library class ExprEvaluator extends int {
// All assignments must have the same int value
result =
unique(Expr value |
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
value = v.getAnAssignedValue() and not this.ignoreVariableAssignment(e, v, value)
|
getValueInternalNonSubExpr(value)
this.getValueInternalNonSubExpr(value)
)
)
}

View File

@@ -1,4 +1,6 @@
private import cpp
private import semmle.code.cpp.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.dataflow.internal.DataFlowUtil
/**
* Gets a function that might be called by `call`.
@@ -63,3 +65,17 @@ predicate mayBenefitFromCallContext(Call call, Function f) { none() }
* restricted to those `call`s for which a context might make a difference.
*/
Function viableImplInCallContext(Call call, Call ctx) { none() }
/** A parameter position represented by an integer. */
class ParameterPosition extends int {
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
}
/** An argument position represented by an integer. */
class ArgumentPosition extends int {
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
}
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
tupleLimit = 1000
}
/**
* Holds if `arg` is an argument of `call` with an argument position that matches
* parameter position `ppos`.
*/
pragma[noinline]
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
exists(ArgumentPosition apos |
arg.argumentOf(call, apos) and
parameterMatch(ppos, apos)
)
}
/**
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
* currently excludes read-steps, store-steps, and flow-through.
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
pragma[noinline]
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallable(call), ppos)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
pragma[noinline]
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), ppos)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamNonLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
@@ -322,7 +336,7 @@ private module Cached {
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
)
}
@@ -330,7 +344,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
exists(ParamNode p, ParameterPosition pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -352,11 +366,13 @@ private module Cached {
}
cached
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
isParameterNode(p, c, pos)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
isArgumentNode(n, call, pos)
}
/**
@@ -374,12 +390,12 @@ private module Cached {
}
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
* The instance parameter is considered to have index `-1`.
* Holds if `p` is the parameter of a viable dispatch target of `call`,
* and `p` has position `ppos`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableExt(call), ppos)
}
/**
@@ -388,9 +404,9 @@ private module Cached {
*/
cached
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
exists(ParameterPosition ppos |
viableParam(call, ppos, p) and
argumentPositionMatch(call, arg, ppos) and
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -862,7 +878,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
* position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
}
/** A data-flow node that represents a call argument. */
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
argumentNode(this, call, pos)
}
}
/**
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
private int pos;
private ParameterPosition pos;
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
int getPosition() { result = pos }
ParameterPosition getPosition() { result = pos }
pragma[nomagic]
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
override string toString() { result = "param update " + pos }
}

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c, pos)
}
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
arg.argumentOf(c, pos)
}
/** Gets the instance argument of a non-static call. */
private Node getInstanceArgument(Call call) {

View File

@@ -2,6 +2,7 @@ private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
/**
@@ -266,3 +267,17 @@ Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget()
)
}
/** A parameter position represented by an integer. */
class ParameterPosition extends int {
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
}
/** An argument position represented by an integer. */
class ArgumentPosition extends int {
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
}
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1012,6 +1012,9 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
bindingset[node, ap]
private predicate filter(NodeEx node, Ap ap) { any() }
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
@@ -1020,6 +1023,13 @@ private module Stage2 {
PrevStage::revFlow(node, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
exists(ApApprox apa0 |
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
@@ -1042,6 +1052,13 @@ private module Stage2 {
*/
pragma[nomagic]
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
fwdFlow0(node, cc, argAp, ap, config) and
flowCand(node, unbindApa(getApprox(ap)), config) and
filter(node, ap)
}
pragma[nomagic]
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
flowCand(node, _, config) and
sourceNode(node, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
@@ -1112,7 +1129,7 @@ private module Stage2 {
) {
exists(DataFlowType contentType |
fwdFlow(node1, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1189,7 +1206,7 @@ private module Stage2 {
) {
exists(ParamNodeEx p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1430,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2125,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2891,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2975,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3622,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3669,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3695,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4424,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4450,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4616,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4644,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
tupleLimit = 1000
}
/**
* Holds if `arg` is an argument of `call` with an argument position that matches
* parameter position `ppos`.
*/
pragma[noinline]
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
exists(ArgumentPosition apos |
arg.argumentOf(call, apos) and
parameterMatch(ppos, apos)
)
}
/**
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
* currently excludes read-steps, store-steps, and flow-through.
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
pragma[noinline]
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallable(call), ppos)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
pragma[noinline]
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), ppos)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamNonLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
@@ -322,7 +336,7 @@ private module Cached {
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
)
}
@@ -330,7 +344,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
exists(ParamNode p, ParameterPosition pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -352,11 +366,13 @@ private module Cached {
}
cached
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
isParameterNode(p, c, pos)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
isArgumentNode(n, call, pos)
}
/**
@@ -374,12 +390,12 @@ private module Cached {
}
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
* The instance parameter is considered to have index `-1`.
* Holds if `p` is the parameter of a viable dispatch target of `call`,
* and `p` has position `ppos`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableExt(call), ppos)
}
/**
@@ -388,9 +404,9 @@ private module Cached {
*/
cached
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
exists(ParameterPosition ppos |
viableParam(call, ppos, p) and
argumentPositionMatch(call, arg, ppos) and
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -862,7 +878,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
* position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
}
/** A data-flow node that represents a call argument. */
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
argumentNode(this, call, pos)
}
}
/**
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
private int pos;
private ParameterPosition pos;
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
int getPosition() { result = pos }
ParameterPosition getPosition() { result = pos }
pragma[nomagic]
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
override string toString() { result = "param update " + pos }
}

View File

@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c, pos)
}
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
arg.argumentOf(c, pos)
}
/**
* A data flow node that occurs as the argument of a call and is passed as-is

View File

@@ -452,7 +452,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
/** Holds if this phi node has input from the `rnk`'th write operation in block `block`. */
final predicate hasInputAtRankInBlock(IRBlock block, int rnk) {
hasInputAtRankInBlock(block, rnk, _)
this.hasInputAtRankInBlock(block, rnk, _)
}
/**

View File

@@ -307,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }

View File

@@ -307,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }

View File

@@ -307,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }

View File

@@ -18,12 +18,12 @@ class SuppressionComment extends Comment {
(
this instanceof CppStyleComment and
// strip the beginning slashes
text = getContents().suffix(2)
text = this.getContents().suffix(2)
or
this instanceof CStyleComment and
// strip both the beginning /* and the end */ the comment
exists(string text0 |
text0 = getContents().suffix(2) and
text0 = this.getContents().suffix(2) and
text = text0.prefix(text0.length() - 2)
) and
// The /* */ comment must be a single-line comment

View File

@@ -153,12 +153,12 @@ class ExtClass extends Class {
}
predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) {
if hasOneVariableGroup()
if this.hasOneVariableGroup()
then
exists(VariableDeclarationGroup vdg | vdg.getClass() = this |
vdg.hasLocationInfo(path, startline, startcol, endline, endcol)
)
else getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
else this.getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
}
}

View File

@@ -50,6 +50,16 @@ predicate reachableThing(Thing t) {
exists(Thing mid | reachableThing(mid) and mid.callsOrAccesses() = t)
}
pragma[nomagic]
predicate callsOrAccessesPlus(Thing thing1, FunctionToRemove thing2) {
thing1.callsOrAccesses() = thing2
or
exists(Thing mid |
thing1.callsOrAccesses() = mid and
callsOrAccessesPlus(mid, thing2)
)
}
class Thing extends Locatable {
Thing() {
this instanceof Function or
@@ -81,7 +91,7 @@ class FunctionToRemove extends Function {
}
Thing getOther() {
result.callsOrAccesses+() = this and
callsOrAccessesPlus(result, this) and
this != result and
// We will already be reporting the enclosing function of a
// local variable, so don't also report the variable

View File

@@ -1,3 +1,10 @@
## 0.0.5
### New Queries
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
## 0.0.4
### New Queries

View File

@@ -103,9 +103,9 @@ class CallWithBufferSize extends FunctionCall {
// `upperBound(e)` defaults to `exprMaxVal(e)` when `e` isn't analyzable. So to get a meaningful
// result in this case we pick the minimum value obtainable from dataflow and range analysis.
result =
upperBound(statedSizeExpr())
upperBound(this.statedSizeExpr())
.minimum(min(Expr statedSizeSrc |
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr())
DataFlow::localExprFlow(statedSizeSrc, this.statedSizeExpr())
|
statedSizeSrc.getValue().toInt()
))

View File

@@ -22,7 +22,7 @@ abstract class LockOperation extends FunctionCall {
ControlFlowNode getAReachedNode() {
result = this
or
exists(ControlFlowNode mid | mid = getAReachedNode() |
exists(ControlFlowNode mid | mid = this.getAReachedNode() |
not mid != this.getMatchingUnlock() and
result = mid.getASuccessor()
)

View File

@@ -156,8 +156,8 @@ abstract class LeapYearFieldAccess extends YearFieldAccess {
//
// https://aa.usno.navy.mil/faq/docs/calendars.php
this.isUsedInMod4Operation() and
additionalModulusCheckForLeapYear(400) and
additionalModulusCheckForLeapYear(100)
this.additionalModulusCheckForLeapYear(400) and
this.additionalModulusCheckForLeapYear(100)
}
}
@@ -176,17 +176,17 @@ class StructTmLeapYearFieldAccess extends LeapYearFieldAccess {
override predicate isUsedInCorrectLeapYearCheck() {
this.isUsedInMod4Operation() and
additionalModulusCheckForLeapYear(400) and
additionalModulusCheckForLeapYear(100) and
this.additionalModulusCheckForLeapYear(400) and
this.additionalModulusCheckForLeapYear(100) and
// tm_year represents years since 1900
(
additionalAdditionOrSubstractionCheckForLeapYear(1900)
this.additionalAdditionOrSubstractionCheckForLeapYear(1900)
or
// some systems may use 2000 for 2-digit year conversions
additionalAdditionOrSubstractionCheckForLeapYear(2000)
this.additionalAdditionOrSubstractionCheckForLeapYear(2000)
or
// converting from/to Unix epoch
additionalAdditionOrSubstractionCheckForLeapYear(1970)
this.additionalAdditionOrSubstractionCheckForLeapYear(1970)
)
}
}

View File

@@ -57,7 +57,7 @@ class LoopWithAlloca extends Stmt {
or
// `e == 0`
exists(EQExpr eq |
conditionRequires(eq, truth.booleanNot()) and
this.conditionRequires(eq, truth.booleanNot()) and
eq.getAnOperand().getValue().toInt() = 0 and
e = eq.getAnOperand() and
not exists(e.getValue())
@@ -65,7 +65,7 @@ class LoopWithAlloca extends Stmt {
or
// `e != 0`
exists(NEExpr eq |
conditionRequires(eq, truth) and
this.conditionRequires(eq, truth) and
eq.getAnOperand().getValue().toInt() = 0 and
e = eq.getAnOperand() and
not exists(e.getValue())
@@ -73,7 +73,7 @@ class LoopWithAlloca extends Stmt {
or
// `(bool)e == true`
exists(EQExpr eq |
conditionRequires(eq, truth) and
this.conditionRequires(eq, truth) and
eq.getAnOperand().getValue().toInt() = 1 and
e = eq.getAnOperand() and
e.getUnspecifiedType() instanceof BoolType and
@@ -82,7 +82,7 @@ class LoopWithAlloca extends Stmt {
or
// `(bool)e != true`
exists(NEExpr eq |
conditionRequires(eq, truth.booleanNot()) and
this.conditionRequires(eq, truth.booleanNot()) and
eq.getAnOperand().getValue().toInt() = 1 and
e = eq.getAnOperand() and
e.getUnspecifiedType() instanceof BoolType and
@@ -90,7 +90,7 @@ class LoopWithAlloca extends Stmt {
)
or
exists(NotExpr notExpr |
conditionRequires(notExpr, truth.booleanNot()) and
this.conditionRequires(notExpr, truth.booleanNot()) and
e = notExpr.getOperand()
)
or
@@ -98,7 +98,7 @@ class LoopWithAlloca extends Stmt {
// requires both of its operand to be true as well.
exists(LogicalAndExpr andExpr |
truth = true and
conditionRequires(andExpr, truth) and
this.conditionRequires(andExpr, truth) and
e = andExpr.getAnOperand()
)
or
@@ -106,7 +106,7 @@ class LoopWithAlloca extends Stmt {
// it requires both of its operand to be false as well.
exists(LogicalOrExpr orExpr |
truth = false and
conditionRequires(orExpr, truth) and
this.conditionRequires(orExpr, truth) and
e = orExpr.getAnOperand()
)
}
@@ -141,9 +141,9 @@ class LoopWithAlloca extends Stmt {
* `conditionRequiresInequality`.
*/
private Variable getAControllingVariable() {
conditionRequires(result.getAnAccess(), _)
this.conditionRequires(result.getAnAccess(), _)
or
conditionRequiresInequality(result.getAnAccess(), _, _)
this.conditionRequiresInequality(result.getAnAccess(), _, _)
}
/**

View File

@@ -61,72 +61,72 @@ class PointerArithmeticAccess extends BufferAccess, Expr {
* A pair of buffer accesses through a call to memcpy.
*/
class MemCpy extends BufferAccess, FunctionCall {
MemCpy() { getTarget().hasName("memcpy") }
MemCpy() { this.getTarget().hasName("memcpy") }
override Expr getPointer() {
result = getArgument(0) or
result = getArgument(1)
result = this.getArgument(0) or
result = this.getArgument(1)
}
override Expr getAccessedLength() { result = getArgument(2) }
override Expr getAccessedLength() { result = this.getArgument(2) }
}
class StrncpySizeExpr extends BufferAccess, FunctionCall {
StrncpySizeExpr() { getTarget().hasName("strncpy") }
StrncpySizeExpr() { this.getTarget().hasName("strncpy") }
override Expr getPointer() {
result = getArgument(0) or
result = getArgument(1)
result = this.getArgument(0) or
result = this.getArgument(1)
}
override Expr getAccessedLength() { result = getArgument(2) }
override Expr getAccessedLength() { result = this.getArgument(2) }
}
class RecvSizeExpr extends BufferAccess, FunctionCall {
RecvSizeExpr() { getTarget().hasName("recv") }
RecvSizeExpr() { this.getTarget().hasName("recv") }
override Expr getPointer() { result = getArgument(1) }
override Expr getPointer() { result = this.getArgument(1) }
override Expr getAccessedLength() { result = getArgument(2) }
override Expr getAccessedLength() { result = this.getArgument(2) }
}
class SendSizeExpr extends BufferAccess, FunctionCall {
SendSizeExpr() { getTarget().hasName("send") }
SendSizeExpr() { this.getTarget().hasName("send") }
override Expr getPointer() { result = getArgument(1) }
override Expr getPointer() { result = this.getArgument(1) }
override Expr getAccessedLength() { result = getArgument(2) }
override Expr getAccessedLength() { result = this.getArgument(2) }
}
class SnprintfSizeExpr extends BufferAccess, FunctionCall {
SnprintfSizeExpr() { getTarget().hasName("snprintf") }
SnprintfSizeExpr() { this.getTarget().hasName("snprintf") }
override Expr getPointer() { result = getArgument(0) }
override Expr getPointer() { result = this.getArgument(0) }
override Expr getAccessedLength() { result = getArgument(1) }
override Expr getAccessedLength() { result = this.getArgument(1) }
}
class MemcmpSizeExpr extends BufferAccess, FunctionCall {
MemcmpSizeExpr() { getTarget().hasName("Memcmp") }
MemcmpSizeExpr() { this.getTarget().hasName("Memcmp") }
override Expr getPointer() {
result = getArgument(0) or
result = getArgument(1)
result = this.getArgument(0) or
result = this.getArgument(1)
}
override Expr getAccessedLength() { result = getArgument(2) }
override Expr getAccessedLength() { result = this.getArgument(2) }
}
class MallocSizeExpr extends BufferAccess, FunctionCall {
MallocSizeExpr() { getTarget().hasName("malloc") }
MallocSizeExpr() { this.getTarget().hasName("malloc") }
override Expr getPointer() { none() }
override Expr getAccessedLength() { result = getArgument(0) }
override Expr getAccessedLength() { result = this.getArgument(0) }
}
class NetworkFunctionCall extends FunctionCall {
NetworkFunctionCall() { getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
}
class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {

View File

@@ -3,8 +3,10 @@
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
* @kind problem
* @problem.severity error
* @security-severity 7.5
* @id cpp/boost/tls-settings-misconfiguration
* @tags security
* external/cwe/cwe-326
*/
import cpp

View File

@@ -3,8 +3,10 @@
* @description Using a deprecated hard-coded protocol using the boost::asio library.
* @kind problem
* @problem.severity error
* @security-severity 7.5
* @id cpp/boost/use-of-deprecated-hardcoded-security-protocol
* @tags security
* external/cwe/cwe-327
*/
import cpp

View File

@@ -13,7 +13,7 @@ import cpp
class MacroFunctionCall extends MacroInvocation {
MacroFunctionCall() {
not exists(getParentInvocation()) and
not exists(this.getParentInvocation()) and
this.getMacro().getHead().matches("%(%")
}

View File

@@ -13,7 +13,7 @@ import semmle.code.cpp.commons.Assertions
class MacroFunctionCall extends MacroInvocation {
MacroFunctionCall() {
not exists(getParentInvocation()) and
not exists(this.getParentInvocation()) and
this.getMacro().getHead().matches("%(%")
}

View File

@@ -38,7 +38,7 @@ class ExternalAPIDataNode extends DataFlow::Node {
int getIndex() { result = i }
/** Gets the description of the function being called. */
string getFunctionDescription() { result = getExternalFunction().toString() }
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */

View File

@@ -38,7 +38,7 @@ class ExternalAPIDataNode extends DataFlow::Node {
int getIndex() { result = i }
/** Gets the description of the function being called. */
string getFunctionDescription() { result = getExternalFunction().toString() }
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */

View File

@@ -42,7 +42,7 @@ class VarargsFunction extends Function {
}
private int trailingArgValueCount(string value) {
result = strictcount(FunctionCall fc | trailingArgValue(fc) = value)
result = strictcount(FunctionCall fc | this.trailingArgValue(fc) = value)
}
string nonTrailingVarArgValue(FunctionCall fc, int index) {
@@ -58,11 +58,11 @@ class VarargsFunction extends Function {
string normalTerminator(int cnt) {
result = ["0", "-1"] and
cnt = trailingArgValueCount(result) and
2 * cnt > totalCount() and
cnt = this.trailingArgValueCount(result) and
2 * cnt > this.totalCount() and
not exists(FunctionCall fc, int index |
// terminator value is used in a non-terminating position
nonTrailingVarArgValue(fc, index) = result
this.nonTrailingVarArgValue(fc, index) = result
)
}

View File

@@ -42,7 +42,7 @@ class TaintSource extends VariableAccess {
definitionUsePair(_, this, va)
or
exists(VariableAccess mid, Expr def |
sourceReaches(mid) and
this.sourceReaches(mid) and
exprDefinition(_, def, mid) and
definitionUsePair(_, def, va)
)
@@ -53,11 +53,11 @@ class TaintSource extends VariableAccess {
* from `va`, possibly using intermediate reassignments.
*/
private predicate reachesSink(VariableAccess va, VariableAccess sink) {
isSink(sink) and
this.isSink(sink) and
va = sink
or
exists(VariableAccess mid, Expr def |
reachesSink(mid, sink) and
this.reachesSink(mid, sink) and
exprDefinition(_, def, va) and
definitionUsePair(_, def, mid)
)
@@ -71,15 +71,15 @@ class TaintSource extends VariableAccess {
* this source to `sink` found via `tainted(source, sink)`.)
*/
predicate reaches(VariableAccess sink) {
isSink(sink) and
this.isSink(sink) and
not exists(VariableAccess va |
va != this and
va != sink and
mayAddNullTerminator(_, va)
|
sourceReaches(va)
this.sourceReaches(va)
or
reachesSink(va, sink)
this.reachesSink(va, sink)
)
}
}

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>When checking the result of SSL certificate verification, accepting any error code may allow an attacker to impersonate someone who is trusted.</p>
</overview>
<recommendation>
<p>When checking an SSL certificate with <code>SSL_get_verify_result</code>, only <code>X509_V_OK</code> is a success code. If there is any other result the certificate should not be accepted.</p>
</recommendation>
<example>
<p>In this example the error code <code>X509_V_ERR_CERT_HAS_EXPIRED</code> is treated the same as an OK result. An expired certificate should not be accepted as it is more likely to be compromised than a valid certificate.</p>
<sample src="SSLResultConflationBad.cpp" />
<p>In the corrected example, only a result of <code>X509_V_OK</code> is accepted.</p>
<sample src="SSLResultConflationGood.cpp" />
</example>
<references>
</references>
</qhelp>

View File

@@ -0,0 +1,50 @@
/**
* @name Certificate result conflation
* @description Only accept SSL certificates that pass certificate verification.
* @kind problem
* @problem.severity error
* @security-severity 7.5
* @precision medium
* @id cpp/certificate-result-conflation
* @tags security
* external/cwe/cwe-295
*/
import cpp
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.dataflow.DataFlow
/**
* A call to `SSL_get_verify_result`.
*/
class SSLGetVerifyResultCall extends FunctionCall {
SSLGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
}
/**
* Data flow from a call to `SSL_get_verify_result` to a guard condition
* that references the result.
*/
class VerifyResultConfig extends DataFlow::Configuration {
VerifyResultConfig() { this = "VerifyResultConfig" }
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof SSLGetVerifyResultCall
}
override predicate isSink(DataFlow::Node sink) {
exists(GuardCondition guard | guard.getAChild*() = sink.asExpr())
}
}
from
VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2,
GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue
where
config.hasFlow(source, sink1) and
config.hasFlow(source, sink2) and
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
c1.getValue().toInt() = 0 and
c2.getValue().toInt() != 0
select guard, "This expression conflates OK and non-OK results from $@.", source, source.toString()

View File

@@ -0,0 +1,13 @@
// ...
if (cert = SSL_get_peer_certificate(ssl))
{
result = SSL_get_verify_result(ssl);
if ((result == X509_V_OK) || (result == X509_V_ERR_CERT_HAS_EXPIRED)) // BAD (conflates OK and a non-OK codes)
{
do_ok();
} else {
do_error();
}
}

View File

@@ -0,0 +1,13 @@
// ...
if (cert = SSL_get_peer_certificate(ssl))
{
result = SSL_get_verify_result(ssl);
if (result == X509_V_OK) // GOOD
{
do_ok();
} else {
do_error();
}
}

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>After fetching an SSL certificate, always check the result of certificate verification.</p>
</overview>
<recommendation>
<p>Always check the result of SSL certificate verification. A certificate that has been revoked may indicate that data is coming from an attacker, whereas a certificate that has expired or was self-signed may indicate an increased likelihood that the data is malicious.</p>
</recommendation>
<example>
<p>In this example, the <code>SSL_get_peer_certificate</code> function is used to get the certificate of a peer. However it is unsafe to use that information without checking if the certificate is valid.</p>
<sample src="SSLResultNotCheckedBad.cpp" />
<p>In the corrected example, we use <code>SSL_get_verify_result</code> to check that certificate verification was successful.</p>
<sample src="SSLResultNotCheckedGood.cpp" />
</example>
<references>
</references>
</qhelp>

View File

@@ -0,0 +1,120 @@
/**
* @name Certificate not checked
* @description Always check the result of certificate verification after fetching an SSL certificate.
* @kind problem
* @problem.severity error
* @security-severity 7.5
* @precision medium
* @id cpp/certificate-not-checked
* @tags security
* external/cwe/cwe-295
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.controlflow.IRGuards
/**
* A call to `SSL_get_peer_certificate`.
*/
class SSLGetPeerCertificateCall extends FunctionCall {
SSLGetPeerCertificateCall() {
getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
}
Expr getSSLArgument() { result = getArgument(0) }
}
/**
* A call to `SSL_get_verify_result`.
*/
class SSLGetVerifyResultCall extends FunctionCall {
SSLGetVerifyResultCall() {
getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
}
Expr getSSLArgument() { result = getArgument(0) }
}
/**
* Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
* `SSL_get_verify_result` entering `node`.
*/
predicate resultIsChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
exists(Expr ssl, SSLGetVerifyResultCall check |
ssl = globalValueNumber(getCertCall.getSSLArgument()).getAnExpr() and
ssl = check.getSSLArgument() and
node = check
)
}
/**
* Holds if the certificate returned by `SSL_get_peer_certificate` is found to be
* `0` on the edge `node1` to `node2`.
*/
predicate certIsZero(
SSLGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
) {
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
exists(GuardCondition guard, Expr zero |
zero.getValue().toInt() = 0 and
node1 = guard and
(
// if (cert == zero) {
guard.comparesEq(cert, zero, 0, true, true) and
node2 = guard.getATrueSuccessor()
or
// if (cert != zero) { }
guard.comparesEq(cert, zero, 0, false, true) and
node2 = guard.getAFalseSuccessor()
)
)
or
(
// if (cert) { }
node1 = cert
or
// if (!cert) {
node1.(NotExpr).getAChild() = cert
) and
node2 = node1.getASuccessor() and
not cert.(GuardCondition).controls(node2, true) // cert may be false
)
}
/**
* Holds if the SSL object passed into `SSL_get_peer_certificate` has not been checked with
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
*/
predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
// cert is not checked at the call to `SSL_get_peer_certificate`
node = getCertCall
or
exists(BasicBlock bb, int pos |
// flow to end of a `BasicBlock`
certNotChecked(getCertCall, bb.getNode(pos)) and
node = bb.getEnd() and
// check for barrier node
not exists(int pos2 |
pos2 > pos and
resultIsChecked(getCertCall, bb.getNode(pos2))
)
)
or
exists(BasicBlock pred, BasicBlock bb |
// flow from the end of one `BasicBlock` to the beginning of a successor
certNotChecked(getCertCall, pred.getEnd()) and
bb = pred.getASuccessor() and
node = bb.getStart() and
// check for barrier bb
not certIsZero(getCertCall, pred.getEnd(), bb.getStart())
)
}
from SSLGetPeerCertificateCall getCertCall, ControlFlowNode node
where
certNotChecked(getCertCall, node) and
node instanceof Function // (function exit)
select getCertCall,
"This " + getCertCall.toString() + " is not followed by a call to SSL_get_verify_result."

View File

@@ -0,0 +1,5 @@
// ...
X509 *cert = SSL_get_peer_certificate(ssl); // BAD (SSL_get_verify_result is never called)
// ...

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