Compare commits

..

181 Commits

Author SHA1 Message Date
Max Schaefer
2189ab030d Revert "JS: Recognize DomSanitizer from @angular/core"
This reverts commit ff1d0cc4c7.
2021-11-25 17:18:34 +00:00
Henry Mercer
667305e27e Remove NoSQL sinks since September 2018 2021-11-25 17:18:34 +00:00
Esben Sparre Andreasen
79b9d05576 Remove additional Xss sinks 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
894ef629f4 Remove additional SQL sinks 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
16e5d70027 Remove additional path-injection sinks 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
76128c6c98 Add benjamin-button.md 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
07a1cbe499 Remove pseudo-properties 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
662153464e Remove 2020 sinks from SqlInjection.ql 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
8cd3b13d84 Remove 2020 sinks from Xss.ql 2021-11-25 17:18:33 +00:00
Esben Sparre Andreasen
7d5205acee Remove 2020 sinks from TaintedPath.ql 2021-11-25 17:18:33 +00:00
Henry Mercer
29eb66d772 JS: Add ML models to .gitignore 2021-11-25 17:06:37 +00:00
Henry Mercer
2af509595b JS: Add ML models specification to ATM query pack definition
This will allow us to resolve the ATM machine learning models that will
be distributed within this pack.
2021-11-25 16:42:38 +00:00
Anders Schack-Mulligen
609d6011a2 Merge pull request #7229 from smowton/smowton/admin/document-xxe-sanitisation-policy
Document XXE sanitisation policy
2021-11-25 10:55:25 +01:00
CodeQL CI
d3da790191 Merge pull request #6873 from erik-krogh/explicit-this
Approved by esbena
2021-11-24 15:23:35 -08:00
Chris Smowton
3c8f6e3c07 Merge pull request #6717 from luchua-bc/java/thread-resource-abuse
Java: CWE-400 - Query to detect uncontrolled thread resource consumption
2021-11-24 18:59:41 +00:00
Arthur Baars
4b3b1d2a8b Merge pull request #7222 from aibaars/ruby-ci-fix
Ruby: fix CI jobs after removal of `.codeql-manifest.json`
2021-11-24 17:16:52 +01:00
Erik Krogh Kristensen
1e752f305d apply the explicit this patch to new code 2021-11-24 15:26:19 +01:00
Erik Krogh Kristensen
08ce03cd93 Merge branch 'main' into explicit-this 2021-11-24 15:24:58 +01:00
Erik Krogh Kristensen
3bab8c6d1d Merge pull request #7173 from erik-krogh/getRubyInSync
JS/PY/RB: get ReDoSUtil in sync for ruby
2021-11-24 15:20:23 +01:00
luchua-bc
b0031a0d85 Add local input test case and update qldoc 2021-11-24 13:30:50 +00:00
Rasmus Wriedt Larsen
7dde52ced2 Merge pull request #7131 from RasmusWL/wsgiref.simple_server
Python: Model `wsgiref.simple_server` applications
2021-11-24 14:22:23 +01:00
Rasmus Wriedt Larsen
2a5e0a3b77 Merge pull request #7145 from RasmusWL/remove-owasp-tags
Python/Ruby: Remove owasp tags
2021-11-24 13:56:48 +01:00
Rasmus Wriedt Larsen
e2652591a5 Python: Change perf fix PoorMansFunctionResolution
Thanks @yoff, this leaves us with the following evaluation, which looks
very close to the one in the other fix (but with cleaner implementation)
-- both at 688k max tuples (although numbers are not exactly the same).

```
[2021-11-24 13:48:40] (14s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@e5f05asv after 74ms:
                      47493  ~3%     {3} r1 = JOIN Class::Class::getAMethod_dispred#ff WITH py_Classes ON FIRST 1 OUTPUT Lhs.1, 0, Lhs.0
                      47335  ~0%     {2} r2 = JOIN r1 WITH AstGenerated::Function_::getArg_dispred#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2
                      46683  ~0%     {2} r3 = JOIN r2 WITH DataFlowPublic::ParameterNode::getParameter_dispred#fb_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
                      259968 ~4%     {2} r4 = JOIN r3 WITH LocalSources::Cached::hasLocalSource#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1
                      161985 ~0%     {3} r5 = JOIN r4 WITH Attributes::AttrRef::accesses_dispred#bff_102#join_rhs ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1, Rhs.2
                      161985 ~2%     {3} r6 = JOIN r5 WITH Attributes::AttrRead#class#f ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.0 'result'
                      688766 ~0%     {3} r7 = JOIN r6 WITH Function::Function::getName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1 'func', Lhs.2 'result'
                      20928  ~0%     {2} r8 = JOIN r7 WITH Class::Class::getAMethod_dispred#ff ON FIRST 2 OUTPUT Lhs.1 'func', Lhs.2 'result'
                                     return r8
```
2021-11-24 13:52:05 +01:00
Chris Smowton
c74eac4930 Remove needless casts 2021-11-24 12:18:05 +00:00
Chris Smowton
cec91c4831 Update ThreadResourceAbuse.qhelp 2021-11-24 12:15:48 +00:00
Chris Smowton
5101a8e9f3 Fix qhelp test 2021-11-24 12:12:56 +00:00
Chris Smowton
136ecaf49a Abbreviate qhelp example 2021-11-24 12:12:22 +00:00
Chris Smowton
120f2045cd Document XXE sanitisation policy 2021-11-24 12:03:28 +00:00
Mathias Vorreiter Pedersen
6d9cea90cb Merge pull request #7226 from MathiasVP/shorter-ir-dataflow-paths
C++: Hide some IR dataflow nodes
2021-11-24 11:13:52 +00:00
Rasmus Wriedt Larsen
47448d9efc Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-11-24 12:02:12 +01:00
Mathias Vorreiter Pedersen
6c7a01d3d5 C++: Add some comments to the two 'flowThrough' predicates. 2021-11-24 10:50:44 +00:00
yoff
f9729bccef Merge pull request #7143 from RasmusWL/path-improvements
Python: Model `posixpath` and `os.stat`
2021-11-24 11:36:06 +01:00
Anders Schack-Mulligen
a3b263ee6e Merge pull request #7181 from bmuskalla/coverageAsDiagnostics
Java: Add diagnostic query for framework coverage
2021-11-24 10:57:50 +01:00
Mathias Vorreiter Pedersen
2e7ddb479e C++: Accept test changes. 2021-11-24 09:41:00 +00:00
Mathias Vorreiter Pedersen
4cbfc306ac C++: Hide dataflow nodes if they're just used for flow-through for read steps or store steps. 2021-11-24 08:01:44 +00:00
Arthur Baars
133ec2e4af Fix CI jobs 2021-11-23 22:03:01 +01:00
Erik Krogh Kristensen
87a1ccd428 Merge branch 'main' into getRubyInSync 2021-11-23 20:20:37 +01:00
luchua-bc
e56737e007 Use value step to optimize the taint step and add a test case for Apache file upload listener 2021-11-23 17:15:28 +00:00
Mathias Vorreiter Pedersen
8c9e817c0d Merge pull request #7188 from github/redsun82/fix-operand-location
C++: take IR Operand locations from definitions
2021-11-23 16:32:06 +00:00
Nick Rolfe
bb38c4d6fd Merge pull request #6978 from github/nickrolfe/regex_injection
Ruby: add regex injection query
2021-11-23 16:22:35 +00:00
Nick Rolfe
1a90b388a9 Merge remote-tracking branch 'origin/main' into nickrolfe/regex_injection 2021-11-23 15:42:05 +00:00
Paolo Tranquilli
055017de49 fix how non existing locations are accounted for 2021-11-23 15:28:16 +00:00
Paolo Tranquilli
9538ac73e4 account for non-existing locations 2021-11-23 15:28:16 +00:00
Paolo Tranquilli
d626745ab1 fix ThisArgumentOperand location
The correct check to do to choose between using `getAnyDef` and `getUse`
is to check whether the location is an instance of UknonwnLocation.
2021-11-23 15:28:16 +00:00
Paolo Tranquilli
e99a040884 implement review suggestions 2021-11-23 15:28:16 +00:00
Paolo Tranquilli
8b44d5c39e sync files 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
30805d964c add ThisArgumentOperand special case 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
9b818a04f2 sync 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
0bb11fa371 fix PrintAST test run
The refactored shouldDumpFunction was now rejecting functions without a
location. This is fixed now.
2021-11-23 15:28:15 +00:00
Paolo Tranquilli
0547e4ccf2 update further test with new locations 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
d4e80c664e replace shouldDump -> shouldDumpLocation 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
4498657384 Apply suggestions from code review
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-11-23 15:28:15 +00:00
Paolo Tranquilli
28806fe5f4 update test results after operand location changes 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
6072ccd81d auto-format 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
0ff9520575 ...and syncing files again 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
b5165e3692 C++: more fine-grained Operand location change
Only RegisterOperands need the change, with the notable exception of
ThisArgumentOperand.
2021-11-23 15:28:15 +00:00
Paolo Tranquilli
5202f963dd C++: sync Operand source 2021-11-23 15:28:15 +00:00
Paolo Tranquilli
74c0197544 C++: take IR Operand locations from definitions
Previously Operand's getLocation would take it from the Operand use.
This lead to slightly confusing query results, where for example an
issue related to a call argument would highlight the function part of
the call instead of the parameter.
2021-11-23 15:28:15 +00:00
Tom Hvitved
83d204d7a8 Merge pull request #7218 from hvitved/ssa/fix-consistency-tests
Ruby: Fix SSA consistency tests + CFG bug
2021-11-23 16:24:41 +01:00
Tom Hvitved
4d918b5e5f Ruby: Fix CFG splitting logic for ensure blocks with loops 2021-11-23 15:21:43 +01:00
Geoffrey White
3e1164f82e Merge pull request #7109 from MathiasVP/remove-reference-to-as-load
C++: Don't interpret 'ReferenceToInstruction' as a load
2021-11-23 13:56:22 +00:00
Alex Ford
055641e684 Merge pull request #7062 from github/ruby/rails-csrf
Ruby: Add `rb/csrf-protection-disabled` query
2021-11-23 13:46:42 +00:00
Taus
8cccee6eba Merge pull request #6972 from yoff/python/promote-redos
Python: Promote ReDoS queries
2021-11-23 14:02:09 +01:00
Tom Hvitved
0bd587b395 Shared SSA: Sync files 2021-11-23 13:30:37 +01:00
Tom Hvitved
e185e9080c Shared SSA: Fix consistency tests 2021-11-23 13:30:23 +01:00
Erik Krogh Kristensen
b2e40ac603 fix typo in test
Co-authored-by: Nick Rolfe <nickrolfe@github.com>
2021-11-23 13:09:22 +01:00
Nick Rolfe
e5f473052d Ruby: add Regexp.{compile,quote} to regex injection test 2021-11-23 11:05:41 +00:00
Tom Hvitved
9d072a12ed Merge pull request #7098 from github/ruby/desugar-for-1
Ruby: Desugar `for` loops as calls to `each`
2021-11-23 11:35:49 +01:00
Mathias Vorreiter Pedersen
672485ae38 Merge branch 'main' into remove-reference-to-as-load 2021-11-23 10:24:17 +00:00
James Fletcher
21aff99637 Merge pull request #7215 from github/jf205-patch-1
Fix link formatting
2021-11-23 10:03:40 +00:00
Tom Hvitved
dcca5d28bb Merge pull request #7172 from hvitved/ruby/ensure-split-cp
Ruby: Remove CP in `EnsureSplitImpl::exit/3`
2021-11-23 11:02:23 +01:00
Benjamin Muskalla
50518b5622 Fix sum of rows 2021-11-23 10:42:24 +01:00
James Fletcher
b8e8ddf9ae fix link 2021-11-23 08:38:39 +00:00
Anders Schack-Mulligen
a68b55b099 Merge pull request #7208 from hvitved/ruby/restrict-use-use
Ruby: Restrict use-use flow
2021-11-23 09:33:43 +01:00
luchua-bc
ed78d39d61 Move duplicate code to the shared library and update qldoc 2021-11-23 03:06:26 +00:00
Henry Mercer
245edd41ff Merge pull request #7186 from github/henrymercer/rename-available-models-predicate
JS: [Internal only] Rename the available ML models external predicate
2021-11-22 18:26:46 +00:00
Nick Rolfe
13459c8afc Ruby: add Regexp.compile as sink for regexp injection query 2021-11-22 17:43:55 +00:00
Nick Rolfe
4b42c4447b Ruby: handle Regexp.quote wherever we handle Regexp.escape 2021-11-22 17:12:01 +00:00
Nick Rolfe
5b11cfe006 Ruby: fix up import path 2021-11-22 17:10:46 +00:00
Nick Rolfe
752b126862 Merge remote-tracking branch 'origin/main' into nickrolfe/regex_injection 2021-11-22 17:05:27 +00:00
Rasmus Wriedt Larsen
eaed870b31 Python: Fix performance problem in PoorMansFunctionResolution
Before these changes:

[2021-11-22 12:02:50] (8s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@cbddf257 after 8.6s:
                      387565   ~0%     {3} r1 = JOIN Attributes::AttrRead#class#f WITH Attributes::AttrRef::accesses_dispred#bff ON FIRST 1 OUTPUT Rhs.2, Lhs.0 'result', Rhs.1
                      6548632  ~0%     {3} r2 = JOIN r1 WITH Function::Function::getName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'func', Lhs.1 'result', Lhs.2
                      5640480  ~0%     {4} r3 = JOIN r2 WITH Class::Class::getAMethod_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'result', Lhs.2, Lhs.0 'func'
                      55660458 ~0%     {5} r4 = JOIN r3 WITH Class::Class::getAMethod_dispred#ff ON FIRST 1 OUTPUT Rhs.1, 0, Lhs.1 'result', Lhs.2, Lhs.3 'func'
                      55621412 ~0%     {4} r5 = JOIN r4 WITH AstGenerated::Function_::getArg_dispred#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2 'result', Lhs.3, Lhs.4 'func'
                      54467144 ~0%     {4} r6 = JOIN r5 WITH DataFlowPublic::ParameterNode::getParameter_dispred#fb_10#join_rhs ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Lhs.1 'result', Lhs.3 'func'
                      20928    ~0%     {2} r7 = JOIN r6 WITH LocalSources::Cached::hasLocalSource#ff ON FIRST 2 OUTPUT Lhs.3 'func', Lhs.2 'result'
                                       return r7

With these changes:

[2021-11-22 11:54:25] (415s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper#fff/3@14db70a8 after 75ms:
                      388306 ~0%     {2} r1 = JOIN Attributes::AttrRead#class#f WITH Attributes::AttrRef::getObject_dispred#bf ON FIRST 1 OUTPUT Rhs.1, Lhs.0 'read'
                      379420 ~4%     {2} r2 = JOIN r1 WITH LocalSources::Cached::hasLocalSource#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'read'
                      175082 ~0%     {2} r3 = JOIN r2 WITH DataFlowPublic::ParameterNode#class#fff ON FIRST 1 OUTPUT Rhs.2, Lhs.1 'read'
                      175082 ~2%     {3} r4 = JOIN r3 WITH Essa::ParameterDefinition::getParameter_dispred#ff ON FIRST 1 OUTPUT 0, Rhs.1, Lhs.1 'read'
                      166798 ~0%     {2} r5 = JOIN r4 WITH AstGenerated::Function_::getArg_dispred#fff_120#join_rhs ON FIRST 2 OUTPUT Rhs.2 'func', Lhs.2 'read'
                      162096 ~0%     {3} r6 = JOIN r5 WITH Class::Class::getAMethod_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.0 'func', Rhs.1 'cls', Lhs.1 'read'
                                     return r6

[2021-11-22 11:54:25] (415s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper2#ffff/4@2b60f0s9 after 63ms:
                      162046 ~0%     {3} r1 = SCAN PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper#fff OUTPUT In.2 'read', In.0 'func', In.1 'cls'
                      162046 ~0%     {3} r2 = JOIN r1 WITH Attributes::AttrRead#class#f ON FIRST 1 OUTPUT Lhs.1 'func', Lhs.2 'cls', Lhs.0 'read'
                      162046 ~1%     {3} r3 = JOIN r2 WITH py_Functions ON FIRST 1 OUTPUT Lhs.1 'cls', Lhs.2 'read', Lhs.0 'func'
                      162046 ~0%     {3} r4 = JOIN r3 WITH py_Classes ON FIRST 1 OUTPUT Lhs.1 'read', Lhs.2 'func', Lhs.0 'cls'
                      161935 ~5%     {4} r5 = JOIN r4 WITH Attributes::AttrRef::getAttributeName_dispred#bf ON FIRST 1 OUTPUT Rhs.1, Lhs.0 'read', Lhs.1 'func', Lhs.2 'cls'
                      688526 ~1%     {4} r6 = JOIN r5 WITH Function::Function::getName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.2 'func', Lhs.3 'cls', Lhs.1 'read', Rhs.1 'readFunction'
                                     return r6

[2021-11-22 11:54:25] (415s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@f73ae6dq after 58ms:
                      688526 ~0%     {4} r1 = SCAN PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper2#ffff OUTPUT In.1, In.0, In.3 'func', In.2 'result'
                      688526 ~0%     {3} r2 = JOIN r1 WITH Class::Class::getAMethod_dispred#ff ON FIRST 2 OUTPUT Rhs.0, Lhs.2 'func', Lhs.3 'result'
                      20913  ~0%     {2} r3 = JOIN r2 WITH Class::Class::getAMethod_dispred#ff ON FIRST 2 OUTPUT Lhs.1 'func', Lhs.2 'result'
                                     return r3

We need the `pragma[only_bind_into]` in getSimpleMethodReferenceWithinClass_helper2, otherwise the tuple counts would look like, which is needlessly big.

[2021-11-22 17:14:34] (2s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper2#ffff/4@5f0505h7 after 711ms:
                      13570510 ~3%     {2} r1 = JOIN Function::Function::getName_dispred#ff_10#join_rhs WITH Attributes::AttrRef::getAttributeName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'read', Lhs.1 'readFunction'
                      688526   ~1%     {4} r2 = JOIN r1 WITH PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass_helper#fff_201#join_rhs ON FIRST 1 OUTPUT Rhs.1 'func', Rhs.2 'cls', Lhs.0 'read', Lhs.1 'readFunction'
                                       return r2
2021-11-22 17:22:39 +01:00
Arthur Baars
f6baab6399 Merge pull request #7211 from dbartol/dbartol/ruby-workspace
Merge Ruby workspace into root workspace
2021-11-22 16:22:12 +01:00
Alex Ford
68c3c16ab3 Ruby: enable forgery protection checks for development environments 2021-11-22 15:00:32 +00:00
Dave Bartolomeo
186e3755c0 Remove unnecessary path options 2021-11-22 09:50:01 -05:00
Tom Hvitved
da39f15a9d Ruby: Move localFlowStepCommon into LocalFlow and make localSsaFlowStep private 2021-11-22 15:24:24 +01:00
Dave Bartolomeo
522074940d Merge Ruby workspace into root workspace 2021-11-22 09:10:59 -05:00
AlonaHlobina
b60fef88b5 Merge pull request #7206 from github/AlonaHlobina-patch-2
Update query-metadata-style-guide.md
2021-11-22 14:48:46 +01:00
Mathias Vorreiter Pedersen
21167f4b67 C++: Accept test changes. 2021-11-22 13:04:23 +00:00
Mathias Vorreiter Pedersen
f308be7382 C++: Restore the missing flow. This has a couple of side-effects: First, it gives us some new good flow (yay). Second, it causes some duplication of results that uses 'argv' as a taint source. The duplication isn't very bad, though. And since it is only for paths that start at 'argv', I think we can live with it for now. 2021-11-22 13:04:07 +00:00
Mathias Vorreiter Pedersen
74221f4aba Merge pull request #7209 from geoffw0/experimental-tests
C++: Move experimental test.
2021-11-22 13:01:52 +00:00
Harry Maclean
6f22867af9 Merge pull request #7015 from github/hmac/ssrf
Ruby: Add Server-Side Request Forgery query
2021-11-22 12:41:39 +00:00
CodeQL CI
ddeb700fd6 Merge pull request #7207 from github/asgerf/document-template-language-extensions
Approved by esbena
2021-11-22 04:16:19 -08:00
Tom Hvitved
fc64faefcf Ruby: Restrict use-use flow 2021-11-22 13:05:17 +01:00
Geoffrey White
6f2b528a32 C++: Move experimental test. 2021-11-22 11:02:06 +00:00
Asger F
8322a44379 JS: Mention .hbs, .ejs, and .njk file extensions
Also fixes a typo `.xhm` -> `.xhtm`
2021-11-22 11:53:55 +01:00
Rasmus Wriedt Larsen
f09f1c4c50 Python: Minor refactor in PoorMansFunctionResolution 2021-11-22 11:11:29 +01:00
Tom Hvitved
39e3254fe0 Merge pull request #7182 from hvitved/csharp/self-assignment-bad-magic
C#: Fix bad magic `Element::fromSource` in context of `SelfAssignment.ql`
2021-11-22 10:57:48 +01:00
AlonaHlobina
0de6511dff Update query-metadata-style-guide.md 2021-11-22 10:17:57 +01:00
Erik Krogh Kristensen
9f08acab7e Merge pull request #7170 from erik-krogh/qldocStyle
Ruby: use A/An/The to start qlDoc for classes
2021-11-19 17:34:35 +01:00
Harry Maclean
06000781e9 Ruby: Document PairCfgNode::getKey/getValue 2021-11-19 14:54:06 +00:00
Henry Mercer
8ba864e897 JS: Rename the available ML models external predicate 2021-11-19 12:56:03 +00:00
Erik Krogh Kristensen
75586b0cf6 Apply suggestions from code review
Co-authored-by: Nick Rolfe <nickrolfe@github.com>
2021-11-19 13:23:01 +01:00
Tom Hvitved
a393bff6cb C#: Fix bad magic Element::getLocation in context of SelfAssignment.ql 2021-11-19 12:44:07 +01:00
Harry Maclean
90a9688310 Ruby: update CFG fixture 2021-11-19 11:31:14 +00:00
Benjamin Muskalla
cd39d15b40 Simplify diagnostic query 2021-11-19 12:28:24 +01:00
Harry Maclean
8fc7e4be43 Ruby: Increase precision of SSRF query 2021-11-19 11:28:09 +00:00
Harry Maclean
c297a68acf Model more of the RestClient API
We now handle this form:

    RestClient::Request.execute(url: "http://example.com")
2021-11-19 11:28:09 +00:00
Harry Maclean
e2ef780c55 Add base_uri note to HTTParty modelling 2021-11-19 11:28:09 +00:00
Harry Maclean
38ff584307 Model more Faraday behaviour
You can instantiate a Faraday connection by passing a URL as an keyword
argument:

    conn = Faraday.new(url: "http://example.com")
2021-11-19 11:28:09 +00:00
Harry Maclean
f933d24031 Fix comment 2021-11-19 11:28:09 +00:00
Harry Maclean
70efadac77 Add change note for Ruby SSRF query 2021-11-19 11:28:09 +00:00
Harry Maclean
e87a4531d8 Remove redundant imports 2021-11-19 11:28:08 +00:00
Harry Maclean
ac20eafecc Add qhelp for Ruby SSRF 2021-11-19 11:28:08 +00:00
Harry Maclean
2bba31eb02 Update metadata of Ruby SSRF query 2021-11-19 11:28:08 +00:00
Harry Maclean
dc464879a2 Add a query for server-side request forgery 2021-11-19 11:28:08 +00:00
Harry Maclean
cd33e4d394 Make string interpolation sanitizer reusable 2021-11-19 11:28:08 +00:00
Harry Maclean
b6ce37b241 Add getURL to HTTP::Client::Request
This member predicate gets dataflow nodes which contribute to the URL of
the request.

Also consolidate the identical tests for each HTTP client.
2021-11-19 11:28:08 +00:00
Harry Maclean
8fd8c9b04d Fix CallExprCfgNode.getKeywordArgument
This predicate now produces results.
2021-11-19 11:28:08 +00:00
Harry Maclean
0caea17118 Add a test for CallCfgNodes
This test shows that `CallCfgNode.getKeywordArgument(string keyword)`
doesn't return any results.
2021-11-19 11:28:07 +00:00
Benjamin Muskalla
fb9b16325d Add diagnostic query for framework coverage 2021-11-19 10:30:59 +01:00
luchua-bc
b6a6ed5ba3 Add a recommendation category query for local user input and check Apache file upload 2021-11-19 04:23:19 +00:00
Tom Hvitved
a4538de3a3 Shared CFG: Rename TNode to TCfgNode
This is in order to avoid name clash with the often so-named IPA type for data-
flow nodes. The name clash is not problematic because they are both in scope,
but because (cached) IPA types with overlapping names are known to sometimes
result in re-evaluation of cached stages, when one of the IPA types gets an
internal `#2` suffix in one query run, and the other IPA type gets the suffix
in another run.
2021-11-18 19:15:36 +01:00
Erik Krogh Kristensen
ee858d840e get ReDoSUtil in sync for ruby 2021-11-18 16:49:34 +01:00
Tom Hvitved
2218516685 Ruby: Remove CP in EnsureSplitImpl::exit/3 2021-11-18 16:05:09 +01:00
Erik Krogh Kristensen
af55f172ae use A/An/The to start qlDoc for classes 2021-11-18 15:42:45 +01:00
Tom Hvitved
de72a765e0 Ruby: Update expected CFG test output (reordering) 2021-11-17 13:44:55 +01:00
Tom Hvitved
9ff63b00d6 Ruby: Remove CFG dependency from AST stage
Commit 028ef6f27f had the unintended side-effect
that the AST and CFG stages got merged, because the AST stage's `isCapturedAccess`
now depends on `getCfgScopeImpl`, which belongs to the CFG stage.

The fix is to remove `getCfgScopeImpl` from the CFG stage, and instead let it
be part of the AST stage.
2021-11-17 13:15:55 +01:00
Tom Hvitved
08c778241d Ruby: Adopt to changes after rebase 2021-11-17 09:17:32 +01:00
Tom Hvitved
413375992d Ruby: Flatten nested statements inside desugared for loops 2021-11-17 09:05:37 +01:00
Tom Hvitved
9125b85ff0 Ruby: Add missing QL doc 2021-11-17 09:05:37 +01:00
Tom Hvitved
92453bd2c5 Ruby: Rewrite break_ensure.rb CFG test to use while loops instead of for loops 2021-11-17 09:05:37 +01:00
Tom Hvitved
945bb7459a Ruby: Update expected test output 2021-11-17 09:05:37 +01:00
Tom Hvitved
a62ad5000b Ruby: Make isCapturedAccess work with synthesized scopes 2021-11-17 09:05:37 +01:00
Tom Hvitved
135ee0d0c1 Ruby: Add implicit writes for synthesized parameters 2021-11-17 09:05:37 +01:00
Tom Hvitved
028ef6f27f Ruby: Handle synthesized scopes 2021-11-17 09:05:37 +01:00
Tom Hvitved
48e6bdb117 Ruby: Remove EmptinessCompletion 2021-11-17 09:05:36 +01:00
Tom Hvitved
db6f843641 Ruby: Hide SynthBlock from the public API 2021-11-17 09:05:36 +01:00
Alex Ford
8603609698 Update test output to account for for-loop -> each desugaring 2021-11-17 09:05:36 +01:00
Alex Ford
e468434b82 ruby: drop special handling of for-in loops in the CFG 2021-11-17 09:05:33 +01:00
Alex Ford
ddfcfc9b67 Desugar for loops as each calls 2021-11-17 09:04:29 +01:00
Alex Ford
f6d99dc00d Define getBlockImpl for synthesized method calls 2021-11-17 09:04:29 +01:00
Alex Ford
a743067dc8 Support synthesis of blocks (without a new variable scope) 2021-11-17 09:04:29 +01:00
Alex Ford
04df56d1c0 Support synthesis of SimpleParameters 2021-11-17 09:04:29 +01:00
Rasmus Wriedt Larsen
98e6fc8a88 Python/Ruby: Remove owasp tags
These are no longer correct, since the A1 category changed from 2017 to
2021, see https://owasp.org/Top10/#whats-changed-in-the-top-10-for-2021

Since only a very few queries had these tags, I think we're much better
off having them removed.
2021-11-16 12:03:50 +01:00
Rasmus Wriedt Larsen
a980f26fda Python: Model os.stat (and friends) 2021-11-16 10:45:32 +01:00
Rasmus Wriedt Larsen
9f4107d211 Python: Model posixpath, ntpath, and genericpath modules 2021-11-16 10:45:14 +01:00
Rasmus Wriedt Larsen
9e097f5430 Python: Improve PoorMansFunctionResolution 2021-11-15 13:40:19 +01:00
Rasmus Wriedt Larsen
0d4cb1e6ce Python: Add test of PoorMansFunctionResolution 2021-11-15 13:34:39 +01:00
Rasmus Wriedt Larsen
6eb4525ab2 Python: Model wsgiref.simple_server applications 2021-11-15 13:34:39 +01:00
Rasmus Wriedt Larsen
e812029c03 Python: Add test for wsgiref.simple_server 2021-11-15 13:34:38 +01:00
Erik Krogh Kristensen
f0c5a80d1a apply the explicit this patch to new code 2021-11-13 21:03:54 +01:00
Erik Krogh Kristensen
0ff36cd083 Merge branch 'main' into explicit-this 2021-11-13 21:01:25 +01:00
Nick Rolfe
9034d74663 Ruby: add file-level qldoc 2021-11-12 11:12:27 +00:00
Mathias Vorreiter Pedersen
dbcd4d6d5d C++: Remove 'ReferenceToInstruction' from the list of instructions we interpret as a load. This makes use lose a bunch of flow, and we'll restore this flow in the next commit. 2021-11-11 10:38:52 +00:00
Alex Ford
556cdbaa21 ruby: QL format 2021-11-09 14:09:11 +00:00
Alex Ford
37775407a9 ruby: drop a redundant bit of documentation 2021-11-09 14:07:00 +00:00
Alex Ford
340897f262 ruby: drop unnecessary variable 2021-11-09 14:06:21 +00:00
Alex Ford
a23750a9c7 ruby: inline some predicates 2021-11-09 14:06:21 +00:00
Alex Ford
c65d1d9a50 ruby: CSRFProtectionDisabled.qhelp fixes
Co-authored-by: Harry Maclean <hmac@github.com>
2021-11-09 14:05:41 +00:00
Mathias Vorreiter Pedersen
10bca3544c C++: Change 'annotate_path_to_sink' so that you now annotate a ir-path with the previous node (instead of its source). This gives a better overview of the path. 2021-11-09 13:49:12 +00:00
Alex Ford
5f78bbbf52 add missing documentation 2021-11-04 21:07:54 +00:00
Alex Ford
543bd28b03 add a change note for rb/csrf-protection-disabled 2021-11-04 20:14:54 +00:00
Alex Ford
d324f9397c qhelp for rb/csrf-protection-disabled 2021-11-04 19:56:56 +00:00
Alex Ford
25da904314 test cases for rb/csrf-protection-disabled 2021-11-04 19:56:56 +00:00
Alex Ford
4666024419 model some ways to configure Rails 2021-11-04 19:56:56 +00:00
Alex Ford
91f99ed2a1 model skip_forgery_protection calls in ActionController classes 2021-11-04 19:56:56 +00:00
Alex Ford
fad7e9489b Add a query to detect instances of CSRF protection being disabled 2021-11-04 19:56:55 +00:00
Alex Ford
8a412dc5fd Add CSRFProtectionSetting concept 2021-11-04 18:18:29 +00:00
Nick Rolfe
dd17271ec8 Merge remote-tracking branch 'origin/main' into nickrolfe/regex_injection 2021-11-03 11:55:42 +00:00
Erik Krogh Kristensen
db40ccae81 add explicit this to all member calls 2021-11-01 09:51:15 +01:00
Nick Rolfe
fed0a06353 Ruby: add change note for rb/regexp-injection 2021-10-29 11:28:34 +01:00
Rasmus Lerchedahl Petersen
7201b3e116 Python: add changenote 2021-10-28 14:48:48 +02:00
Rasmus Lerchedahl Petersen
8536f5f5a2 Python: remember to update refs... 2021-10-28 14:32:53 +02:00
Nick Rolfe
bd92403b42 Ruby: fix qhelp 2021-10-28 10:42:56 +01:00
Nick Rolfe
11154a9409 Ruby: add regex injection query 2021-10-27 15:58:12 +01:00
Rasmus Lerchedahl Petersen
fed6a97eb8 Python: Promote ReDoS queries 2021-10-27 11:03:57 +02:00
luchua-bc
378db7de87 Remove local user input and use fluent model 2021-09-27 17:33:04 +00:00
luchua-bc
5264936fc3 Correct the run method and add Math.min check 2021-09-24 21:00:53 +00:00
luchua-bc
272e4f6cf9 Update the query 2021-09-24 01:48:11 +00:00
luchua-bc
2dc38aee54 Update qldoc 2021-09-23 20:31:24 +00:00
luchua-bc
8170f01b66 Query to detect uncontrolled thread resource consumption 2021-09-20 02:12:47 +00:00
314 changed files with 14516 additions and 6117 deletions

View File

@@ -1,11 +1,16 @@
{ "provide": [ "ruby/.codeqlmanifest.json",
"*/ql/src/qlpack.yml",
"*/ql/lib/qlpack.yml",
"*/ql/test/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/upgrades/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml" ] }
{
"provide": [
"*/ql/src/qlpack.yml",
"*/ql/lib/qlpack.yml",
"*/ql/test/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/upgrades/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",
"ruby/ql/consistency-queries/qlpack.yml",
"ruby/extractor-pack/codeql-extractor.yml"
]
}

View File

@@ -41,7 +41,7 @@ jobs:
- name: Create database
run: |
codeql database create \
--search-path "${{ github.workspace }}/ruby" \
--search-path "${{ github.workspace }}/ruby/extractor-pack" \
--threads 4 \
--language ruby --source-root "${{ github.workspace }}/repo" \
"${{ runner.temp }}/database"

View File

@@ -32,14 +32,14 @@ jobs:
- uses: ./ruby/actions/create-extractor-pack
- name: Run QL tests
run: |
codeql test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" --consistency-queries ql/consistency-queries ql/test
codeql test run --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" "ql/src" "ql/examples"
codeql query compile --check-only --threads=4 --warnings=error "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check DB upgrade scripts

51
benjamin-button.md Normal file
View File

@@ -0,0 +1,51 @@
# benjamin-buttons.md
This file describes the changes that have been applied to
the library to make it behave as if it was younger.
## TaintedPath.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+pathinjection
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+tainted-path
Sinks from the "graceful-fs" and "fs-extra" (added before the open-sourcing squash).
## Xss.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- recursive type tracking for `jQuery::dollar`, `DOM::domValueRef`.
## SqlInjection.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sql
TypeTracking in SQL.qll (added before the open-sourcing squash)
The model of `mssql` and `sequelize` (added before the open-sourcing squash)
## PseudoProperties
Pseudo-properties (`$name$`) used in type-tracking and global dataflow configurations have been disabled.
Found by searching for `"\$.*\$"`.

View File

@@ -460,9 +460,10 @@
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll"
],
"ReDoS Util Python/JS": [
"ReDoS Util Python/JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll"
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll",
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll"
],
"ReDoS Exponential Python/JS": [
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",

View File

@@ -484,8 +484,9 @@ module TaintedWithPath {
/** Gets the element that `pathNode` wraps, if any. */
Element getElementFromPathNode(PathNode pathNode) {
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
result = node.asExpr() or
result = node.asParameter()
result = node.asInstruction().getAST()
or
result = node.asOperand().getDef().getAST()
)
or
result = pathNode.(EndpointPathNode).inner()

View File

@@ -299,7 +299,17 @@ predicate isImmutableOrUnobservable(Node n) {
}
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof OperandNode and not n instanceof ArgumentNode }
predicate nodeIsHidden(Node n) {
n instanceof OperandNode and not n instanceof ArgumentNode
or
StoreNodeFlow::flowThrough(n, _) and
not StoreNodeFlow::flowOutOf(n, _) and
not StoreNodeFlow::flowInto(_, n)
or
ReadNodeFlow::flowThrough(n, _) and
not ReadNodeFlow::flowOutOf(n, _) and
not ReadNodeFlow::flowInto(_, n)
}
class LambdaCallKind = Unit;

View File

@@ -806,7 +806,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
or
// Flow into, through, and out of store nodes
StoreNodeFlow::flowInto(nodeFrom, nodeTo)
StoreNodeFlow::flowInto(nodeFrom.asInstruction(), nodeTo)
or
StoreNodeFlow::flowThrough(nodeFrom, nodeTo)
or
@@ -831,23 +831,19 @@ private predicate adjacentDefUseFlow(Node nodeFrom, Node nodeTo) {
//Def-use flow
Ssa::ssaFlow(nodeFrom, nodeTo)
or
exists(Instruction loadAddress | loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) |
// Use-use flow through reads
exists(Node address |
Ssa::addressFlowTC(address.asInstruction(), loadAddress) and
Ssa::ssaFlow(address, nodeTo)
)
or
// Use-use flow through stores.
exists(Node store |
Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and
Ssa::ssaFlow(store, nodeTo)
)
// Use-use flow through stores.
exists(Instruction loadAddress, Node store |
loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) and
Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and
Ssa::ssaFlow(store, nodeTo)
)
)
}
private module ReadNodeFlow {
/**
* INTERNAL: Do not use.
*/
module ReadNodeFlow {
/** Holds if the read node `nodeTo` should receive flow from `nodeFrom`. */
predicate flowInto(Node nodeFrom, ReadNode nodeTo) {
nodeTo.isInitial() and
@@ -867,7 +863,12 @@ private module ReadNodeFlow {
)
}
/** Holds if the read node `nodeTo` should receive flow from the read node `nodeFrom`. */
/**
* Holds if the read node `nodeTo` should receive flow from the read node `nodeFrom`.
*
* This happens when `readFrom` is _not_ the source of a `readStep`, and `nodeTo` is
* the `ReadNode` that represents an address that directly depends on `nodeFrom`.
*/
predicate flowThrough(ReadNode nodeFrom, ReadNode nodeTo) {
not readStep(nodeFrom, _, _) and
nodeFrom.getOuter() = nodeTo
@@ -906,17 +907,25 @@ private module ReadNodeFlow {
}
}
private module StoreNodeFlow {
/**
* INTERNAL: Do not use.
*/
module StoreNodeFlow {
/** Holds if the store node `nodeTo` should receive flow from `nodeFrom`. */
predicate flowInto(Node nodeFrom, StoreNode nodeTo) {
nodeTo.flowInto(Ssa::getDestinationAddress(nodeFrom.asInstruction()))
predicate flowInto(Instruction instrFrom, StoreNode nodeTo) {
nodeTo.flowInto(Ssa::getDestinationAddress(instrFrom))
}
/** Holds if the store node `nodeTo` should receive flow from `nodeFom`. */
predicate flowThrough(StoreNode nFrom, StoreNode nodeTo) {
/**
* Holds if the store node `nodeTo` should receive flow from `nodeFom`.
*
* This happens when `nodeFrom` is _not_ the source of a `storeStep`, and `nodeFrom` is
* the `Storenode` that represents an address that directly depends on `nodeTo`.
*/
predicate flowThrough(StoreNode nodeFrom, StoreNode nodeTo) {
// Flow through a post update node that doesn't need a store step.
not storeStep(nFrom, _, _) and
nodeTo.getOuter() = nFrom
not storeStep(nodeFrom, _, _) and
nodeTo.getOuter() = nodeFrom
}
/**

View File

@@ -645,17 +645,18 @@ module Consistency {
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(_, def0, bb, i)))
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(_, _, bb, i)
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _)
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
}

View File

@@ -244,17 +244,6 @@ Instruction getDestinationAddress(Instruction instr) {
]
}
class ReferenceToInstruction extends CopyValueInstruction {
ReferenceToInstruction() {
this.getResultType() instanceof Cpp::ReferenceType and
not this.getUnary().getResultType() instanceof Cpp::ReferenceType
}
Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
Operand getSourceAddressOperand() { result = this.getUnaryOperand() }
}
/** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */
Instruction getSourceAddress(Instruction instr) { result = getSourceAddressOperand(instr).getDef() }
@@ -266,11 +255,7 @@ Operand getSourceAddressOperand(Instruction instr) {
result =
[
instr.(LoadInstruction).getSourceAddressOperand(),
instr.(ReadSideEffectInstruction).getArgumentOperand(),
// `ReferenceToInstruction` is really more of an address-of operation,
// but by including it in this list we break out of `flowOutOfAddressStep` at an
// instruction that, at the source level, looks like a use of a variable.
instr.(ReferenceToInstruction).getSourceAddressOperand()
instr.(ReadSideEffectInstruction).getArgumentOperand()
]
}
@@ -295,10 +280,6 @@ Operand getSourceValueOperand(Instruction instr) {
result = instr.(LoadInstruction).getSourceValueOperand()
or
result = instr.(ReadSideEffectInstruction).getSideEffectOperand()
or
// See the comment on the `ReferenceToInstruction` disjunct in `getSourceAddressOperand` for why
// this case is included.
result = instr.(ReferenceToInstruction).getSourceValueOperand()
}
/**
@@ -513,6 +494,64 @@ private module Cached {
explicitWrite(false, storeNode.getStoreInstruction(), def)
)
or
// The destination of a store operation has undergone lvalue-to-rvalue conversion and is now a
// right-hand-side of a store operation.
// Find the next use of the variable in that store operation, and recursively find the load of that
// pointer. For example, consider this case:
//
// ```cpp
// int x = source();
// int* p = &x;
// sink(*p);
// ```
//
// if we want to find the load of the address of `x`, we see that the pointer is stored into `p`,
// and we then need to recursively look for the load of `p`.
exists(
Def def, StoreInstruction store, IRBlock block1, int rnk1, Use use, IRBlock block2, int rnk2
|
store = def.getInstruction() and
store.getSourceValueOperand() = operand and
def.hasRankInBlock(block1, rnk1) and
use.hasRankInBlock(block2, rnk2) and
adjacentDefRead(_, block1, rnk1, block2, rnk2)
|
// The shared SSA library has determined that `use` is the next use of the operand
// so we find the next load of that use (but only if there is no `PostUpdateNode`) we
// need to flow into first.
not StoreNodeFlow::flowInto(store, _) and
flowOutOfAddressStep(use.getOperand(), nodeTo)
or
// It may also be the case that `store` gives rise to another store step. So let's make sure that
// we also take those into account.
StoreNodeFlow::flowInto(store, nodeTo)
)
or
// As we find the next load of an address, we might come across another use of the same variable.
// In that case, we recursively find the next use of _that_ operand, and continue searching for
// the next load of that operand. For example, consider this case:
//
// ```cpp
// int x = source();
// use(&x);
// int* p = &x;
// sink(*p);
// ```
//
// The next use of `x` after its definition is `use(&x)`, but there is a later load of the address
// of `x` that we want to flow to. So we use the shared SSA library to find the next load.
not operand = getSourceAddressOperand(_) and
exists(Use use1, Use use2, IRBlock block1, int rnk1, IRBlock block2, int rnk2 |
use1.getOperand() = operand and
use1.hasRankInBlock(block1, rnk1) and
// Don't flow to the next use if this use is part of a store operation that totally
// overrides a variable.
not explicitWrite(true, _, use1.getOperand().getDef()) and
adjacentDefRead(_, block1, rnk1, block2, rnk2) and
use2.hasRankInBlock(block2, rnk2) and
flowOutOfAddressStep(use2.getOperand(), nodeTo)
)
or
operand = getSourceAddressOperand(nodeTo.asInstruction())
or
exists(ReturnIndirectionInstruction ret |

View File

@@ -20,6 +20,14 @@ private import internal.OperandInternal
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
* opposed to testing `not loc isntanceof UnknownLocation`
*/
private class KnownLocation extends Language::Location {
KnownLocation() { not this instanceof Language::UnknownLocation }
}
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
* By default this is where the operand is used, but some subclasses may override this
* using `getAnyDef()` if it makes more sense.
*/
final Language::Location getLocation() { result = this.getUse().getLocation() }
Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
final override string toString() { result = tag.toString() }
// most `RegisterOperands` have a more meaningful location at the definition
// the only exception are specific cases of `ThisArgumentOperand`
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
}
/**
* An operand representing the implicit 'this' argument to a member function
* An operand representing the implicit `this` argument to a member function
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
// in most cases the def location makes more sense, but in some corner cases it
// has an unknown location: in those cases we fall back to the use location
override Language::Location getLocation() {
if this.getAnyDef().getLocation() instanceof KnownLocation
then result = this.getAnyDef().getLocation()
else result = this.getUse().getLocation()
}
}
/**

View File

@@ -20,6 +20,14 @@ private import internal.OperandInternal
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
* opposed to testing `not loc isntanceof UnknownLocation`
*/
private class KnownLocation extends Language::Location {
KnownLocation() { not this instanceof Language::UnknownLocation }
}
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
* By default this is where the operand is used, but some subclasses may override this
* using `getAnyDef()` if it makes more sense.
*/
final Language::Location getLocation() { result = this.getUse().getLocation() }
Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
final override string toString() { result = tag.toString() }
// most `RegisterOperands` have a more meaningful location at the definition
// the only exception are specific cases of `ThisArgumentOperand`
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
}
/**
* An operand representing the implicit 'this' argument to a member function
* An operand representing the implicit `this` argument to a member function
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
// in most cases the def location makes more sense, but in some corner cases it
// has an unknown location: in those cases we fall back to the use location
override Language::Location getLocation() {
if this.getAnyDef().getLocation() instanceof KnownLocation
then result = this.getAnyDef().getLocation()
else result = this.getUse().getLocation()
}
}
/**

View File

@@ -20,6 +20,14 @@ private import internal.OperandInternal
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
* opposed to testing `not loc isntanceof UnknownLocation`
*/
private class KnownLocation extends Language::Location {
KnownLocation() { not this instanceof Language::UnknownLocation }
}
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
* By default this is where the operand is used, but some subclasses may override this
* using `getAnyDef()` if it makes more sense.
*/
final Language::Location getLocation() { result = this.getUse().getLocation() }
Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
final override string toString() { result = tag.toString() }
// most `RegisterOperands` have a more meaningful location at the definition
// the only exception are specific cases of `ThisArgumentOperand`
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
}
/**
* An operand representing the implicit 'this' argument to a member function
* An operand representing the implicit `this` argument to a member function
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
// in most cases the def location makes more sense, but in some corner cases it
// has an unknown location: in those cases we fall back to the use location
override Language::Location getLocation() {
if this.getAnyDef().getLocation() instanceof KnownLocation
then result = this.getAnyDef().getLocation()
else result = this.getUse().getLocation()
}
}
/**

View File

@@ -4,8 +4,8 @@ using SinkFunction = void (*)(int);
void notSink(int notSinkParam);
void callsSink(int sinkParam) { // $ ir-path=31:28 ir-path=32:31 ir-path=34:22
sink(sinkParam); // $ ir-sink=31:28 ir-sink=32:31 ir-sink=34:22 ast=31:28 ast=32:31 ast=34:22 MISSING: ast,ir=28
void callsSink(int sinkParam) { // $ ir-path=31:23 ir-path=32:26 ir-path=34:17
sink(sinkParam); // $ ast=31:28 ast=32:31 ast=34:22 ir-sink
}
struct {
@@ -25,7 +25,7 @@ void assignGlobals() {
};
void testStruct() {
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ ir MISSING: ast
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ MISSING: ir-path,ast
globalStruct.notSinkPtr(atoi(getenv("TAINTED"))); // clean
globalUnion.sinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
@@ -48,8 +48,8 @@ class D2 : public D1 {
class D3 : public D2 {
public:
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 ir-path=73:30
sink(p); // $ ir-sink=58:10 ir-sink=60:17 ir-sink=61:28 ir-sink=62:29 ir-sink=63:33 ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 SPURIOUS: ast=73:30 ir-sink=73:30
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 SPURIOUS: ir-path=73:30
sink(p); // $ ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 ir-sink SPURIOUS: ast=73:30
}
};

View File

@@ -23,11 +23,10 @@ class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
override predicate isSink(Element e) { isSinkArgument(e) }
}
predicate irTaint(Element source, Element sink, string tag) {
exists(TaintedWithPath::PathNode sinkNode, TaintedWithPath::PathNode predNode |
predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag) {
exists(TaintedWithPath::PathNode sinkNode |
TaintedWithPath::taintedWithPath(source, _, _, sinkNode) and
predNode = getAPredecessor*(sinkNode) and
sink = getElementFromPathNode(predNode) and
// Make sure the path is actually reachable from this predecessor.
// Otherwise, we could pick `predNode` to be b when `source` is
// `source1` in this dataflow graph:
@@ -35,7 +34,7 @@ predicate irTaint(Element source, Element sink, string tag) {
// ^
// source2 ---> b --/
source = getElementFromPathNode(getAPredecessor*(predNode)) and
if sinkNode = predNode then tag = "ir-sink" else tag = "ir-path"
if predNode = sinkNode then tag = "ir-sink" else tag = "ir-path"
)
}
@@ -45,21 +44,25 @@ class IRDefaultTaintTrackingTest extends InlineExpectationsTest {
override string getARelevantTag() { result = ["ir-path", "ir-sink"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Element source, Element tainted, int n |
irTaint(source, tainted, tag) and
n = strictcount(Element otherSource | irTaint(otherSource, tainted, _)) and
(
n = 1 and value = ""
or
// If there is more than one source for this sink
// we specify the source location explicitly.
n > 1 and
exists(Element source, Element elem, TaintedWithPath::PathNode node, int n |
irTaint(source, node, tag) and
elem = getElementFromPathNode(node) and
n = count(int startline | getAPredecessor(node).hasLocationInfo(_, startline, _, _, _)) and
location = elem.getLocation() and
element = elem.toString()
|
// Zero predecessors means it's a source, and 1 predecessor means it has a unique predecessor.
// In either of these cases we leave out the location.
n = [0, 1] and value = ""
or
// If there is more than one predecessor for this node
// we specify the source location explicitly.
n > 1 and
exists(TaintedWithPath::PathNode pred | pred = getAPredecessor(node) |
value =
source.getLocation().getStartLine().toString() + ":" +
source.getLocation().getStartColumn()
) and
location = tainted.getLocation() and
element = tainted.toString()
getElementFromPathNode(pred).getLocation().getStartLine().toString() + ":" +
getElementFromPathNode(pred).getLocation().getStartColumn()
)
)
}
}

View File

@@ -13,8 +13,8 @@ struct S {
}
};
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=98:18
sink(a); // $ ast=96:26 ast=98:18 ir-sink=96:26 ir-sink=98:18
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=102:26
sink(a); // $ ast=96:26 ast=98:18 ir-sink
}
extern int i;
@@ -27,7 +27,7 @@ public:
class DerivedCallsSink : public BaseWithPureVirtual {
public:
void f(const char* p) override { // $ ir-path
sink(p); // $ ir-sink ast=108:10 SPURIOUS: ast=111:10
sink(p); // $ ast=108:10 ir-sink SPURIOUS: ast=111:10
}
};
@@ -49,8 +49,8 @@ public:
};
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
void f(const char* p) override { // $ ir-path
DerivedCallsSinkDiamond1::f(p);
void f(const char* p) override { // $ ir-path=53:37 ir-path=115:11
DerivedCallsSinkDiamond1::f(p); // $ ir-path
}
};
@@ -58,7 +58,7 @@ template<typename T>
class CRTP {
public:
void f(const char* p) { // $ ir-path
static_cast<T*>(this)->g(p);
static_cast<T*>(this)->g(p); // $ ir-path
}
};
@@ -79,7 +79,7 @@ class Derived2 : public Derived1 {
class Derived3 : public Derived2 {
public:
void f(const char* p) override { // $ ir-path=124:19 ir-path=126:43 ir-path=128:44
sink(p); // $ ast,ir-sink=124:19 ast,ir-sink=126:43 ast,ir-sink=128:44
sink(p); // $ ast=124:19 ast=126:43 ast=128:44 ir-sink
}
};
@@ -97,11 +97,11 @@ int main(int argc, char *argv[]) {
char*** p = &argv; // $ ast,ir-path
sink(*p[0]); // $ ast,ir-sink
sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18
calls_sink_with_argv(*p[i]); // $ MISSING: ast,ir-path
calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 MISSING:ast
sink(*(argv + 1)); // $ ast,ir-path ir-sink
sink(*(argv + 1)); // $ ast ir-path ir-sink
BaseWithPureVirtual* b = new DerivedCallsSink;

View File

@@ -190,9 +190,9 @@ void test_pointers1()
sink(ptr1); // $ ast MISSING: ir
sink(ptr2); // $ SPURIOUS: ast
sink(*ptr2); // $ ast MISSING: ir
sink(ptr3); // $ ast MISSING: ir
sink(ptr4); // $ SPURIOUS: ast
sink(*ptr4); // $ ast MISSING: ir
sink(ptr3); // $ ast,ir
sink(ptr4); // $ SPURIOUS: ast,ir
sink(*ptr4); // $ ast,ir
}
void test_pointers2()

View File

@@ -35,17 +35,17 @@ postWithInFlow
| BarrierGuard.cpp:60:3:60:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:8:20:8:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:3:22:6 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:9:22:20 | sourceArray1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:26:8:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:26:27:26:34 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:28:3:28:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:28:22:28:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:30:8:30:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:30:27:30:34 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:39:16:39:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -77,55 +77,55 @@ postWithInFlow
| dispatch.cpp:29:29:29:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:31:8:31:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:31:16:31:24 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:32:8:32:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:32:16:32:24 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:33:3:33:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:33:11:33:16 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:35:8:35:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:35:16:35:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:36:8:36:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:36:16:36:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:37:3:37:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:37:11:37:17 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:39:8:39:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:39:8:39:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:39:15:39:23 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:40:8:40:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:40:8:40:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:40:15:40:23 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:41:3:41:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:41:3:41:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:41:10:41:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:43:8:43:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:43:8:43:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:43:15:43:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:44:8:44:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:44:8:44:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:44:15:44:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:45:3:45:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:45:3:45:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:45:10:45:16 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:51:3:51:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:55:8:55:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:55:22:55:30 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:56:8:56:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:56:22:56:30 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:58:28:58:36 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:60:3:60:14 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:60:18:60:29 | Call [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:60:18:60:29 | new [post update] | PostUpdateNode should not be the target of local flow. |
@@ -140,34 +140,34 @@ postWithInFlow
| dispatch.cpp:65:10:65:21 | new [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:69:3:69:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:69:8:69:13 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:73:3:73:5 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:73:3:73:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:73:7:73:12 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:77:3:77:19 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:3:78:21 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:23:78:39 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:24:78:37 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:80:8:80:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:81:3:81:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:81:6:81:11 | x [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:85:3:85:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:3:89:10 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:12:89:17 | (Middle *)... [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:12:89:17 | (Top *)... [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:12:89:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:21:89:26 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:3:90:10 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:12:90:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:18:90:23 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:100:3:100:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:105:5:105:17 | maybeCallSink [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:113:30:113:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -176,11 +176,11 @@ postWithInFlow
| dispatch.cpp:127:31:127:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:129:10:129:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:129:18:129:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:130:10:130:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:130:10:130:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:130:17:130:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:148:3:148:3 | u [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:148:5:148:5 | f [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:168:3:168:4 | u2 [post update] | PostUpdateNode should not be the target of local flow. |
@@ -191,10 +191,10 @@ postWithInFlow
| example.c:24:9:24:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:24:20:24:20 | y [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:26:9:26:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:26:13:26:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:26:19:26:24 | coords [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:28:2:28:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:28:14:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:28:14:28:25 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:28:22:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| example.c:28:23:28:25 | pos [post update] | PostUpdateNode should not be the target of local flow. |
@@ -227,23 +227,23 @@ postWithInFlow
| lambdas.cpp:43:3:43:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:43:3:43:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:43:3:43:3 | c [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:3:45:3 | t [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:3:45:3 | u [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:3:45:3 | w [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:4:45:4 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:7:45:7 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:10:45:10 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:11:5:11:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:11:5:11:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:11:5:11:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:5:16:10 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:12:16:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:12:16:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:12:16:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:20:5:20:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:20:5:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:20:5:20:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
@@ -259,11 +259,11 @@ postWithInFlow
| ref.cpp:31:7:31:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:31:7:31:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:31:7:31:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:7:37:19 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:21:37:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:21:37:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:21:37:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:39:7:39:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:39:7:39:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:39:7:39:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
@@ -276,26 +276,26 @@ postWithInFlow
| ref.cpp:48:7:48:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:48:7:48:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:48:7:48:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:55:5:55:17 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:55:19:55:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:58:5:58:13 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:58:15:58:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:61:5:61:24 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:61:26:61:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:64:5:64:13 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:64:15:64:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:75:5:75:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:75:5:75:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:75:9:75:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:5:79:10 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:12:79:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:12:79:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:12:79:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:83:5:83:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:83:5:83:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:83:9:83:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
@@ -311,11 +311,11 @@ postWithInFlow
| ref.cpp:96:7:96:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:96:7:96:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:96:11:96:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:7:102:19 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:21:102:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:21:102:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:21:102:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:104:7:104:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:104:7:104:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:104:11:104:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
@@ -328,18 +328,18 @@ postWithInFlow
| ref.cpp:115:7:115:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:115:7:115:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:115:11:115:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:122:5:122:17 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:122:19:122:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:125:5:125:13 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:125:15:125:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:128:5:128:24 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:128:26:128:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:131:5:131:13 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:131:15:131:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:6:7:6:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:8:3:8:4 | t2 [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:12:5:12:6 | t2 [post update] | PostUpdateNode should not be the target of local flow. |
@@ -520,40 +520,40 @@ postWithInFlow
| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:383:7:383:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:3:384:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:10:384:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:11:384:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:389:7:389:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:390:8:390:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:3:391:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:10:391:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:11:391:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:3:400:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:10:400:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:11:400:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:406:8:406:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:3:407:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:10:407:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:11:407:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:417:3:417:14 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:417:16:417:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:423:3:423:18 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:423:21:423:25 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:429:3:429:18 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:429:20:429:24 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:436:3:436:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:436:19:436:23 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:442:3:442:16 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:442:18:442:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:453:7:453:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:456:7:456:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:458:7:458:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
@@ -561,12 +561,12 @@ postWithInFlow
| test.cpp:465:4:465:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:465:4:465:4 | p [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:469:7:469:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:470:3:470:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:470:22:470:22 | x [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:3:481:19 | content [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:21:481:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:21:481:30 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:21:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:24:481:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:481:24:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:482:8:482:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,28 @@
| A.cpp:25:13:25:13 | c | AST only |
| A.cpp:27:28:27:28 | c | AST only |
| A.cpp:31:14:31:21 | new | IR only |
| A.cpp:40:8:40:13 | 0 | IR only |
| A.cpp:41:8:41:13 | new | IR only |
| A.cpp:40:15:40:21 | 0 | IR only |
| A.cpp:41:15:41:21 | new | IR only |
| A.cpp:41:15:41:21 | new | IR only |
| A.cpp:47:12:47:18 | new | IR only |
| A.cpp:54:12:54:18 | new | IR only |
| A.cpp:55:8:55:10 | new | IR only |
| A.cpp:55:12:55:19 | new | IR only |
| A.cpp:55:12:55:19 | new | IR only |
| A.cpp:57:11:57:24 | new | IR only |
| A.cpp:57:11:57:24 | new | IR only |
| A.cpp:57:17:57:23 | new | IR only |
| A.cpp:57:28:57:30 | new | IR only |
| A.cpp:57:17:57:23 | new | IR only |
| A.cpp:62:13:62:19 | new | IR only |
| A.cpp:64:10:64:15 | new | IR only |
| A.cpp:64:21:64:28 | new | IR only |
| A.cpp:64:21:64:28 | new | IR only |
| A.cpp:71:13:71:19 | new | IR only |
| A.cpp:73:10:73:19 | new | IR only |
| A.cpp:73:25:73:32 | new | IR only |
| A.cpp:73:25:73:32 | new | IR only |
| A.cpp:89:15:89:21 | new | IR only |
| A.cpp:99:14:99:21 | new | IR only |
| A.cpp:100:9:100:9 | a | AST only |
| A.cpp:116:12:116:19 | new | IR only |
| A.cpp:126:8:126:10 | new | IR only |
| A.cpp:126:12:126:18 | new | IR only |
| A.cpp:126:12:126:18 | new | IR only |
| A.cpp:130:12:130:18 | new | IR only |
| A.cpp:142:10:142:10 | c | AST only |
@@ -33,57 +33,57 @@
| A.cpp:151:12:151:24 | new | IR only |
| A.cpp:159:12:159:18 | new | IR only |
| A.cpp:160:18:160:60 | new | IR only |
| A.cpp:160:18:160:60 | new | IR only |
| A.cpp:160:32:160:59 | 0 | IR only |
| A.cpp:160:32:160:59 | 0 | IR only |
| A.cpp:160:32:160:59 | new | IR only |
| A.cpp:161:18:161:40 | 0 | IR only |
| A.cpp:160:32:160:59 | new | IR only |
| A.cpp:160:43:160:49 | 0 | IR only |
| A.cpp:160:52:160:58 | 0 | IR only |
| A.cpp:161:18:161:40 | new | IR only |
| A.cpp:162:18:162:40 | 0 | IR only |
| A.cpp:161:29:161:35 | 0 | IR only |
| A.cpp:162:18:162:40 | new | IR only |
| A.cpp:162:29:162:35 | 0 | IR only |
| A.cpp:183:7:183:10 | head | AST only |
| A.cpp:184:13:184:16 | next | AST only |
| B.cpp:7:16:7:35 | 0 | IR only |
| B.cpp:7:16:7:35 | new | IR only |
| B.cpp:7:28:7:34 | 0 | IR only |
| B.cpp:8:16:8:27 | new | IR only |
| B.cpp:16:16:16:38 | 0 | IR only |
| B.cpp:16:16:16:38 | new | IR only |
| B.cpp:16:28:16:34 | 0 | IR only |
| B.cpp:17:16:17:27 | new | IR only |
| B.cpp:35:13:35:17 | elem1 | AST only |
| B.cpp:36:13:36:17 | elem2 | AST only |
| B.cpp:46:13:46:16 | box1 | AST only |
| C.cpp:18:12:18:18 | new | IR only |
| C.cpp:24:11:24:12 | s3 | AST only |
| C.cpp:30:5:30:8 | s2 | IR only |
| C.cpp:30:10:30:11 | s2 | IR only |
| C.cpp:30:10:30:11 | this | IR only |
| C.cpp:32:5:32:8 | s4 | IR only |
| C.cpp:32:10:32:11 | s4 | IR only |
| D.cpp:9:21:9:24 | elem | AST only |
| D.cpp:11:29:11:32 | elem | AST only |
| D.cpp:16:21:16:23 | box | AST only |
| D.cpp:18:29:18:31 | box | AST only |
| D.cpp:29:15:29:41 | new | IR only |
| D.cpp:29:15:29:41 | new | IR only |
| D.cpp:29:24:29:40 | 0 | IR only |
| D.cpp:29:24:29:40 | new | IR only |
| D.cpp:29:24:29:40 | new | IR only |
| D.cpp:29:33:29:39 | 0 | IR only |
| D.cpp:30:13:30:16 | elem | AST only |
| D.cpp:36:15:36:41 | new | IR only |
| D.cpp:36:15:36:41 | new | IR only |
| D.cpp:36:24:36:40 | 0 | IR only |
| D.cpp:36:24:36:40 | new | IR only |
| D.cpp:36:24:36:40 | new | IR only |
| D.cpp:36:33:36:39 | 0 | IR only |
| D.cpp:43:15:43:41 | new | IR only |
| D.cpp:43:15:43:41 | new | IR only |
| D.cpp:43:24:43:40 | 0 | IR only |
| D.cpp:43:24:43:40 | new | IR only |
| D.cpp:43:24:43:40 | new | IR only |
| D.cpp:43:33:43:39 | 0 | IR only |
| D.cpp:44:19:44:22 | elem | AST only |
| D.cpp:50:15:50:41 | new | IR only |
| D.cpp:50:15:50:41 | new | IR only |
| D.cpp:50:24:50:40 | 0 | IR only |
| D.cpp:50:24:50:40 | new | IR only |
| D.cpp:50:24:50:40 | new | IR only |
| D.cpp:50:33:50:39 | 0 | IR only |
| D.cpp:57:5:57:12 | boxfield | AST only |
| D.cpp:57:16:57:42 | new | IR only |
| D.cpp:57:16:57:42 | new | IR only |
| D.cpp:57:25:57:41 | 0 | IR only |
| D.cpp:57:25:57:41 | new | IR only |
| D.cpp:57:25:57:41 | new | IR only |
| D.cpp:57:34:57:40 | 0 | IR only |
| D.cpp:58:20:58:23 | elem | AST only |
| aliasing.cpp:9:6:9:7 | m1 | AST only |
| aliasing.cpp:13:5:13:6 | m1 | AST only |
@@ -100,13 +100,13 @@
| aliasing.cpp:98:5:98:6 | m1 | AST only |
| aliasing.cpp:106:3:106:5 | * ... | AST only |
| arrays.cpp:6:3:6:8 | access to array | AST only |
| arrays.cpp:7:3:7:6 | access to array | IR only |
| arrays.cpp:8:3:8:6 | access to array | IR only |
| arrays.cpp:9:3:9:6 | * ... | IR only |
| arrays.cpp:10:3:10:6 | * ... | IR only |
| arrays.cpp:7:8:7:13 | access to array | IR only |
| arrays.cpp:8:8:8:13 | access to array | IR only |
| arrays.cpp:9:8:9:11 | * ... | IR only |
| arrays.cpp:10:8:10:15 | * ... | IR only |
| arrays.cpp:15:3:15:10 | * ... | AST only |
| arrays.cpp:16:3:16:6 | access to array | IR only |
| arrays.cpp:17:3:17:6 | access to array | IR only |
| arrays.cpp:16:8:16:13 | access to array | IR only |
| arrays.cpp:17:8:17:13 | access to array | IR only |
| arrays.cpp:36:19:36:22 | data | AST only |
| arrays.cpp:42:22:42:25 | data | AST only |
| arrays.cpp:48:22:48:25 | data | AST only |

View File

@@ -12,7 +12,7 @@ struct Outer {
};
void absink(struct AB *ab) {
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast=40:20 MISSING: ir
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20
sink(ab->b); // no flow
}
@@ -30,7 +30,7 @@ int struct_init(void) {
sink(outer.nestedAB.a); //$ ast,ir
sink(outer.nestedAB.b); // no flow
sink(outer.pointerAB->a); //$ ast MISSING: ir
sink(outer.pointerAB->a); //$ ast,ir
sink(outer.pointerAB->b); // no flow
absink(&outer.nestedAB);

View File

@@ -21,9 +21,9 @@ void test_unique_ptr_struct() {
std::unique_ptr<A> p1(new A{source(), 0});
std::unique_ptr<A> p2 = std::make_unique<A>(source(), 0);
sink(p1->x); // $ ir MISSING: ast
sink(p1->x); // $ MISSING: ast,ir
sink(p1->y);
sink(p2->x); // $ ir=22:46 MISSING: ast
sink(p2->x); // $ MISSING: ast,ir=22:46
sink(p2->y);
}

View File

@@ -126,15 +126,15 @@ void pointer_test() {
*p2 = source();
sink(*p1); // $ ast MISSING: ir
sink(*p1); // $ ast,ir
sink(*p2); // $ ast,ir
sink(*p3);
p3 = &t1;
sink(*p3); // $ ast MISSING: ir
sink(*p3); // $ ast,ir
*p3 = 0;
sink(*p3); // $ SPURIOUS: ast
sink(*p3); // $ SPURIOUS: ast,ir
}
// --- return values ---

View File

@@ -1,10 +1,15 @@
private import cpp
/**
* Holds if the specified location is in standard headers.
*/
predicate locationIsInStandardHeaders(Location loc) {
loc.getFile().getAbsolutePath().regexpMatch(".*/include/[^/]+")
}
/**
* Holds if the AST or IR for the specified function should be printed in the test output.
*
* This predicate excludes functions defined in standard headers.
*/
predicate shouldDumpFunction(Function func) {
not func.getLocation().getFile().getAbsolutePath().regexpMatch(".*/include/[^/]+")
}
predicate shouldDumpFunction(Function func) { not locationIsInStandardHeaders(func.getLocation()) }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
private import cpp
private import semmle.code.cpp.ir.IR
private import PrintConfig
from Operand a
where not locationIsInStandardHeaders(a.getLocation())
select a, a.getDumpString()

View File

@@ -1474,7 +1474,7 @@ reverseRead
argHasPostUpdate
postWithInFlow
| FunctionTryStmt.cpp:2:3:2:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| VacuousDestructorCall.cpp:10:3:10:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| VacuousDestructorCall.cpp:10:22:10:22 | i [post update] | PostUpdateNode should not be the target of local flow. |
| abortingfunctions.cpp:49:5:49:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1497,7 +1497,7 @@ postWithInFlow
| bad_asts.cpp:10:7:10:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:15:10:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:16:7:16:23 | s [post update] | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:27:11:27:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| break_labels.c:3:9:3:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| break_labels.c:5:9:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1520,35 +1520,35 @@ postWithInFlow
| builtin.c:22:3:22:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:3:34:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:10:34:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:22:34:31 | (volatile void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:34:23:34:31 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:39:3:39:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:39:10:39:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:39:37:39:45 | carry_out [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:43:3:43:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:43:41:43:49 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:45:3:45:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:48:2:48:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:51:3:51:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:51:10:51:27 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:51:30:51:38 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:54:3:54:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:54:10:54:26 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:54:29:54:38 | atomic_int [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.c:56:3:56:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:5:5:5:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:10:10:10:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:10:14:10:22 | i [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:10:24:10:24 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:14:11:14:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:15:5:15:29 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:15:32:15:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
| builtin.cpp:15:33:15:35 | ptr [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1559,18 +1559,18 @@ postWithInFlow
| condition_decls.cpp:3:13:3:22 | Call [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:3:13:3:22 | new [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:9:5:9:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:16:6:16:20 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:16:6:16:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:16:19:16:20 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:26:10:26:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:26:10:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:26:23:26:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:41:9:41:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:41:9:41:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:41:22:41:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:16:48:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:16:48:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:22:48:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:27:48:31 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:27:48:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:34:48:36 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:39:48:53 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:39:48:53 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:48:52:48:53 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:6:13:6:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:6:13:6:15 | val [post update] | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:10:9:10:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1594,8 +1594,8 @@ postWithInFlow
| conditional_destructors.cpp:42:18:42:22 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:42:18:42:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| constmemberaccess.cpp:9:2:9:2 | i [post update] | PostUpdateNode should not be the target of local flow. |
| constructorinitializer.cpp:8:4:8:4 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| constructorinitializer.cpp:8:4:8:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| constructorinitializer.cpp:8:6:8:18 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1650,13 +1650,13 @@ postWithInFlow
| cpp17.cpp:15:5:15:45 | Call [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:5:19:8 | 1 [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:5:19:8 | 2 [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:5:19:8 | p [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:10:19:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:13:19:13 | 1 [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:13:19:13 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:13:19:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:16:19:16 | 2 [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:16:19:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| cpp17.cpp:19:16:19:16 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| defdestructordeleteexpr.cpp:4:5:4:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -1982,20 +1982,20 @@ postWithInFlow
| ir.cpp:579:10:579:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:585:5:585:18 | string [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:585:32:585:39 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:591:11:591:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:592:5:592:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:593:5:593:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:594:5:594:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:616:12:616:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:616:12:616:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:617:12:617:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:617:12:617:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:617:15:617:22 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:618:12:618:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:619:12:619:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:619:12:619:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:619:16:619:30 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:631:9:631:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:635:9:635:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:639:9:639:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2011,11 +2011,11 @@ postWithInFlow
| ir.cpp:649:9:649:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:653:9:653:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:653:15:653:36 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:654:11:654:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:654:11:654:14 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:654:17:654:38 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:655:9:655:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2042,7 +2042,7 @@ postWithInFlow
| ir.cpp:716:5:716:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:716:12:716:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:721:3:721:54 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:721:10:721:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:721:41:721:47 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:721:41:721:47 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:726:9:726:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:728:7:728:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2110,13 +2110,13 @@ postWithInFlow
| ir.cpp:805:11:805:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:806:12:806:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:808:5:808:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:5:809:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:7:809:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:7:809:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:5:810:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:7:810:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:7:810:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:811:3:811:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2124,20 +2124,20 @@ postWithInFlow
| ir.cpp:813:3:813:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:814:3:814:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:816:5:816:5 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:817:5:817:5 | m [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:818:3:818:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:819:3:819:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:820:3:820:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:822:5:822:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:5:823:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:7:823:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:7:823:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:5:824:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:7:824:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:7:824:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:825:3:825:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2145,9 +2145,9 @@ postWithInFlow
| ir.cpp:827:3:827:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:828:3:828:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:830:5:830:5 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:831:5:831:5 | d [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:832:3:832:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:833:3:833:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:834:3:834:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2170,8 +2170,8 @@ postWithInFlow
| ir.cpp:861:23:861:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:863:9:863:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:864:15:864:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:867:1:867:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:867:1:867:14 | this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:868:3:868:12 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:873:15:873:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:874:3:874:3 | p [post update] | PostUpdateNode should not be the target of local flow. |
| ir.cpp:875:3:875:3 | p [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2293,23 +2293,23 @@ postWithInFlow
| misc.c:229:7:229:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| misc.c:230:2:230:3 | p1 [post update] | PostUpdateNode should not be the target of local flow. |
| misc.c:231:2:231:40 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:3:6:8 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:3:6:8 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:19:6:19 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:19:6:19 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:22:6:22 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
| modeled-functions.cpp:6:22:6:22 | (unsigned long *)... [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:13:8:13:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:14:8:14:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:28:3:28:8 | result [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:28:12:28:16 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:28:18:28:23 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
| ms_assume.cpp:34:1:34:1 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:11:7:11:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:11:7:11:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:11:12:11:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:28:7:28:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:28:7:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:28:12:28:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:48:5:48:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:48:5:48:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| ms_try_mix.cpp:48:10:48:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| newexpr.cpp:8:2:8:20 | Call [post update] | PostUpdateNode should not be the target of local flow. |
| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. |
| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2321,21 +2321,21 @@ postWithInFlow
| ops.cpp:26:31:26:53 | Call [post update] | PostUpdateNode should not be the target of local flow. |
| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. |
| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:8:5:8:10 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:8:12:8:21 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:8:12:8:21 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:25:5:25:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:25:5:25:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:27:8:27:13 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
| parameterinitializer.cpp:30:5:30:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:23:10:23:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:26:5:26:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:27:5:27:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:27:16:27:20 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
| pointer_to_member.cpp:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| pruning.c:69:9:69:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| pruning.c:78:9:78:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2585,9 +2585,9 @@ postWithInFlow
| static_init_templates.cpp:3:2:3:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:3:2:3:4 | ref [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:18:7:18:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:20:2:20:10 | a [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:20:12:20:12 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:21:2:21:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:21:2:21:4 | val [post update] | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:22:2:22:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2629,8 +2629,8 @@ postWithInFlow
| staticlocals.cpp:26:19:26:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| stmt_expr.cpp:13:16:13:16 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| stmt_expr.cpp:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| stmt_expr.cpp:13:18:13:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
| stmt_expr.cpp:27:5:27:7 | ptr [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:4:16:4:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:5:14:5:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
@@ -2644,9 +2644,9 @@ postWithInFlow
| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:19:3:19:11 | xs [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:19:13:19:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. |
| stream_it.cpp:20:3:20:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| subscriptexpr.c:4:2:4:2 | i [post update] | PostUpdateNode should not be the target of local flow. |
| switchbody.c:5:11:5:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -136,7 +136,7 @@ useNotDominatedByDefinition
| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
| static_init_templates.cpp:15:1:15:18 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | static_init_templates.cpp:15:1:15:18 | void MyClass::MyClass() | void MyClass::MyClass() |
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
| try_catch.cpp:21:9:21:9 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) |
switchInstructionWithoutDefaultEdge
notMarkedAsConflated

View File

@@ -12,17 +12,17 @@ edges
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query indirection |
| search.c:51:21:51:26 | call to getenv | search.c:55:5:55:15 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:55:5:55:15 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection |
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection |
| search.c:51:21:51:26 | call to getenv | search.c:57:5:57:15 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:57:5:57:15 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection |
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection |
| search.c:55:5:55:15 | raw_query | search.c:14:24:14:28 | query |
| search.c:55:17:55:25 | raw_query | search.c:14:24:14:28 | query |
| search.c:55:17:55:25 | raw_query indirection | search.c:14:24:14:28 | *query |
| search.c:57:5:57:15 | raw_query | search.c:22:24:22:28 | query |
| search.c:57:17:57:25 | raw_query | search.c:22:24:22:28 | query |
| search.c:57:17:57:25 | raw_query indirection | search.c:22:24:22:28 | *query |
subpaths
nodes
@@ -44,9 +44,9 @@ nodes
| search.c:23:39:23:43 | query indirection | semmle.label | query indirection |
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
| search.c:55:5:55:15 | raw_query | semmle.label | raw_query |
| search.c:55:17:55:25 | raw_query | semmle.label | raw_query |
| search.c:55:17:55:25 | raw_query indirection | semmle.label | raw_query indirection |
| search.c:57:5:57:15 | raw_query | semmle.label | raw_query |
| search.c:57:17:57:25 | raw_query | semmle.label | raw_query |
| search.c:57:17:57:25 | raw_query indirection | semmle.label | raw_query indirection |
#select
| search.c:17:8:17:12 | query | search.c:51:21:51:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |

View File

@@ -6,11 +6,11 @@ edges
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data indirection |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
| test.cpp:73:17:73:22 | data | test.cpp:37:73:37:76 | data |
| test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data |
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | *data |
subpaths
nodes
@@ -25,7 +25,7 @@ nodes
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
| test.cpp:73:17:73:22 | data | semmle.label | data |
| test.cpp:73:24:73:27 | data | semmle.label | data |
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
#select
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA | test.cpp:64:30:64:35 | call to getenv | call to getenv |

View File

@@ -11,24 +11,50 @@ edges
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command indirection |
| test.cpp:42:7:42:16 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:42:18:42:23 | call to getenv | test.cpp:42:7:42:16 | call to getenv |
| test.cpp:42:18:42:23 | call to getenv | test.cpp:42:18:42:34 | call to getenv |
| test.cpp:42:18:42:23 | call to getenv | test.cpp:42:18:42:34 | call to getenv indirection |
| test.cpp:42:18:42:34 | (const char *)... | test.cpp:42:7:42:16 | call to getenv |
| test.cpp:42:18:42:34 | (const char *)... | test.cpp:42:18:42:34 | call to getenv |
| test.cpp:42:18:42:34 | (const char *)... | test.cpp:42:18:42:34 | call to getenv indirection |
| test.cpp:42:18:42:34 | call to getenv | test.cpp:24:30:24:36 | command |
| test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:24:30:24:36 | *command |
| test.cpp:43:7:43:16 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:43:18:43:23 | call to getenv | test.cpp:43:7:43:16 | call to getenv |
| test.cpp:43:18:43:23 | call to getenv | test.cpp:43:18:43:34 | call to getenv |
| test.cpp:43:18:43:23 | call to getenv | test.cpp:43:18:43:34 | call to getenv indirection |
| test.cpp:43:18:43:34 | (const char *)... | test.cpp:43:7:43:16 | call to getenv |
| test.cpp:43:18:43:34 | (const char *)... | test.cpp:43:18:43:34 | call to getenv |
| test.cpp:43:18:43:34 | (const char *)... | test.cpp:43:18:43:34 | call to getenv indirection |
| test.cpp:43:18:43:34 | call to getenv | test.cpp:29:30:29:36 | command |
| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | *command |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | (const char *)... |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer indirection |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | (const char *)... |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data indirection |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (const char *)... |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (reference dereference) |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref indirection |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | (const char *)... |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | (const char *)... |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | (const char *)... |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (const char *)... |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | (const char *)... |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | (const char *)... |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer indirection |
@@ -63,13 +89,13 @@ nodes
| test.cpp:31:10:31:16 | command | semmle.label | command |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
| test.cpp:42:7:42:16 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:42:18:42:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:42:18:42:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:43:7:43:16 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:43:18:43:34 | call to getenv | semmle.label | call to getenv |
| test.cpp:43:18:43:34 | call to getenv indirection | semmle.label | call to getenv indirection |
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
@@ -78,6 +104,29 @@ nodes
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data | semmle.label | data |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... |
@@ -103,6 +152,9 @@ nodes
| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:42:18:42:23 | call to getenv | call to getenv |
| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:43:18:43:23 | call to getenv | call to getenv |
| test.cpp:62:10:62:15 | buffer | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:63:10:63:13 | data | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:64:10:64:16 | dataref | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:65:10:65:14 | data2 | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | The value of this argument may come from $@ and is being passed to system | test.cpp:56:12:56:17 | buffer | buffer |
| test.cpp:78:10:78:15 | buffer | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | The value of this argument may come from $@ and is being passed to system | test.cpp:76:12:76:17 | buffer | buffer |
| test.cpp:99:15:99:20 | buffer | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary | test.cpp:98:17:98:22 | buffer | buffer |
| test.cpp:107:15:107:20 | buffer | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary | test.cpp:106:17:106:22 | buffer | buffer |

View File

@@ -61,8 +61,8 @@ void testReferencePointer1()
system(buffer); // BAD
system(data); // BAD
system(dataref); // BAD [NOT DETECTED]
system(data2); // BAD [NOT DETECTED]
system(dataref); // BAD
system(data2); // BAD
}
}

View File

@@ -108,10 +108,45 @@ edges
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 |
| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:9:25:9:31 | *correct |
| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:117:15:117:16 | printWrapper output argument |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 indirection |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 |
@@ -317,6 +352,8 @@ nodes
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |

View File

@@ -23,9 +23,9 @@ edges
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store |
| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection |
| globalVars.c:24:2:24:9 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:2:24:9 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:2:24:9 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection |
| globalVars.c:24:11:24:14 | argv indirection | globalVars.c:11:22:11:25 | *argv |
@@ -37,13 +37,13 @@ edges
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection |
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:2:35:9 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str |
| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:30:15:30:18 | printWrapper output argument |
| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:2:35:9 | copy |
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:2:35:9 | copy |
| globalVars.c:35:2:35:9 | copy | globalVars.c:15:21:15:23 | val |
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:2:35:9 | copy |
| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:11:35:14 | copy |
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 indirection |
@@ -85,7 +85,7 @@ nodes
| globalVars.c:16:2:16:12 | Store | semmle.label | Store |
| globalVars.c:19:25:19:27 | *str | semmle.label | *str |
| globalVars.c:19:25:19:27 | ReturnIndirection | semmle.label | ReturnIndirection |
| globalVars.c:24:2:24:9 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection |
@@ -103,7 +103,7 @@ nodes
| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:33:15:33:18 | copy | semmle.label | copy |
| globalVars.c:35:2:35:9 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |

View File

@@ -13,17 +13,15 @@ edges
| test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r |
| test.cpp:6:5:6:12 | ReturnValue | test.cpp:24:11:24:18 | call to get_rand |
| test.cpp:8:9:8:12 | call to rand | test.cpp:6:5:6:12 | ReturnValue |
| test.cpp:13:2:13:6 | * ... [post update] | test.cpp:30:3:30:11 | & ... [post update] |
| test.cpp:13:3:13:6 | dest [post update] | test.cpp:30:3:30:11 | & ... [post update] |
| test.cpp:13:2:13:6 | * ... [post update] | test.cpp:30:13:30:14 | & ... [post update] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:6 | * ... [post update] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:3:13:6 | dest [post update] |
| test.cpp:18:2:18:5 | (reference dereference) [post update] | test.cpp:36:3:36:11 | r [post update] |
| test.cpp:18:2:18:5 | dest [post update] | test.cpp:36:3:36:11 | r [post update] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:30:13:30:14 | & ... [post update] |
| test.cpp:18:2:18:5 | (reference dereference) [post update] | test.cpp:36:13:36:13 | r [post update] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:5 | (reference dereference) [post update] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:5 | dest [post update] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:36:13:36:13 | r [post update] |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:30:3:30:11 | & ... [post update] | test.cpp:31:7:31:7 | r |
| test.cpp:36:3:36:11 | r [post update] | test.cpp:37:7:37:7 | r |
| test.cpp:30:13:30:14 | & ... [post update] | test.cpp:31:7:31:7 | r |
| test.cpp:36:13:36:13 | r [post update] | test.cpp:37:7:37:7 | r |
| test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x |
| test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x |
| test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y |
@@ -64,16 +62,14 @@ nodes
| test.cpp:6:5:6:12 | ReturnValue | semmle.label | ReturnValue |
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:13:2:13:6 | * ... [post update] | semmle.label | * ... [post update] |
| test.cpp:13:3:13:6 | dest [post update] | semmle.label | dest [post update] |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:18:2:18:5 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] |
| test.cpp:18:2:18:5 | dest [post update] | semmle.label | dest [post update] |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand |
| test.cpp:25:7:25:7 | r | semmle.label | r |
| test.cpp:30:3:30:11 | & ... [post update] | semmle.label | & ... [post update] |
| test.cpp:30:13:30:14 | & ... [post update] | semmle.label | & ... [post update] |
| test.cpp:31:7:31:7 | r | semmle.label | r |
| test.cpp:36:3:36:11 | r [post update] | semmle.label | r [post update] |
| test.cpp:36:13:36:13 | r [post update] | semmle.label | r [post update] |
| test.cpp:37:7:37:7 | r | semmle.label | r |
| test.cpp:86:10:86:13 | call to rand | semmle.label | call to rand |
| test.cpp:90:10:90:10 | x | semmle.label | x |

View File

@@ -50,31 +50,31 @@ edges
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | (size_t)... |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:2:245:9 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:2:247:8 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size |
| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:10:247:19 | local_size |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | (size_t)... |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:245:2:245:9 | local_size |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:247:2:247:8 | local_size |
| test.cpp:245:2:245:9 | local_size | test.cpp:224:23:224:23 | s |
| test.cpp:247:2:247:8 | local_size | test.cpp:230:21:230:21 | s |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:289:8:289:15 | size [post update] |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:305:9:305:16 | size [post update] |
| test.cpp:251:2:251:9 | out_size [post update] | test.cpp:289:8:289:15 | size [post update] |
| test.cpp:251:2:251:9 | out_size [post update] | test.cpp:305:9:305:16 | size [post update] |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:245:11:245:20 | local_size |
| test.cpp:237:24:237:37 | (const char *)... | test.cpp:247:10:247:19 | local_size |
| test.cpp:245:11:245:20 | local_size | test.cpp:224:23:224:23 | s |
| test.cpp:247:10:247:19 | local_size | test.cpp:230:21:230:21 | s |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:289:17:289:20 | size [post update] |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:305:18:305:21 | size [post update] |
| test.cpp:251:18:251:23 | call to getenv | test.cpp:251:2:251:9 | (reference dereference) [post update] |
| test.cpp:251:18:251:23 | call to getenv | test.cpp:251:2:251:9 | out_size [post update] |
| test.cpp:251:18:251:23 | call to getenv | test.cpp:289:17:289:20 | size [post update] |
| test.cpp:251:18:251:23 | call to getenv | test.cpp:305:18:305:21 | size [post update] |
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:251:2:251:9 | (reference dereference) [post update] |
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:251:2:251:9 | out_size [post update] |
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:289:17:289:20 | size [post update] |
| test.cpp:251:18:251:31 | (const char *)... | test.cpp:305:18:305:21 | size [post update] |
| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
| test.cpp:289:8:289:15 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
| test.cpp:289:8:289:15 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
| test.cpp:305:9:305:16 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
| test.cpp:305:9:305:16 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
| test.cpp:289:17:289:20 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
| test.cpp:289:17:289:20 | size [post update] | test.cpp:291:11:291:28 | ... * ... |
| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... |
subpaths
nodes
| test.cpp:40:21:40:24 | argv | semmle.label | argv |
@@ -137,8 +137,8 @@ nodes
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
| test.cpp:245:2:245:9 | local_size | semmle.label | local_size |
| test.cpp:247:2:247:8 | local_size | semmle.label | local_size |
| test.cpp:245:11:245:20 | local_size | semmle.label | local_size |
| test.cpp:247:10:247:19 | local_size | semmle.label | local_size |
| test.cpp:251:2:251:9 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] |
| test.cpp:251:2:251:9 | out_size [post update] | semmle.label | out_size [post update] |
| test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv |
@@ -148,11 +148,11 @@ nodes
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:289:8:289:15 | size [post update] | semmle.label | size [post update] |
| test.cpp:289:17:289:20 | size [post update] | semmle.label | size [post update] |
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:305:9:305:16 | size [post update] | semmle.label | size [post update] |
| test.cpp:305:18:305:21 | size [post update] | semmle.label | size [post update] |
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |

View File

@@ -1,9 +1,9 @@
edges
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
| test2.cpp:25:22:25:23 | & ... | test2.cpp:27:2:27:11 | v |
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:2:27:11 | v |
| test2.cpp:27:2:27:11 | v | test2.cpp:12:21:12:21 | v |
| test2.cpp:25:22:25:23 | & ... | test2.cpp:27:13:27:13 | v |
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v |
| test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v |
| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:17:6:17:18 | call to getTaintedInt |
| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:18:6:18:18 | call to getTaintedInt |
@@ -31,7 +31,7 @@ nodes
| test2.cpp:14:11:14:11 | v | semmle.label | v |
| test2.cpp:25:22:25:23 | & ... | semmle.label | & ... |
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
| test2.cpp:27:2:27:11 | v | semmle.label | v |
| test2.cpp:27:13:27:13 | v | semmle.label | v |
| test5.cpp:5:5:5:17 | ReturnValue | semmle.label | ReturnValue |
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |

View File

@@ -645,17 +645,18 @@ module Consistency {
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(_, def0, bb, i)))
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(_, _, bb, i)
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _)
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
}

View File

@@ -25,7 +25,7 @@ module ControlFlow {
* Only nodes that can be reached from the callable entry point are included in
* the CFG.
*/
class Node extends TNode {
class Node extends TCfgNode {
/** Gets a textual representation of this control flow node. */
string toString() { none() }

View File

@@ -788,7 +788,7 @@ private module Cached {
* The control flow graph is pruned for unreachable nodes.
*/
cached
newtype TNode =
newtype TCfgNode =
TEntryNode(CfgScope scope) { succEntrySplits(scope, _, _, _) } or
TAnnotatedExitNode(CfgScope scope, boolean normal) {
exists(Reachability::SameSplitsBlock b, SuccessorType t | b.isReachable(_) |
@@ -807,7 +807,7 @@ private module Cached {
/** Gets a successor node of a given flow type, if any. */
cached
TNode getASuccessor(TNode pred, SuccessorType t) {
TCfgNode getASuccessor(TCfgNode pred, SuccessorType t) {
// Callable entry node -> callable body
exists(ControlFlowElement succElement, Splits succSplits, CfgScope scope |
result = TElementNode(succElement, succSplits) and

View File

@@ -645,17 +645,18 @@ module Consistency {
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(_, def0, bb, i)))
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(_, _, bb, i)
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _)
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
}

View File

@@ -645,17 +645,18 @@ module Consistency {
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(_, def0, bb, i)))
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(_, _, bb, i)
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _)
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
}

View File

@@ -645,17 +645,18 @@ module Consistency {
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(_, def0, bb, i)))
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(_, _, bb, i)
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _)
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
}

View File

@@ -14,6 +14,7 @@ class Element extends @dotnet_element {
string toString() { none() }
/** Gets the location of this element. */
pragma[nomagic]
Location getLocation() { none() }
/**

View File

@@ -20,6 +20,14 @@ private import internal.OperandInternal
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
* opposed to testing `not loc isntanceof UnknownLocation`
*/
private class KnownLocation extends Language::Location {
KnownLocation() { not this instanceof Language::UnknownLocation }
}
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
* By default this is where the operand is used, but some subclasses may override this
* using `getAnyDef()` if it makes more sense.
*/
final Language::Location getLocation() { result = this.getUse().getLocation() }
Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
final override string toString() { result = tag.toString() }
// most `RegisterOperands` have a more meaningful location at the definition
// the only exception are specific cases of `ThisArgumentOperand`
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
}
/**
* An operand representing the implicit 'this' argument to a member function
* An operand representing the implicit `this` argument to a member function
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
// in most cases the def location makes more sense, but in some corner cases it
// has an unknown location: in those cases we fall back to the use location
override Language::Location getLocation() {
if this.getAnyDef().getLocation() instanceof KnownLocation
then result = this.getAnyDef().getLocation()
else result = this.getUse().getLocation()
}
}
/**

View File

@@ -20,6 +20,14 @@ private import internal.OperandInternal
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
* opposed to testing `not loc isntanceof UnknownLocation`
*/
private class KnownLocation extends Language::Location {
KnownLocation() { not this instanceof Language::UnknownLocation }
}
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
/**
* Gets the location of the source code for this operand.
* By default this is where the operand is used, but some subclasses may override this
* using `getAnyDef()` if it makes more sense.
*/
final Language::Location getLocation() { result = this.getUse().getLocation() }
Language::Location getLocation() { result = this.getUse().getLocation() }
/**
* Gets the function that contains this operand.
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
final override string toString() { result = tag.toString() }
// most `RegisterOperands` have a more meaningful location at the definition
// the only exception are specific cases of `ThisArgumentOperand`
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
}
/**
* An operand representing the implicit 'this' argument to a member function
* An operand representing the implicit `this` argument to a member function
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
// in most cases the def location makes more sense, but in some corner cases it
// has an unknown location: in those cases we fall back to the use location
override Language::Location getLocation() {
if this.getAnyDef().getLocation() instanceof KnownLocation
then result = this.getAnyDef().getLocation()
else result = this.getUse().getLocation()
}
}
/**

View File

@@ -219,7 +219,7 @@ alerts generated by the custom queries.
From CodeQL CLI 2.7.1 onwards, you can include markdown-rendered query help in SARIF files
by providing the ``--sarif-add-query-help`` option when running
``codeql database analyze``.
For more information, see `Configuring CodeQL CLI in your CI system <https://docs.github.com/en/code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-cli-in-your-ci-system#analyzing-a-codeql-database>`
For more information, see `Configuring CodeQL CLI in your CI system <https://docs.github.com/en/code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-cli-in-your-ci-system#analyzing-a-codeql-database>`__
in the GitHub documentation.
You can write query help for custom queries directly in a markdown file and save it alongside the

View File

@@ -20,7 +20,7 @@
Java,"Java 7 to 16 [4]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [5]_",``.java``
JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9",Not applicable,``.py``
Ruby [7]_,"up to 3.02",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
TypeScript [8]_,"2.6-4.4",Standard TypeScript compiler,"``.ts``, ``.tsx``"

View File

@@ -39,6 +39,7 @@ Query file metadata contains important information that defines the identifier a
* @tags maintainability
* external/cwe/cwe-563
* @precision very-high
* @security-severity 6.1
*/
```

View File

@@ -0,0 +1,17 @@
/**
* @name Diagnostics for framework coverage
* @description Expose diagnostics for the number of API endpoints covered by CSV models.
* @kind diagnostic
* @id java/diagnostics/framework-coverage
*/
import java
import semmle.code.java.dataflow.ExternalFlow
from string packageAndType, int rows
where
exists(string package, string type |
packageAndType = package + ";" + type and
rows = strictsum(int n, string kind | modelCoverage(package, _, kind, type, n) | n)
)
select packageAndType, rows

View File

@@ -27,6 +27,11 @@ If this is not possible you should disable the parsing of external general entit
This improves security but the code will still be at risk of denial of service and server side request forgery attacks.
Protection against denial of service attacks may also be implemented by setting entity expansion limits, which is done
by default in recent JDK and JRE implementations.
Because there are many different ways to disable external entity retrieval with varying support between different providers,
in this query we choose to specifically check for the <a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java">OWASP recommended way</a>
to disable external entity retrieval for a particular parser. There may be other ways of making a particular parser safe
which deviate from these guidelines, in which case this query will continue to flag the parser as potentially dangerous.
</p>
</recommendation>

View File

@@ -0,0 +1,72 @@
/**
* @name Uncontrolled thread resource consumption from local input source
* @description Using user input directly to control a thread's sleep time could lead to
* performance problems or even resource exhaustion.
* @kind path-problem
* @id java/thread-resource-abuse
* @problem.severity recommendation
* @tags security
* external/cwe/cwe-400
*/
import java
import ThreadResourceAbuse
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
/** The `getInitParameter` method of servlet or JSF. */
class GetInitParameter extends Method {
GetInitParameter() {
(
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName(["javax.servlet", "jakarta.servlet"],
["FilterConfig", "Registration", "ServletConfig", "ServletContext"]) or
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName(["javax.faces.context", "jakarta.faces.context"], "ExternalContext")
) and
this.getName() = "getInitParameter"
}
}
/** An access to the `getInitParameter` method. */
class GetInitParameterAccess extends MethodAccess {
GetInitParameterAccess() { this.getMethod() instanceof GetInitParameter }
}
/* Init parameter input of a Java EE web application. */
class InitParameterInput extends LocalUserInput {
InitParameterInput() { this.asExpr() instanceof GetInitParameterAccess }
}
/** Taint configuration of uncontrolled thread resource consumption from local user input. */
class ThreadResourceAbuse extends TaintTracking::Configuration {
ThreadResourceAbuse() { this = "ThreadResourceAbuse" }
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
override predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
any(AdditionalValueStep r).step(pred, succ)
}
override predicate isSanitizer(DataFlow::Node node) {
exists(
MethodAccess ma // Math.min(sleepTime, MAX_INTERVAL)
|
ma.getMethod().hasQualifiedName("java.lang", "Math", "min") and
node.asExpr() = ma.getAnArgument()
)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof LessThanSanitizer // if (sleepTime > 0 && sleepTime < 5000) { ... }
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ThreadResourceAbuse conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Possible uncontrolled resource consumption due to $@.",
source.getNode(), "local user-provided value"

View File

@@ -0,0 +1,11 @@
class SleepTest {
public void test(int userSuppliedWaitTime) throws Exception {
// BAD: no boundary check on wait time
Thread.sleep(userSuppliedWaitTime);
// GOOD: enforce an upper limit on wait time
if (userSuppliedWaitTime > 0 && userSuppliedWaitTime < 5000) {
Thread.sleep(userSuppliedWaitTime);
}
}
}

View File

@@ -0,0 +1,48 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The <code>Thread.sleep</code> method is used to pause the execution of current thread for
specified time. When the sleep time is user-controlled, especially in the web application context,
it can be abused to cause all of a server's threads to sleep, leading to denial of service.</p>
</overview>
<recommendation>
<p>To guard against this attack, consider specifying an upper range of allowed sleep time or adopting
the producer/consumer design pattern with <code>Object.wait</code> method to avoid performance
problems or even resource exhaustion. For more information, refer to the concurrency tutorial of Oracle
listed below or <code>java/ql/src/Likely Bugs/Concurrency</code> queries of CodeQL.</p>
</recommendation>
<example>
<p>The following example shows a bad situation and a good situation respectively. In the bad situation,
a thread sleep time comes directly from user input. In the good situation, an upper
range check on the maximum sleep time allowed is enforced.</p>
<sample src="ThreadResourceAbuse.java" />
</example>
<references>
<li>
Snyk:
<a href="https://snyk.io/vuln/SNYK-JAVA-COMGOOGLECODEGWTUPLOAD-569506">Denial of Service (DoS)
in com.googlecode.gwtupload:gwtupload</a>.
</li>
<li>
gwtupload:
<a href="https://github.com/manolo/gwtupload/issues/33">[Fix DOS issue] Updating the
AbstractUploadListener.java file</a>.
</li>
<li>
The blog of a gypsy engineer:
<a href="https://blog.gypsyengineer.com/en/security/cve-2019-17555-dos-via-retry-after-header-in-apache-olingo.html">
CVE-2019-17555: DoS via Retry-After header in Apache Olingo</a>.
</li>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html">The Java Concurrency Tutorials</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,47 @@
/**
* @name Uncontrolled thread resource consumption
* @description Using user input directly to control a thread's sleep time could lead to
* performance problems or even resource exhaustion.
* @kind path-problem
* @id java/thread-resource-abuse
* @problem.severity warning
* @tags security
* external/cwe/cwe-400
*/
import java
import ThreadResourceAbuse
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
/** Taint configuration of uncontrolled thread resource consumption. */
class ThreadResourceAbuse extends TaintTracking::Configuration {
ThreadResourceAbuse() { this = "ThreadResourceAbuse" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof PauseThreadSink }
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
any(AdditionalValueStep r).step(pred, succ)
}
override predicate isSanitizer(DataFlow::Node node) {
exists(
MethodAccess ma // Math.min(sleepTime, MAX_INTERVAL)
|
ma.getMethod().hasQualifiedName("java.lang", "Math", "min") and
node.asExpr() = ma.getAnArgument()
)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof LessThanSanitizer // if (sleepTime > 0 && sleepTime < 5000) { ... }
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, ThreadResourceAbuse conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"Vulnerability of uncontrolled resource consumption due to $@.", source.getNode(),
"user-provided value"

View File

@@ -0,0 +1,78 @@
/** Provides sink models and classes related to pausing thread operations. */
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.dataflow.FlowSteps
/** `java.lang.Math` data model for value comparison in the new CSV format. */
private class MathCompDataModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"java.lang;Math;false;min;;;Argument[0..1];ReturnValue;value",
"java.lang;Math;false;max;;;Argument[0..1];ReturnValue;value"
]
}
}
/** Thread pause data model in the new CSV format. */
private class PauseThreadDataModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"java.lang;Thread;true;sleep;;;Argument[0];thread-pause",
"java.util.concurrent;TimeUnit;true;sleep;;;Argument[0];thread-pause"
]
}
}
/** A sink representing methods pausing a thread. */
class PauseThreadSink extends DataFlow::Node {
PauseThreadSink() { sinkNode(this, "thread-pause") }
}
/** A sanitizer for lessThan check. */
class LessThanSanitizer extends DataFlow::BarrierGuard instanceof ComparisonExpr {
override predicate checks(Expr e, boolean branch) {
e = super.getLesserOperand() and
branch = true
or
e = super.getGreaterOperand() and
branch = false
}
}
/** Value step from the constructor call of a `Runnable` to the instance parameter (this) of `run`. */
private class RunnableStartToRunStep extends AdditionalValueStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ConstructorCall cc, Method m |
m.getDeclaringType() = cc.getConstructedType().getSourceDeclaration() and
cc.getConstructedType().getASupertype*().hasQualifiedName("java.lang", "Runnable") and
m.hasName("run")
|
pred.asExpr() = cc and
succ.(DataFlow::InstanceParameterNode).getEnclosingCallable() = m
)
}
}
/**
* Value step from the constructor call of a `ProgressListener` of Apache File Upload to the
* instance parameter (this) of `update`.
*/
private class ApacheFileUploadProgressUpdateStep extends AdditionalValueStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ConstructorCall cc, Method m |
m.getDeclaringType() = cc.getConstructedType().getSourceDeclaration() and
cc.getConstructedType()
.getASupertype*()
.hasQualifiedName(["org.apache.commons.fileupload", "org.apache.commons.fileupload2"],
"ProgressListener") and
m.hasName("update")
|
pred.asExpr() = cc and
succ.(DataFlow::InstanceParameterNode).getEnclosingCallable() = m
)
}
}

View File

@@ -0,0 +1,23 @@
edges
| ThreadResourceAbuse.java:37:25:37:73 | getInitParameter(...) : String | ThreadResourceAbuse.java:40:28:40:36 | delayTime : Number |
| ThreadResourceAbuse.java:40:4:40:37 | new UncheckedSyncAction(...) [waitTime] : Number | ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number |
| ThreadResourceAbuse.java:40:28:40:36 | delayTime : Number | ThreadResourceAbuse.java:40:4:40:37 | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:40:28:40:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number |
| ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number |
| ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number | ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number |
| ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | waitTime |
nodes
| ThreadResourceAbuse.java:37:25:37:73 | getInitParameter(...) : String | semmle.label | getInitParameter(...) : String |
| ThreadResourceAbuse.java:40:4:40:37 | new UncheckedSyncAction(...) [waitTime] : Number | semmle.label | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:40:28:40:36 | delayTime : Number | semmle.label | delayTime : Number |
| ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | semmle.label | waitTime : Number |
| ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number | semmle.label | this [post update] [waitTime] : Number |
| ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number | semmle.label | waitTime : Number |
| ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number | semmle.label | parameter this [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number | semmle.label | this <.field> [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | waitTime | semmle.label | waitTime |
subpaths
| ThreadResourceAbuse.java:40:28:40:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number | ThreadResourceAbuse.java:40:4:40:37 | new UncheckedSyncAction(...) [waitTime] : Number |
#select
| ThreadResourceAbuse.java:74:18:74:25 | waitTime | ThreadResourceAbuse.java:37:25:37:73 | getInitParameter(...) : String | ThreadResourceAbuse.java:74:18:74:25 | waitTime | Possible uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:37:25:37:73 | getInitParameter(...) | local user-provided value |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql

View File

@@ -0,0 +1,68 @@
edges
| ThreadResourceAbuse.java:18:25:18:57 | getParameter(...) : String | ThreadResourceAbuse.java:21:28:21:36 | delayTime : Number |
| ThreadResourceAbuse.java:21:4:21:37 | new UncheckedSyncAction(...) [waitTime] : Number | ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number |
| ThreadResourceAbuse.java:21:28:21:36 | delayTime : Number | ThreadResourceAbuse.java:21:4:21:37 | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:21:28:21:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number |
| ThreadResourceAbuse.java:29:82:29:114 | getParameter(...) : String | ThreadResourceAbuse.java:30:28:30:36 | delayTime : Number |
| ThreadResourceAbuse.java:30:4:30:37 | new UncheckedSyncAction(...) [waitTime] : Number | ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number |
| ThreadResourceAbuse.java:30:28:30:36 | delayTime : Number | ThreadResourceAbuse.java:30:4:30:37 | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:30:28:30:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number |
| ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number |
| ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number | ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number |
| ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | waitTime |
| ThreadResourceAbuse.java:141:27:141:43 | getValue(...) : String | ThreadResourceAbuse.java:144:34:144:42 | delayTime |
| ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | ThreadResourceAbuse.java:176:17:176:26 | retryAfter |
| ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number |
| ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number | UploadListener.java:28:14:28:19 | parameter this [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | UploadListener.java:15:24:15:44 | sleepMilliseconds : Number |
| UploadListener.java:15:24:15:44 | sleepMilliseconds : Number | UploadListener.java:16:17:16:33 | sleepMilliseconds : Number |
| UploadListener.java:16:17:16:33 | sleepMilliseconds : Number | UploadListener.java:16:3:16:13 | this <.field> [post update] [slowUploads] : Number |
| UploadListener.java:28:14:28:19 | parameter this [slowUploads] : Number | UploadListener.java:29:3:29:11 | this <.field> [slowUploads] : Number |
| UploadListener.java:29:3:29:11 | this <.field> [slowUploads] : Number | UploadListener.java:30:3:30:15 | this <.field> [slowUploads] : Number |
| UploadListener.java:30:3:30:15 | this <.field> [slowUploads] : Number | UploadListener.java:33:7:33:17 | this <.field> [slowUploads] : Number |
| UploadListener.java:30:3:30:15 | this <.field> [slowUploads] : Number | UploadListener.java:35:18:35:28 | this <.field> [slowUploads] : Number |
| UploadListener.java:33:7:33:17 | slowUploads : Number | UploadListener.java:35:18:35:28 | slowUploads |
| UploadListener.java:33:7:33:17 | this <.field> [slowUploads] : Number | UploadListener.java:33:7:33:17 | slowUploads : Number |
| UploadListener.java:35:18:35:28 | this <.field> [slowUploads] : Number | UploadListener.java:35:18:35:28 | slowUploads |
nodes
| ThreadResourceAbuse.java:18:25:18:57 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ThreadResourceAbuse.java:21:4:21:37 | new UncheckedSyncAction(...) [waitTime] : Number | semmle.label | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:21:28:21:36 | delayTime : Number | semmle.label | delayTime : Number |
| ThreadResourceAbuse.java:29:82:29:114 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ThreadResourceAbuse.java:30:4:30:37 | new UncheckedSyncAction(...) [waitTime] : Number | semmle.label | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:30:28:30:36 | delayTime : Number | semmle.label | delayTime : Number |
| ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | semmle.label | waitTime : Number |
| ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number | semmle.label | this [post update] [waitTime] : Number |
| ThreadResourceAbuse.java:67:20:67:27 | waitTime : Number | semmle.label | waitTime : Number |
| ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number | semmle.label | parameter this [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number | semmle.label | this <.field> [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | waitTime | semmle.label | waitTime |
| ThreadResourceAbuse.java:141:27:141:43 | getValue(...) : String | semmle.label | getValue(...) : String |
| ThreadResourceAbuse.java:144:34:144:42 | delayTime | semmle.label | delayTime |
| ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | semmle.label | getHeader(...) : String |
| ThreadResourceAbuse.java:176:17:176:26 | retryAfter | semmle.label | retryAfter |
| ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number | semmle.label | new UploadListener(...) [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | semmle.label | uploadDelay : Number |
| UploadListener.java:15:24:15:44 | sleepMilliseconds : Number | semmle.label | sleepMilliseconds : Number |
| UploadListener.java:16:3:16:13 | this <.field> [post update] [slowUploads] : Number | semmle.label | this <.field> [post update] [slowUploads] : Number |
| UploadListener.java:16:17:16:33 | sleepMilliseconds : Number | semmle.label | sleepMilliseconds : Number |
| UploadListener.java:28:14:28:19 | parameter this [slowUploads] : Number | semmle.label | parameter this [slowUploads] : Number |
| UploadListener.java:29:3:29:11 | this <.field> [slowUploads] : Number | semmle.label | this <.field> [slowUploads] : Number |
| UploadListener.java:30:3:30:15 | this <.field> [slowUploads] : Number | semmle.label | this <.field> [slowUploads] : Number |
| UploadListener.java:33:7:33:17 | slowUploads : Number | semmle.label | slowUploads : Number |
| UploadListener.java:33:7:33:17 | this <.field> [slowUploads] : Number | semmle.label | this <.field> [slowUploads] : Number |
| UploadListener.java:35:18:35:28 | slowUploads | semmle.label | slowUploads |
| UploadListener.java:35:18:35:28 | this <.field> [slowUploads] : Number | semmle.label | this <.field> [slowUploads] : Number |
subpaths
| ThreadResourceAbuse.java:21:28:21:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number | ThreadResourceAbuse.java:21:4:21:37 | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:30:28:30:36 | delayTime : Number | ThreadResourceAbuse.java:66:30:66:41 | waitTime : Number | ThreadResourceAbuse.java:67:4:67:7 | this [post update] [waitTime] : Number | ThreadResourceAbuse.java:30:4:30:37 | new UncheckedSyncAction(...) [waitTime] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | UploadListener.java:15:24:15:44 | sleepMilliseconds : Number | UploadListener.java:16:3:16:13 | this <.field> [post update] [slowUploads] : Number | ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number |
#select
| ThreadResourceAbuse.java:74:18:74:25 | waitTime | ThreadResourceAbuse.java:18:25:18:57 | getParameter(...) : String | ThreadResourceAbuse.java:74:18:74:25 | waitTime | Vulnerability of uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:18:25:18:57 | getParameter(...) | user-provided value |
| ThreadResourceAbuse.java:74:18:74:25 | waitTime | ThreadResourceAbuse.java:29:82:29:114 | getParameter(...) : String | ThreadResourceAbuse.java:74:18:74:25 | waitTime | Vulnerability of uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:29:82:29:114 | getParameter(...) | user-provided value |
| ThreadResourceAbuse.java:144:34:144:42 | delayTime | ThreadResourceAbuse.java:141:27:141:43 | getValue(...) : String | ThreadResourceAbuse.java:144:34:144:42 | delayTime | Vulnerability of uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:141:27:141:43 | getValue(...) | user-provided value |
| ThreadResourceAbuse.java:176:17:176:26 | retryAfter | ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | ThreadResourceAbuse.java:176:17:176:26 | retryAfter | Vulnerability of uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) | user-provided value |
| UploadListener.java:35:18:35:28 | slowUploads | ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | UploadListener.java:35:18:35:28 | slowUploads | Vulnerability of uncontrolled resource consumption due to $@. | ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) | user-provided value |

View File

@@ -0,0 +1,212 @@
package test.cwe400.cwe.examples;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ThreadResourceAbuse extends HttpServlet {
static final int DEFAULT_RETRY_AFTER = 5*1000;
static final int MAX_RETRY_AFTER = 10*1000;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from request parameter without validation
String delayTimeStr = request.getParameter("DelayTime");
try {
int delayTime = Integer.valueOf(delayTimeStr);
new UncheckedSyncAction(delayTime).start();
} catch (NumberFormatException e) {
}
}
protected void doGet2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from request parameter without validation
try {
int delayTime = request.getParameter("nodelay") != null ? 0 : Integer.valueOf(request.getParameter("DelayTime"));
new UncheckedSyncAction(delayTime).start();
} catch (NumberFormatException e) {
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from context init parameter without validation
String delayTimeStr = getServletContext().getInitParameter("DelayTime");
try {
int delayTime = Integer.valueOf(delayTimeStr);
new UncheckedSyncAction(delayTime).start();
} catch (NumberFormatException e) {
}
}
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// GOOD: Get thread pause time from request cookie with validation
Cookie[] cookies = request.getCookies();
for ( int i=0; i<cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("DelayTime")) {
String delayTimeStr = cookie.getValue();
try {
int delayTime = Integer.valueOf(delayTimeStr);
new CheckedSyncAction(delayTime).start();
} catch (NumberFormatException e) {
}
}
}
}
class UncheckedSyncAction extends Thread {
int waitTime;
public UncheckedSyncAction(int waitTime) {
this.waitTime = waitTime;
}
@Override
public void run() {
// BAD: no boundary check on wait time
try {
Thread.sleep(waitTime);
// Do other updates
} catch (InterruptedException e) {
}
}
}
class CheckedSyncAction extends Thread {
int waitTime;
public CheckedSyncAction(int waitTime) {
this.waitTime = waitTime;
}
@Override
public void run() {
// GOOD: enforce an upper limit on wait time
try {
if (waitTime > 0 && waitTime < 5000) {
Thread.sleep(waitTime);
// Do other updates
}
} catch (InterruptedException e) {
}
}
}
class CheckedSyncAction2 extends Thread {
int waitTime;
public CheckedSyncAction2(int waitTime) {
this.waitTime = waitTime;
}
@Override
public void run() {
// GOOD: enforce an upper limit on wait time
try {
if (waitTime >= 5000) {
// No action
} else {
Thread.sleep(waitTime);
}
// Do other updates
} catch (InterruptedException e) {
}
}
}
protected void doPost2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// GOOD: Get thread pause time from init container parameter with validation
String delayTimeStr = getServletContext().getInitParameter("DelayTime");
try {
int delayTime = Integer.valueOf(delayTimeStr);
new CheckedSyncAction2(delayTime).start();
} catch (NumberFormatException e) {
}
}
protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from request cookie without validation
Cookie[] cookies = request.getCookies();
for ( int i=0; i<cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("DelayTime")) {
String delayTimeStr = cookie.getValue();
try {
int delayTime = Integer.valueOf(delayTimeStr);
TimeUnit.MILLISECONDS.sleep(delayTime);
// Do other updates
} catch (NumberFormatException ne) {
} catch (InterruptedException ie) {
}
}
}
}
int parseRetryAfter(String value) {
if (value == null || value.isEmpty()) {
return DEFAULT_RETRY_AFTER;
}
try {
int n = Integer.parseInt(value);
if (n < 0) {
return DEFAULT_RETRY_AFTER;
}
return Math.min(n, MAX_RETRY_AFTER);
} catch (NumberFormatException e) {
return DEFAULT_RETRY_AFTER;
}
}
protected void doHead2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from request header without validation
String header = request.getHeader("Retry-After");
int retryAfter = Integer.parseInt(header);
try {
Thread.sleep(retryAfter);
} catch (InterruptedException ignore) {
// ignore
}
}
protected void doHead3(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// GOOD: Get thread pause time from request header with validation
String header = request.getHeader("Retry-After");
int retryAfter = parseRetryAfter(header);
try {
Thread.sleep(retryAfter);
} catch (InterruptedException ignore) {
// ignore
}
}
private long getContentLength(HttpServletRequest request) {
long size = -1;
try {
size = Long.parseLong(request.getHeader("Content-length"));
} catch (NumberFormatException e) {
}
return size;
}
protected void doHead4(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// BAD: Get thread pause time from request header without validation
try {
String uploadDelayStr = request.getParameter("delay");
int uploadDelay = Integer.parseInt(uploadDelayStr);
UploadListener listener = new UploadListener(uploadDelay, getContentLength(request));
} catch (Exception e) { }
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-400/ThreadResourceAbuse.ql

View File

@@ -0,0 +1,40 @@
package test.cwe400.cwe.examples;
import java.io.Serializable;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload2.ProgressListener;
public class UploadListener implements ProgressListener, Serializable {
protected int slowUploads = 0;
private Long bytesRead = 0L;
private long contentLength = 0L;
public UploadListener(int sleepMilliseconds, long requestSize) {
slowUploads = sleepMilliseconds;
contentLength = requestSize;
}
public long getPercent() {
return contentLength != 0 ? bytesRead * 100 / contentLength : 0;
}
public long getBytesRead() {
return bytesRead;
}
public void update(long done, long total, int item) {
bytesRead = done;
contentLength = total;
// Just a way to slow down the upload process and see the progress bar in fast networks.
if (slowUploads > 0 && done < total) {
try {
Thread.sleep(slowUploads);
} catch (Exception e) {
}
}
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/apache-commons-fileupload-1.4

View File

@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload2;
/**
* The {@link ProgressListener} may be used to display a progress bar
* or do stuff like that.
*/
public interface ProgressListener {
/**
* Updates the listeners status information.
*
* @param pBytesRead The total number of bytes, which have been read
* so far.
* @param pContentLength The total number of bytes, which are being
* read. May be -1, if this number is unknown.
* @param pItems The number of the field, which is currently being
* read. (0 = no item so far, 1 = first item is being read, ...)
*/
void update(long pBytesRead, long pContentLength, int pItems);
}

View File

@@ -7,7 +7,7 @@
private import javascript
private import ATMConfig
external predicate adaptiveThreatModelingModels(
external predicate availableMlModels(
string modelChecksum, string modelLanguage, string modelName, string modelType
);

View File

@@ -119,10 +119,10 @@ module Raw {
predicate isEntityNameNode(Entity entity) {
exists(int index |
TAstNode(entity) = getParentNode() and
this = getParentNode().astNodeChild(index) and
TAstNode(entity) = this.getParentNode() and
this = this.getParentNode().astNodeChild(index) and
// An entity name node must be the first child of the entity.
index = min(int otherIndex | exists(getParentNode().astNodeChild(otherIndex))) and
index = min(int otherIndex | exists(this.getParentNode().astNodeChild(otherIndex))) and
entity.getName() = rawNode.(raw::VarDecl).getName()
)
}
@@ -319,7 +319,7 @@ module Wrapped {
AstNode getChild(int index) { result = injectedChild(enclosingEntity, rawNode, index) }
string toString() { result = getType() }
string toString() { result = this.getType() }
Raw::Location getLocation() { result = rawNode.getLocation() }
}
@@ -378,7 +378,7 @@ module DatabaseFeatures {
override string getType() { result = "javascript function" }
override string toString() { result = "Entity: " + getName() }
override string toString() { result = "Entity: " + this.getName() }
override Location getLocation() { result = entity.getLocation() }

View File

@@ -11,7 +11,7 @@ import EndpointFeatures as EndpointFeatures
import EndpointTypes
private string getACompatibleModelChecksum() {
adaptiveThreatModelingModels(result, "javascript", _, "atm-endpoint-scoring")
availableMlModels(result, "javascript", _, "atm-endpoint-scoring")
}
/**

View File

@@ -0,0 +1,3 @@
# Avoid checking in ML models
# This matches the mlModels property of qlpack.yml.
resources/*.codeqlmodel

View File

@@ -5,3 +5,5 @@ suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
dependencies:
codeql/javascript-experimental-atm-lib: "*"
mlModels:
- "resources/*.codeqlmodel"

View File

@@ -26,7 +26,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
override Location getLocation() { hasLocation(this, result) }
override File getFile() {
result = getLocation().getFile() // Specialized for performance reasons
result = this.getLocation().getFile() // Specialized for performance reasons
}
/** Gets the first token belonging to this element. */
@@ -76,7 +76,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
/** Gets the toplevel syntactic unit to which this element belongs. */
cached
TopLevel getTopLevel() { Stages::Ast::ref() and result = getParent().getTopLevel() }
TopLevel getTopLevel() { Stages::Ast::ref() and result = this.getParent().getTopLevel() }
/**
* Gets the `i`th child node of this node.
@@ -85,10 +85,10 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
* change between versions of the extractor.
*/
ASTNode getChild(int i) {
result = getChildExpr(i) or
result = getChildStmt(i) or
result = this.getChildExpr(i) or
result = this.getChildStmt(i) or
properties(result, this, i, _, _) or
result = getChildTypeExpr(i)
result = this.getChildTypeExpr(i)
}
/** Gets the `i`th child statement of this node. */
@@ -101,22 +101,22 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
TypeExpr getChildTypeExpr(int i) { typeexprs(result, _, this, i, _) }
/** Gets a child node of this node. */
ASTNode getAChild() { result = getChild(_) }
ASTNode getAChild() { result = this.getChild(_) }
/** Gets a child expression of this node. */
Expr getAChildExpr() { result = getChildExpr(_) }
Expr getAChildExpr() { result = this.getChildExpr(_) }
/** Gets a child statement of this node. */
Stmt getAChildStmt() { result = getChildStmt(_) }
Stmt getAChildStmt() { result = this.getChildStmt(_) }
/** Gets the number of child nodes of this node. */
int getNumChild() { result = count(getAChild()) }
int getNumChild() { result = count(this.getAChild()) }
/** Gets the number of child expressions of this node. */
int getNumChildExpr() { result = count(getAChildExpr()) }
int getNumChildExpr() { result = count(this.getAChildExpr()) }
/** Gets the number of child statements of this node. */
int getNumChildStmt() { result = count(getAChildStmt()) }
int getNumChildStmt() { result = count(this.getAChildStmt()) }
/** Gets the parent node of this node, if any. */
cached
@@ -126,7 +126,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
ControlFlowNode getFirstControlFlowNode() { result = this }
/** Holds if this syntactic entity belongs to an externs file. */
predicate inExternsFile() { getTopLevel().isExterns() }
predicate inExternsFile() { this.getTopLevel().isExterns() }
/**
* Holds if this is an ambient node that is not a `TypeExpr` and is not inside a `.d.ts` file
@@ -137,9 +137,9 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
cached
private predicate isAmbientInternal() {
Stages::Ast::ref() and
getParent().isAmbientInternal()
this.getParent().isAmbientInternal()
or
not isAmbientTopLevel(getTopLevel()) and
not isAmbientTopLevel(this.getTopLevel()) and
(
this instanceof ExternalModuleDeclaration
or
@@ -176,9 +176,9 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
*/
pragma[inline]
predicate isAmbient() {
isAmbientInternal()
this.isAmbientInternal()
or
isAmbientTopLevel(getTopLevel())
isAmbientTopLevel(this.getTopLevel())
or
this instanceof TypeExpr
}
@@ -211,11 +211,11 @@ class TopLevel extends @toplevel, StmtContainer {
predicate isMinified() {
Stages::Ast::ref() and
// file name contains 'min' (not as part of a longer word)
getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+")
this.getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+")
or
exists(int numstmt | numstmt = strictcount(Stmt s | s.getTopLevel() = this) |
// there are more than two statements per line on average
numstmt.(float) / getNumberOfLines() > 2 and
numstmt.(float) / this.getNumberOfLines() > 2 and
// and there are at least ten statements overall
numstmt >= 10
)
@@ -249,9 +249,9 @@ class TopLevel extends @toplevel, StmtContainer {
/** Gets the number of lines containing comments in this toplevel. */
int getNumberOfLinesOfComments() { numlines(this, _, _, result) }
override predicate isStrict() { getAStmt() instanceof StrictModeDecl }
override predicate isStrict() { this.getAStmt() instanceof StrictModeDecl }
override ControlFlowNode getFirstControlFlowNode() { result = getEntry() }
override ControlFlowNode getFirstControlFlowNode() { result = this.getEntry() }
override string toString() { result = "<toplevel>" }
}
@@ -348,7 +348,7 @@ class JavaScriptURL extends @javascript_url, CodeInAttribute { }
* </pre>
*/
class Externs extends TopLevel {
Externs() { isExterns() }
Externs() { this.isExterns() }
}
/**
@@ -393,7 +393,7 @@ class StmtContainer extends @stmt_container, ASTNode {
StmtContainer getFunctionBoundary() {
if this instanceof Function or this instanceof TopLevel
then result = this
else result = getEnclosingContainer().getFunctionBoundary()
else result = this.getEnclosingContainer().getFunctionBoundary()
}
/** Gets a statement that belongs to this container. */
@@ -427,19 +427,19 @@ class StmtContainer extends @stmt_container, ASTNode {
*
* Empty toplevels do not have a start node.
*/
ConcreteControlFlowNode getStart() { successor(getEntry(), result) }
ConcreteControlFlowNode getStart() { successor(this.getEntry(), result) }
/**
* Gets the entry basic block of this function, that is, the basic block
* containing the entry node of its CFG.
*/
EntryBasicBlock getEntryBB() { result = getEntry() }
EntryBasicBlock getEntryBB() { result = this.getEntry() }
/**
* Gets the start basic block of this function, that is, the basic block
* containing the start node of its CFG.
*/
BasicBlock getStartBB() { result.getANode() = getStart() }
BasicBlock getStartBB() { result.getANode() = this.getStart() }
/** Gets the scope induced by this toplevel or function, if any. */
Scope getScope() { scopenodes(this, result) }
@@ -449,7 +449,7 @@ class StmtContainer extends @stmt_container, ASTNode {
*
* See Annex C of the ECMAScript language specification.
*/
predicate isStrict() { getEnclosingContainer().isStrict() }
predicate isStrict() { this.getEnclosingContainer().isStrict() }
}
/**

View File

@@ -55,14 +55,14 @@ module API {
/**
* Gets a call to the function represented by this API component.
*/
CallNode getACall() { result = getReturn().getAnImmediateUse() }
CallNode getACall() { result = this.getReturn().getAnImmediateUse() }
/**
* Gets a call to the function represented by this API component,
* or a promisified version of the function.
*/
CallNode getMaybePromisifiedCall() {
result = getACall()
result = this.getACall()
or
result = Impl::getAPromisifiedInvocation(this, _, _)
}
@@ -70,12 +70,12 @@ module API {
/**
* Gets a `new` call to the function represented by this API component.
*/
NewNode getAnInstantiation() { result = getInstance().getAnImmediateUse() }
NewNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
/**
* Gets an invocation (with our without `new`) to the function represented by this API component.
*/
InvokeNode getAnInvocation() { result = getACall() or result = getAnInstantiation() }
InvokeNode getAnInvocation() { result = this.getACall() or result = this.getAnInstantiation() }
/**
* Gets a data-flow node corresponding to the right-hand side of a definition of the API
@@ -97,7 +97,7 @@ module API {
* Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition
* of the API component represented by this node.
*/
DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(getARhs()) }
DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(this.getARhs()) }
/**
* Gets a node representing member `m` of this API component.
@@ -107,21 +107,21 @@ module API {
*/
bindingset[m]
bindingset[result]
Node getMember(string m) { result = getASuccessor(Label::member(m)) }
Node getMember(string m) { result = this.getASuccessor(Label::member(m)) }
/**
* Gets a node representing a member of this API component where the name of the member is
* not known statically.
*/
Node getUnknownMember() { result = getASuccessor(Label::unknownMember()) }
Node getUnknownMember() { result = this.getASuccessor(Label::unknownMember()) }
/**
* Gets a node representing a member of this API component where the name of the member may
* or may not be known statically.
*/
Node getAMember() {
result = getASuccessor(Label::member(_)) or
result = getUnknownMember()
result = this.getASuccessor(Label::member(_)) or
result = this.getUnknownMember()
}
/**
@@ -135,7 +135,7 @@ module API {
* This predicate may have multiple results when there are multiple constructor calls invoking this API component.
* Consider using `getAnInstantiation()` if there is a need to distinguish between individual constructor calls.
*/
Node getInstance() { result = getASuccessor(Label::instance()) }
Node getInstance() { result = this.getASuccessor(Label::instance()) }
/**
* Gets a node representing the `i`th parameter of the function represented by this node.
@@ -144,14 +144,14 @@ module API {
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
bindingset[i]
Node getParameter(int i) { result = getASuccessor(Label::parameter(i)) }
Node getParameter(int i) { result = this.getASuccessor(Label::parameter(i)) }
/**
* Gets the number of parameters of the function represented by this node.
*/
int getNumParameter() {
result =
max(string s | exists(getASuccessor(Label::parameterByStringIndex(s))) | s.toInt()) + 1
max(string s | exists(this.getASuccessor(Label::parameterByStringIndex(s))) | s.toInt()) + 1
}
/**
@@ -160,12 +160,12 @@ module API {
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
Node getLastParameter() { result = getParameter(getNumParameter() - 1) }
Node getLastParameter() { result = this.getParameter(this.getNumParameter() - 1) }
/**
* Gets a node representing the receiver of the function represented by this node.
*/
Node getReceiver() { result = getASuccessor(Label::receiver()) }
Node getReceiver() { result = this.getASuccessor(Label::receiver()) }
/**
* Gets a node representing a parameter or the receiver of the function represented by this
@@ -176,8 +176,8 @@ module API {
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
Node getAParameter() {
result = getASuccessor(Label::parameterByStringIndex(_)) or
result = getReceiver()
result = this.getASuccessor(Label::parameterByStringIndex(_)) or
result = this.getReceiver()
}
/**
@@ -186,24 +186,26 @@ module API {
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getACall()` if there is a need to distingiush between individual calls.
*/
Node getReturn() { result = getASuccessor(Label::return()) }
Node getReturn() { result = this.getASuccessor(Label::return()) }
/**
* Gets a node representing the promised value wrapped in the `Promise` object represented by
* this node.
*/
Node getPromised() { result = getASuccessor(Label::promised()) }
Node getPromised() { result = this.getASuccessor(Label::promised()) }
/**
* Gets a node representing the error wrapped in the `Promise` object represented by this node.
*/
Node getPromisedError() { result = getASuccessor(Label::promisedError()) }
Node getPromisedError() { result = this.getASuccessor(Label::promisedError()) }
/**
* Gets a string representation of the lexicographically least among all shortest access paths
* from the root to this node.
*/
string getPath() { result = min(string p | p = getAPath(Impl::distanceFromRoot(this)) | p) }
string getPath() {
result = min(string p | p = this.getAPath(Impl::distanceFromRoot(this)) | p)
}
/**
* Gets a node such that there is an edge in the API graph between this node and the other
@@ -221,13 +223,13 @@ module API {
* Gets a node such that there is an edge in the API graph between this node and the other
* one.
*/
Node getAPredecessor() { result = getAPredecessor(_) }
Node getAPredecessor() { result = this.getAPredecessor(_) }
/**
* Gets a node such that there is an edge in the API graph between that other node and
* this one.
*/
Node getASuccessor() { result = getASuccessor(_) }
Node getASuccessor() { result = this.getASuccessor(_) }
/**
* Holds if this node may take its value from `that` node.
@@ -256,9 +258,9 @@ module API {
* parameters are zero.
*/
predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) {
getInducingNode().hasLocationInfo(path, startline, startcol, endline, endcol)
this.getInducingNode().hasLocationInfo(path, startline, startcol, endline, endcol)
or
not exists(getInducingNode()) and
not exists(this.getInducingNode()) and
path = "" and
startline = 0 and
startcol = 0 and
@@ -305,12 +307,12 @@ module API {
/** A node corresponding to a definition of an API component. */
class Definition extends Node, Impl::TDef {
override string toString() { result = "def " + getPath() }
override string toString() { result = "def " + this.getPath() }
}
/** A node corresponding to the use of an API component. */
class Use extends Node, Impl::TUse {
override string toString() { result = "use " + getPath() }
override string toString() { result = "use " + this.getPath() }
}
/** Gets the root node. */
@@ -964,19 +966,19 @@ module API {
pragma[nomagic]
Node getParameter(int i) {
result = callee.getParameter(i) and
result = getAParameterCandidate(i)
result = this.getAParameterCandidate(i)
}
/**
* Gets an API node where a RHS of the node is the `i`th argument to this call.
*/
private Node getAParameterCandidate(int i) { result.getARhs() = getArgument(i) }
private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) }
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = getParameter(_) }
Node getAParameter() { result = this.getParameter(_) }
/** Gets the API node for the last parameter of this invocation. */
Node getLastParameter() { result = getParameter(getNumArgument() - 1) }
Node getLastParameter() { result = this.getParameter(this.getNumArgument() - 1) }
/** Gets the API node for the return value of this call. */
Node getReturn() {

View File

@@ -129,7 +129,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
BasicBlock getAPredecessor() { result.getASuccessor() = this }
/** Gets a node in this block. */
ControlFlowNode getANode() { result = getNode(_) }
ControlFlowNode getANode() { result = this.getNode(_) }
/** Gets the node at the given position in this block. */
ControlFlowNode getNode(int pos) { bbIndex(this, result, pos) }
@@ -138,7 +138,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
ControlFlowNode getFirstNode() { result = this }
/** Gets the last node in this block. */
ControlFlowNode getLastNode() { result = getNode(length() - 1) }
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
/** Gets the length of this block. */
int length() { result = bbLength(this) }
@@ -160,13 +160,13 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
*/
predicate isLiveAtEntry(Variable v, VarUse u) {
// restrict `u` to be reachable from this basic block
u = getASuccessor*().getANode() and
u = this.getASuccessor*().getANode() and
(
// shortcut: if `v` is never defined, then it must be live
isDefinedInSameContainer(v)
this.isDefinedInSameContainer(v)
implies
// otherwise, do full liveness computation
isLiveAtEntryImpl(v, u)
this.isLiveAtEntryImpl(v, u)
)
}
@@ -176,11 +176,11 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* function or script.
*/
private predicate isLiveAtEntryImpl(Variable v, VarUse u) {
isLocallyLiveAtEntry(v, u)
this.isLocallyLiveAtEntry(v, u)
or
isDefinedInSameContainer(v) and
this.isDefinedInSameContainer(v) and
not this.defAt(_, v, _) and
getASuccessor().isLiveAtEntryImpl(v, u)
this.getASuccessor().isLiveAtEntryImpl(v, u)
}
/**
@@ -188,7 +188,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* this basic block belongs.
*/
private predicate isDefinedInSameContainer(Variable v) {
exists(VarDef def | def.getAVariable() = v and def.getContainer() = getContainer())
exists(VarDef def | def.getAVariable() = v and def.getContainer() = this.getContainer())
}
/**
@@ -198,9 +198,9 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* be more efficient on large databases.
*/
predicate isLiveAtEntry(Variable v) {
isLocallyLiveAtEntry(v, _)
this.isLocallyLiveAtEntry(v, _)
or
not this.defAt(_, v, _) and getASuccessor().isLiveAtEntry(v)
not this.defAt(_, v, _) and this.getASuccessor().isLiveAtEntry(v)
}
/**
@@ -208,18 +208,18 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* `u` is a use of `v` witnessing the liveness.
*/
predicate localIsLiveAtEntry(LocalVariable v, VarUse u) {
isLocallyLiveAtEntry(v, u)
this.isLocallyLiveAtEntry(v, u)
or
not this.defAt(_, v, _) and getASuccessor().localIsLiveAtEntry(v, u)
not this.defAt(_, v, _) and this.getASuccessor().localIsLiveAtEntry(v, u)
}
/**
* Holds if local variable `v` is live at entry to this basic block.
*/
predicate localIsLiveAtEntry(LocalVariable v) {
isLocallyLiveAtEntry(v, _)
this.isLocallyLiveAtEntry(v, _)
or
not this.defAt(_, v, _) and getASuccessor().localIsLiveAtEntry(v)
not this.defAt(_, v, _) and this.getASuccessor().localIsLiveAtEntry(v)
}
/**
@@ -227,9 +227,9 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* this basic block without going through a redefinition of `v`.
*/
predicate localMayBeOverwritten(LocalVariable v, VarDef d) {
isLocallyOverwritten(v, d)
this.isLocallyOverwritten(v, d)
or
not defAt(_, v, _) and getASuccessor().localMayBeOverwritten(v, d)
not this.defAt(_, v, _) and this.getASuccessor().localMayBeOverwritten(v, d)
}
/**
@@ -239,10 +239,10 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* result is the length of this basic block.
*/
private int nextDefOrUseAfter(PurelyLocalVariable v, int i, VarDef d) {
defAt(i, v, d) and
this.defAt(i, v, d) and
result =
min(int j |
(defAt(j, v, _) or useAt(j, v, _) or j = length()) and
(this.defAt(j, v, _) or this.useAt(j, v, _) or j = this.length()) and
j > i
)
}
@@ -253,10 +253,10 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* definition and before a re-definition.
*/
predicate localLiveDefAt(PurelyLocalVariable v, int i, VarDef d) {
exists(int j | j = nextDefOrUseAfter(v, i, d) |
useAt(j, v, _)
exists(int j | j = this.nextDefOrUseAfter(v, i, d) |
this.useAt(j, v, _)
or
j = length() and getASuccessor().localIsLiveAtEntry(v)
j = this.length() and this.getASuccessor().localIsLiveAtEntry(v)
)
}
@@ -265,7 +265,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* no definitions of `v` before it.
*/
private predicate isLocallyLiveAtEntry(Variable v, VarUse u) {
exists(int n | useAt(n, v, u) | not exists(int m | m < n | defAt(m, v, _)))
exists(int n | this.useAt(n, v, u) | not exists(int m | m < n | this.defAt(m, v, _)))
}
/**
@@ -273,7 +273,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* no other definitions of `v` before it.
*/
private predicate isLocallyOverwritten(Variable v, VarDef d) {
exists(int n | defAt(n, v, d) | not exists(int m | m < n | defAt(m, v, _)))
exists(int n | this.defAt(n, v, d) | not exists(int m | m < n | this.defAt(m, v, _)))
}
/**
@@ -287,7 +287,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* whose first node is unreachable.
*/
class UnreachableBlock extends BasicBlock {
UnreachableBlock() { getFirstNode().isUnreachable() }
UnreachableBlock() { this.getFirstNode().isUnreachable() }
}
/**
@@ -337,7 +337,7 @@ class ReachableBasicBlock extends BasicBlock {
* A reachable basic block with more than one predecessor.
*/
class ReachableJoinBlock extends ReachableBasicBlock {
ReachableJoinBlock() { getFirstNode().isJoin() }
ReachableJoinBlock() { this.getFirstNode().isJoin() }
/**
* Holds if this basic block belongs to the dominance frontier of `b`, that is
@@ -348,11 +348,11 @@ class ReachableJoinBlock extends ReachableBasicBlock {
* its use in optimization".
*/
predicate inDominanceFrontierOf(ReachableBasicBlock b) {
b = getAPredecessor() and not b = getImmediateDominator()
b = this.getAPredecessor() and not b = this.getImmediateDominator()
or
exists(ReachableBasicBlock prev | inDominanceFrontierOf(prev) |
exists(ReachableBasicBlock prev | this.inDominanceFrontierOf(prev) |
b = prev.getImmediateDominator() and
not b = getImmediateDominator()
not b = this.getImmediateDominator()
)
}
}

View File

@@ -39,7 +39,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
* Has no result if no name could be determined.
*/
string getName() {
result = getIdentifier().getName() // Overridden in ClassExpr
result = this.getIdentifier().getName() // Overridden in ClassExpr
}
/** Gets a member declared in this class or interface. */
@@ -50,37 +50,37 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
/** Gets the member with the given name declared in this class or interface. */
MemberDeclaration getMember(string name) {
result = getAMember() and
result = this.getAMember() and
result.getName() = name
}
/** Gets a method declared in this class or interface. */
MethodDeclaration getAMethod() { result = getAMember() }
MethodDeclaration getAMethod() { result = this.getAMember() }
/**
* Gets the method with the given name declared in this class or interface.
*
* Note that for overloaded method signatures in TypeScript files, this returns every overload.
*/
MethodDeclaration getMethod(string name) { result = getMember(name) }
MethodDeclaration getMethod(string name) { result = this.getMember(name) }
/** Gets an overloaded version of the method with the given name declared in this class or interface. */
MethodDeclaration getMethodOverload(string name, int overloadIndex) {
result = getMethod(name) and
result = this.getMethod(name) and
overloadIndex = result.getOverloadIndex()
}
/** Gets a field declared in this class or interface. */
FieldDeclaration getAField() { result = getAMember() }
FieldDeclaration getAField() { result = this.getAMember() }
/** Gets the field with the given name declared in this class or interface. */
FieldDeclaration getField(string name) { result = getMember(name) }
FieldDeclaration getField(string name) { result = this.getMember(name) }
/** Gets a call signature declared in this interface. */
CallSignature getACallSignature() { result = getAMember() }
CallSignature getACallSignature() { result = this.getAMember() }
/** Gets an index signature declared in this interface. */
IndexSignature getAnIndexSignature() { result = getAMember() }
IndexSignature getAnIndexSignature() { result = this.getAMember() }
/**
* Gets the expression denoting the super class of this class,
@@ -97,7 +97,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
/**
* Gets any type from the `implements` clause of this class or `extends` clause of this interface.
*/
TypeExpr getASuperInterface() { result = getSuperInterface(_) }
TypeExpr getASuperInterface() { result = this.getSuperInterface(_) }
/**
* Holds if this is an interface or a class declared with the `abstract` modifier.
@@ -157,10 +157,10 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
*/
class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNode {
/** Gets the variable holding this class. */
Variable getVariable() { result = getIdentifier().getVariable() }
Variable getVariable() { result = this.getIdentifier().getVariable() }
/** Gets the identifier naming the defined class, if any. */
override VarDecl getIdentifier() { result = getChildExpr(0) }
override VarDecl getIdentifier() { result = this.getChildExpr(0) }
override TypeParameter getTypeParameter(int i) {
// AST indices for type parameters: -3, -6, -9, ...
@@ -170,7 +170,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
}
/** Gets the expression denoting the super class of the defined class, if any. */
override Expr getSuperClass() { result = getChildExpr(1) }
override Expr getSuperClass() { result = this.getChildExpr(1) }
/** Gets the `n`th type from the `implements` clause of this class, starting at 0. */
override TypeExpr getSuperInterface(int i) {
@@ -189,7 +189,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Note that every class has a constructor: if no explicit constructor
* is declared, it has a synthetic default constructor.
*/
ConstructorDeclaration getConstructor() { result = getAMethod() }
ConstructorDeclaration getConstructor() { result = this.getAMethod() }
/**
* Gets the `i`th decorator applied to this class.
@@ -210,7 +210,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* For example, the class `@A @B class C {}` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
/**
* Holds if this class has the `abstract` modifier.
@@ -218,8 +218,8 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
override predicate isAbstract() { is_abstract_class(this) }
override string describe() {
if exists(inferNameFromVarDef())
then result = inferNameFromVarDef()
if exists(this.inferNameFromVarDef())
then result = this.inferNameFromVarDef()
else result = "anonymous class"
}
@@ -229,8 +229,8 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `let C = class D {}`, prefer `D` to `C`
if exists(getIdentifier())
then result = "class " + getIdentifier().getName()
if exists(this.getIdentifier())
then result = "class " + this.getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "class " + vd.getTarget().(VarRef).getName()
@@ -243,7 +243,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Note that constructors aren't considered instance methods.
*/
Function getInstanceMethod(string name) {
exists(MemberDefinition mem | mem = getMember(name) |
exists(MemberDefinition mem | mem = this.getMember(name) |
result = mem.getInit() and
not mem.isStatic() and
not mem instanceof ConstructorDefinition
@@ -254,7 +254,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Gets the definition of the super class of this class, if it can be determined.
*/
ClassDefinition getSuperClassDefinition() {
result = getSuperClass().analyze().getAValue().(AbstractClass).getClass()
result = this.getSuperClass().analyze().getAValue().(AbstractClass).getClass()
}
override string getAPrimaryQlClass() { result = "ClassDefinition" }
@@ -285,7 +285,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
*/
class ClassDeclStmt extends @class_decl_stmt, ClassDefinition, Stmt {
override ControlFlowNode getFirstControlFlowNode() {
if has_declare_keyword(this) then result = this else result = getIdentifier()
if has_declare_keyword(this) then result = this else result = this.getIdentifier()
}
}
@@ -307,7 +307,7 @@ class ClassExpr extends @class_expr, ClassDefinition, Expr {
override string getName() {
result = ClassDefinition.super.getName()
or
not exists(getIdentifier()) and
not exists(this.getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@@ -327,21 +327,25 @@ class ClassExpr extends @class_expr, ClassDefinition, Expr {
override predicate isImpure() { none() }
override ControlFlowNode getFirstControlFlowNode() {
if exists(getIdentifier())
then result = getIdentifier()
if exists(this.getIdentifier())
then result = this.getIdentifier()
else
if exists(getSuperClass())
then result = getSuperClass().getFirstControlFlowNode()
if exists(this.getSuperClass())
then result = this.getSuperClass().getFirstControlFlowNode()
else
if exists(getClassInitializedMember())
if exists(this.getClassInitializedMember())
then
result =
min(ClassInitializedMember m | m = getClassInitializedMember() | m order by m.getIndex())
min(ClassInitializedMember m |
m = this.getClassInitializedMember()
|
m order by m.getIndex()
)
else result = this
}
/** Returns a member that is initialized during the creation of this class. */
private ClassInitializedMember getClassInitializedMember() { result = getAMember() }
private ClassInitializedMember getClassInitializedMember() { result = this.getAMember() }
}
/**
@@ -371,7 +375,7 @@ class SuperExpr extends @super_expr, Expr {
* Gets the function whose `super` binding this expression refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getEnclosingFunction().getThisBinder() }
Function getBinder() { result = this.getEnclosingFunction().getThisBinder() }
override string getAPrimaryQlClass() { result = "SuperExpr" }
}
@@ -386,13 +390,13 @@ class SuperExpr extends @super_expr, Expr {
* ```
*/
class SuperCall extends CallExpr {
SuperCall() { getCallee().getUnderlyingValue() instanceof SuperExpr }
SuperCall() { this.getCallee().getUnderlyingValue() instanceof SuperExpr }
/**
* Gets the function whose `super` binding this call refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getCallee().getUnderlyingValue().(SuperExpr).getBinder() }
Function getBinder() { result = this.getCallee().getUnderlyingValue().(SuperExpr).getBinder() }
}
/**
@@ -405,7 +409,7 @@ class SuperCall extends CallExpr {
* ```
*/
class SuperPropAccess extends PropAccess {
SuperPropAccess() { getBase().getUnderlyingValue() instanceof SuperExpr }
SuperPropAccess() { this.getBase().getUnderlyingValue() instanceof SuperExpr }
}
/**
@@ -502,7 +506,7 @@ class MemberDeclaration extends @property, Documentable {
*
* Class members not declared in a TypeScript file are always considered public.
*/
predicate isPublic() { not isPrivate() and not isProtected() }
predicate isPublic() { not this.isPrivate() and not this.isProtected() }
/**
* Holds if this is a TypeScript member explicitly annotated with the `public` keyword.
@@ -523,20 +527,20 @@ class MemberDeclaration extends @property, Documentable {
* Gets the expression specifying the name of this member,
* or nothing if this is a call signature.
*/
Expr getNameExpr() { result = getChildExpr(0) }
Expr getNameExpr() { result = this.getChildExpr(0) }
/**
* Gets the expression specifying the initial value of the member;
* for methods and constructors this is always a function, for fields
* it may not be defined.
*/
Expr getInit() { result = getChildExpr(1) }
Expr getInit() { result = this.getChildExpr(1) }
/** Gets the name of this member. */
string getName() {
result = getNameExpr().(Literal).getValue()
result = this.getNameExpr().(Literal).getValue()
or
not isComputed() and result = getNameExpr().(Identifier).getName()
not this.isComputed() and result = this.getNameExpr().(Identifier).getName()
}
/** Holds if the name of this member is computed. */
@@ -552,7 +556,7 @@ class MemberDeclaration extends @property, Documentable {
int getMemberIndex() { properties(this, _, result, _, _) }
/** Holds if the name of this member is computed by an impure expression. */
predicate hasImpureNameExpr() { isComputed() and getNameExpr().isImpure() }
predicate hasImpureNameExpr() { this.isComputed() and this.getNameExpr().isImpure() }
/**
* Gets the `i`th decorator applied to this member.
@@ -560,7 +564,7 @@ class MemberDeclaration extends @property, Documentable {
* For example, a method of the form `@A @B m() { ... }` has
* `@A` as its 0th decorator and `@B` as its first decorator.
*/
Decorator getDecorator(int i) { result = getChildExpr(-(i + 1)) }
Decorator getDecorator(int i) { result = this.getChildExpr(-(i + 1)) }
/**
* Gets a decorator applied to this member.
@@ -568,27 +572,27 @@ class MemberDeclaration extends @property, Documentable {
* For example, a method of the form `@A @B m() { ... }` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
override string toString() { properties(this, _, _, _, result) }
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
result = this.getNameExpr().getFirstControlFlowNode()
}
/**
* True if this is neither abstract, ambient, nor part of an overloaded method signature.
*/
predicate isConcrete() {
not isAbstract() and
not isAmbient() and
not this.isAbstract() and
not this.isAmbient() and
(this instanceof MethodDeclaration implies this.(MethodDeclaration).getBody().hasBody())
}
/**
* True if this is abstract, ambient, or an overload signature.
*/
predicate isSignature() { not isConcrete() }
predicate isSignature() { not this.isConcrete() }
override string getAPrimaryQlClass() { result = "MemberDeclaration" }
}
@@ -615,7 +619,7 @@ class MemberDeclaration extends @property, Documentable {
* ```
*/
class MemberDefinition extends MemberDeclaration {
MemberDefinition() { isConcrete() }
MemberDefinition() { this.isConcrete() }
}
/**
@@ -631,7 +635,7 @@ class MemberDefinition extends MemberDeclaration {
* ```
*/
class MemberSignature extends MemberDeclaration {
MemberSignature() { isSignature() }
MemberSignature() { this.isSignature() }
}
/**
@@ -668,7 +672,7 @@ class MethodDeclaration extends MemberDeclaration {
/**
* Gets the body of this method.
*/
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/**
* Holds if this method is overloaded, that is, there are multiple method
@@ -676,10 +680,10 @@ class MethodDeclaration extends MemberDeclaration {
*/
predicate isOverloaded() {
not this instanceof ConstructorDeclaration and
hasOverloadedMethod(getDeclaringType(), getName())
hasOverloadedMethod(this.getDeclaringType(), this.getName())
or
this instanceof ConstructorDeclaration and
hasOverloadedConstructor(getDeclaringClass())
hasOverloadedConstructor(this.getDeclaringClass())
}
/**
@@ -806,13 +810,13 @@ class MethodSignature extends MethodDeclaration, MemberSignature {
*/
class ConstructorDeclaration extends MethodDeclaration {
ConstructorDeclaration() {
not isComputed() and
not isStatic() and
getName() = "constructor"
not this.isComputed() and
not this.isStatic() and
this.getName() = "constructor"
}
/** Holds if this is a synthetic default constructor. */
predicate isSynthetic() { getLocation().isEmpty() }
predicate isSynthetic() { this.getLocation().isEmpty() }
override string getAPrimaryQlClass() { result = "ConstructorDeclaration" }
}
@@ -1073,9 +1077,9 @@ class SetterMethodSignature extends SetterMethodDeclaration, AccessorMethodSigna
class FieldDeclaration extends MemberDeclaration, @field {
/** Gets the type annotation of this field, if any, such as `T` in `{ x: T }`. */
TypeAnnotation getTypeAnnotation() {
result = getChildTypeExpr(2)
result = this.getChildTypeExpr(2)
or
result = getDocumentation().getATagByTitle("type").getType()
result = this.getDocumentation().getATagByTitle("type").getType()
}
/** Holds if this is a TypeScript field annotated with the `readonly` keyword. */
@@ -1136,9 +1140,9 @@ class ParameterField extends FieldDeclaration, @parameter_field {
)
}
override Expr getNameExpr() { result = getParameter() }
override Expr getNameExpr() { result = this.getParameter() }
override TypeAnnotation getTypeAnnotation() { result = getParameter().getTypeAnnotation() }
override TypeAnnotation getTypeAnnotation() { result = this.getParameter().getTypeAnnotation() }
}
/**
@@ -1168,7 +1172,7 @@ class StaticInitializer extends MemberDefinition, @static_initializer {
* Call signatures are either function call signatures or constructor call signatures.
*/
class CallSignature extends @call_signature, MemberSignature {
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/** Gets the interface or function type that declares this call signature. */
override InterfaceDefinition getDeclaringType() {
@@ -1190,7 +1194,7 @@ class CallSignature extends @call_signature, MemberSignature {
class FunctionCallSignature extends @function_call_signature, CallSignature {
/** Gets the index of this function call signature among the function call signatures in the enclosing type. */
int getOverloadIndex() {
exists(ClassOrInterface type | type = getDeclaringType() |
exists(ClassOrInterface type | type = this.getDeclaringType() |
this =
rank[result + 1](FunctionCallSignature sig, int i |
sig = type.getMemberByIndex(i)
@@ -1204,7 +1208,7 @@ class FunctionCallSignature extends @function_call_signature, CallSignature {
* Holds if this function call signature is overloaded, that is, there are multiple function call
* signatures declared in the enclosing type.
*/
predicate isOverloaded() { hasOverloadedFunctionCallSignature(getDeclaringType()) }
predicate isOverloaded() { hasOverloadedFunctionCallSignature(this.getDeclaringType()) }
}
/**
@@ -1221,7 +1225,7 @@ class FunctionCallSignature extends @function_call_signature, CallSignature {
class ConstructorCallSignature extends @constructor_call_signature, CallSignature {
/** Gets the index of this constructor call signature among the constructor call signatures in the enclosing type. */
int getOverloadIndex() {
exists(ClassOrInterface type | type = getDeclaringType() |
exists(ClassOrInterface type | type = this.getDeclaringType() |
this =
rank[result + 1](ConstructorCallSignature sig, int i |
sig = type.getMemberByIndex(i)
@@ -1235,7 +1239,7 @@ class ConstructorCallSignature extends @constructor_call_signature, CallSignatur
* Holds if this constructor call signature is overloaded, that is, there are multiple constructor call
* signatures declared in the enclosing type.
*/
predicate isOverloaded() { hasOverloadedConstructorCallSignature(getDeclaringType()) }
predicate isOverloaded() { hasOverloadedConstructorCallSignature(this.getDeclaringType()) }
}
/**
@@ -1250,7 +1254,7 @@ class ConstructorCallSignature extends @constructor_call_signature, CallSignatur
* ```
*/
class IndexSignature extends @index_signature, MemberSignature {
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/** Gets the interface or function type that declares this index signature. */
override InterfaceDefinition getDeclaringType() {

View File

@@ -51,13 +51,13 @@ module DOM {
* Gets the root element (i.e. an element without a parent) in which this element is contained.
*/
ElementDefinition getRoot() {
if not exists(getParent()) then result = this else result = getParent().getRoot()
if not exists(this.getParent()) then result = this else result = this.getParent().getRoot()
}
/**
* Gets the document element to which this element belongs, if it can be determined.
*/
DocumentElementDefinition getDocument() { result = getRoot() }
DocumentElementDefinition getDocument() { result = this.getRoot() }
}
/**
@@ -108,7 +108,7 @@ module DOM {
/**
* Gets the value of this attribute, if it can be determined.
*/
string getStringValue() { result = getValueNode().getStringValue() }
string getStringValue() { result = this.getValueNode().getStringValue() }
/**
* Gets the DOM element this attribute belongs to.
@@ -120,7 +120,7 @@ module DOM {
* such as `{{window.location.url}}`.
*/
predicate mayHaveTemplateValue() {
getStringValue().regexpMatch(Templating::getDelimiterMatchingRegexp())
this.getStringValue().regexpMatch(Templating::getDelimiterMatchingRegexp())
}
}
@@ -359,35 +359,6 @@ module DOM {
call.getNumArgument() = 1 and
unique(InferredType t | t = getArgumentTypeFromJQueryMethodGet(call)) = TTNumber()
)
or
// A `this` node from a callback given to a `$().each(callback)` call.
// purposely not using JQuery::MethodCall to avoid `jquery.each()`.
exists(DataFlow::CallNode eachCall | eachCall = JQuery::objectRef().getAMethodCall("each") |
this = DataFlow::thisNode(eachCall.getCallback(0).getFunction()) or
this = eachCall.getABoundCallbackParameter(0, 1)
)
or
// A read of an array-element from a JQuery object. E.g. `$("#foo")[0]`
exists(DataFlow::PropRead read |
read = this and read = JQuery::objectRef().getAPropertyRead()
|
unique(InferredType t | t = read.getPropertyNameExpr().analyze().getAType()) = TTNumber()
)
or
// A receiver node of an event handler on a DOM node
exists(DataFlow::SourceNode domNode, DataFlow::FunctionNode eventHandler |
// NOTE: we do not use `getABoundFunctionValue()`, since bound functions tend to have
// a different receiver anyway
eventHandler = domNode.getAPropertySource(any(string n | n.matches("on%")))
or
eventHandler =
domNode.getAMethodCall("addEventListener").getArgument(1).getAFunctionValue()
|
domNode = domValueRef() and
this = eventHandler.getReceiver()
)
or
this = DataFlow::thisNode(any(EventHandlerCode evt))
}
}
}
@@ -421,11 +392,6 @@ module DOM {
or
t.start() and
result = domValueRef().getAMethodCall(["item", "namedItem"])
or
t.startInProp("target") and
result = domEventSource()
or
exists(DataFlow::TypeTracker t2 | result = domValueRef(t2).track(t2, t))
}
/** Gets a data flow node that may refer to a value from the DOM. */

View File

@@ -45,7 +45,7 @@ module DefensiveExpressionTest {
)
}
override boolean getTheTestResult() { result = analyze().getTheBooleanValue() }
override boolean getTheTestResult() { result = this.analyze().getTheBooleanValue() }
}
/**
@@ -153,7 +153,7 @@ module DefensiveExpressionTest {
InferredType op2type;
NullUndefinedComparison() {
exists(Expr op2 | hasOperands(operand, op2) |
exists(Expr op2 | this.hasOperands(operand, op2) |
op2type = TTNull() and SyntacticConstants::isNull(op2)
or
op2type = TTUndefined() and SyntacticConstants::isUndefined(op2)
@@ -161,7 +161,7 @@ module DefensiveExpressionTest {
}
override boolean getTheTestResult() {
result = getPolarity() and
result = this.getPolarity() and
(
if this instanceof StrictEqualityTest
then
@@ -172,7 +172,7 @@ module DefensiveExpressionTest {
not isNotNullOrUndefined(operand.analyze().getAType())
)
or
result = getPolarity().booleanNot() and
result = this.getPolarity().booleanNot() and
(
if this instanceof StrictEqualityTest
then
@@ -336,7 +336,7 @@ module DefensiveExpressionTest {
or
testResult = false and not operand.analyze().getAType().getTypeofTag() = tag
|
if getPolarity() = true then result = testResult else result = testResult.booleanNot()
if this.getPolarity() = true then result = testResult else result = testResult.booleanNot()
)
}

View File

@@ -20,22 +20,22 @@ class ExprOrType extends @expr_or_type, Documentable {
Stmt getEnclosingStmt() { enclosing_stmt(this, result) }
/** Gets the function in which this expression or type appears, if any. */
Function getEnclosingFunction() { result = getContainer() }
Function getEnclosingFunction() { result = this.getContainer() }
/**
* Gets the JSDoc comment associated with this expression or type or its parent statement, if any.
*/
override JSDoc getDocumentation() {
result = getOwnDocumentation()
result = this.getOwnDocumentation()
or
// if there is no JSDoc for the expression itself, check the enclosing property or statement
not exists(getOwnDocumentation()) and
not exists(this.getOwnDocumentation()) and
(
exists(Property prop | prop = getParent() | result = prop.getDocumentation())
exists(Property prop | prop = this.getParent() | result = prop.getDocumentation())
or
exists(MethodDeclaration decl | decl = getParent() | result = decl.getDocumentation())
exists(MethodDeclaration decl | decl = this.getParent() | result = decl.getDocumentation())
or
exists(VariableDeclarator decl | decl = getParent() | result = decl.getDocumentation())
exists(VariableDeclarator decl | decl = this.getParent() | result = decl.getDocumentation())
or
exists(DeclStmt stmt | this = stmt.getDecl(0) | result = stmt.getDocumentation())
or
@@ -119,7 +119,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
* Holds if this expression is pure, that is, its evaluation is guaranteed
* to be side-effect free.
*/
predicate isPure() { not isImpure() }
predicate isPure() { not this.isImpure() }
/**
* Gets the kind of this expression, which is an integer value representing the expression's
@@ -151,22 +151,22 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
* Holds if this expression accesses the global variable `g`, either directly
* or through the `window` object.
*/
predicate accessesGlobal(string g) { flow().accessesGlobal(g) }
predicate accessesGlobal(string g) { this.flow().accessesGlobal(g) }
/**
* Holds if this expression may evaluate to `s`.
*/
predicate mayHaveStringValue(string s) { flow().mayHaveStringValue(s) }
predicate mayHaveStringValue(string s) { this.flow().mayHaveStringValue(s) }
/**
* Holds if this expression may evaluate to `b`.
*/
predicate mayHaveBooleanValue(boolean b) { flow().mayHaveBooleanValue(b) }
predicate mayHaveBooleanValue(boolean b) { this.flow().mayHaveBooleanValue(b) }
/**
* Holds if this expression may refer to the initial value of parameter `p`.
*/
predicate mayReferToParameter(Parameter p) { flow().mayReferToParameter(p) }
predicate mayReferToParameter(Parameter p) { this.flow().mayReferToParameter(p) }
/**
* Gets the static type of this expression, as determined by the TypeScript type system.
@@ -248,9 +248,9 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
*/
pragma[inline]
DataFlow::Node getExceptionTarget() {
result = getCatchParameterFromStmt(getRawEnclosingStmt(this))
result = getCatchParameterFromStmt(this.getRawEnclosingStmt(this))
or
not exists(getCatchParameterFromStmt(getRawEnclosingStmt(this))) and
not exists(getCatchParameterFromStmt(this.getRawEnclosingStmt(this))) and
result =
any(DataFlow::FunctionNode f | f.getFunction() = this.getContainer()).getExceptionalReturn()
}
@@ -340,15 +340,15 @@ class ParExpr extends @par_expr, Expr {
/** Gets the expression within parentheses. */
Expr getExpression() { result = this.getChildExpr(0) }
override Expr stripParens() { result = getExpression().stripParens() }
override Expr stripParens() { result = this.getExpression().stripParens() }
override int getIntValue() { result = getExpression().getIntValue() }
override int getIntValue() { result = this.getExpression().getIntValue() }
override predicate isImpure() { getExpression().isImpure() }
override predicate isImpure() { this.getExpression().isImpure() }
override Expr getUnderlyingValue() { result = getExpression().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getExpression().getUnderlyingValue() }
override Expr getUnderlyingReference() { result = getExpression().getUnderlyingReference() }
override Expr getUnderlyingReference() { result = this.getExpression().getUnderlyingReference() }
override string getAPrimaryQlClass() { result = "ParExpr" }
}
@@ -391,10 +391,10 @@ class BooleanLiteral extends @boolean_literal, Literal { }
*/
class NumberLiteral extends @number_literal, Literal {
/** Gets the integer value of this literal. */
override int getIntValue() { result = getValue().toInt() }
override int getIntValue() { result = this.getValue().toInt() }
/** Gets the floating point value of this literal. */
float getFloatValue() { result = getValue().toFloat() }
float getFloatValue() { result = this.getValue().toFloat() }
}
/**
@@ -411,13 +411,13 @@ class BigIntLiteral extends @bigint_literal, Literal {
* Gets the integer value of this literal if it can be represented
* as a QL integer value.
*/
override int getIntValue() { result = getValue().toInt() }
override int getIntValue() { result = this.getValue().toInt() }
/**
* Gets the floating point value of this literal if it can be represented
* as a QL floating point value.
*/
float getFloatValue() { result = getValue().toFloat() }
float getFloatValue() { result = this.getValue().toFloat() }
}
/**
@@ -459,19 +459,19 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent {
RegExpTerm getRoot() { this = result.getParent() }
/** Gets the flags of this regular expression. */
string getFlags() { result = getValue().regexpCapture(".*/(\\w*)$", 1) }
string getFlags() { result = this.getValue().regexpCapture(".*/(\\w*)$", 1) }
/** Holds if this regular expression has an `m` flag. */
predicate isMultiline() { RegExp::isMultiline(getFlags()) }
predicate isMultiline() { RegExp::isMultiline(this.getFlags()) }
/** Holds if this regular expression has a `g` flag. */
predicate isGlobal() { RegExp::isGlobal(getFlags()) }
predicate isGlobal() { RegExp::isGlobal(this.getFlags()) }
/** Holds if this regular expression has an `i` flag. */
predicate isIgnoreCase() { RegExp::isIgnoreCase(getFlags()) }
predicate isIgnoreCase() { RegExp::isIgnoreCase(this.getFlags()) }
/** Holds if this regular expression has an `s` flag. */
predicate isDotAll() { RegExp::isDotAll(getFlags()) }
predicate isDotAll() { RegExp::isDotAll(this.getFlags()) }
override string getAPrimaryQlClass() { result = "RegExpLiteral" }
}
@@ -492,16 +492,16 @@ class ThisExpr extends @this_expr, Expr {
* Gets the function whose `this` binding this expression refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getEnclosingFunction().getThisBinder() }
Function getBinder() { result = this.getEnclosingFunction().getThisBinder() }
/**
* Gets the function or top-level whose `this` binding this expression refers to,
* which is the nearest enclosing non-arrow function or top-level.
*/
StmtContainer getBindingContainer() {
result = getContainer().(Function).getThisBindingContainer()
result = this.getContainer().(Function).getThisBindingContainer()
or
result = getContainer().(TopLevel)
result = this.getContainer().(TopLevel)
}
override string getAPrimaryQlClass() { result = "ThisExpr" }
@@ -534,14 +534,14 @@ class ArrayExpr extends @array_expr, Expr {
/** Holds if the `i`th element of this array literal is omitted. */
predicate elementIsOmitted(int i) {
i in [0 .. getSize() - 1] and
not exists(getElement(i))
i in [0 .. this.getSize() - 1] and
not exists(this.getElement(i))
}
/** Holds if this array literal has an omitted element. */
predicate hasOmittedElement() { elementIsOmitted(_) }
predicate hasOmittedElement() { this.elementIsOmitted(_) }
override predicate isImpure() { getAnElement().isImpure() }
override predicate isImpure() { this.getAnElement().isImpure() }
override string getAPrimaryQlClass() { result = "ArrayExpr" }
}
@@ -583,7 +583,7 @@ class ObjectExpr extends @obj_expr, Expr {
*/
predicate hasTrailingComma() { this.getLastToken().getPreviousToken().getValue() = "," }
override predicate isImpure() { getAProperty().isImpure() }
override predicate isImpure() { this.getAProperty().isImpure() }
override string getAPrimaryQlClass() { result = "ObjectExpr" }
}
@@ -626,9 +626,9 @@ class Property extends @property, Documentable {
/** Gets the name of this property. */
string getName() {
not isComputed() and result = getNameExpr().(Identifier).getName()
not this.isComputed() and result = this.getNameExpr().(Identifier).getName()
or
result = getNameExpr().(Literal).getValue()
result = this.getNameExpr().(Literal).getValue()
}
/** Holds if the name of this property is computed. */
@@ -638,30 +638,30 @@ class Property extends @property, Documentable {
predicate isMethod() { is_method(this) }
/** Holds if this property is defined using shorthand syntax. */
predicate isShorthand() { getNameExpr().getLocation() = getInit().getLocation() }
predicate isShorthand() { this.getNameExpr().getLocation() = this.getInit().getLocation() }
/** Gets the object literal this property belongs to. */
ObjectExpr getObjectExpr() { properties(this, result, _, _, _) }
/** Gets the (0-based) index at which this property appears in its enclosing literal. */
int getIndex() { this = getObjectExpr().getProperty(result) }
int getIndex() { this = this.getObjectExpr().getProperty(result) }
/**
* Holds if this property is impure, that is, the evaluation of its name or
* its initializer expression could have side effects.
*/
predicate isImpure() {
isComputed() and getNameExpr().isImpure()
this.isComputed() and this.getNameExpr().isImpure()
or
getInit().isImpure()
this.getInit().isImpure()
}
override string toString() { properties(this, _, _, _, result) }
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
result = this.getNameExpr().getFirstControlFlowNode()
or
not exists(getNameExpr()) and result = getInit().getFirstControlFlowNode()
not exists(this.getNameExpr()) and result = this.getInit().getFirstControlFlowNode()
}
/**
@@ -677,7 +677,7 @@ class Property extends @property, Documentable {
* For example, the property `@A @B x: 42` has
* `@A` as its 0th decorator, and `@B` as its first decorator.
*/
Decorator getDecorator(int i) { result = getChildExpr(-(i + 1)) }
Decorator getDecorator(int i) { result = this.getChildExpr(-(i + 1)) }
/**
* Gets a decorator applied to this property.
@@ -685,7 +685,7 @@ class Property extends @property, Documentable {
* For example, the property `@A @B x: 42` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
override string getAPrimaryQlClass() { result = "Property" }
}
@@ -774,7 +774,7 @@ class PropertySetter extends PropertyAccessor, @property_setter { }
* ```
*/
class SpreadProperty extends Property {
SpreadProperty() { not exists(getNameExpr()) }
SpreadProperty() { not exists(this.getNameExpr()) }
}
/**
@@ -834,7 +834,9 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function {
override predicate isImpure() { none() }
override Function getThisBinder() { result = getEnclosingContainer().(Function).getThisBinder() }
override Function getThisBinder() {
result = this.getEnclosingContainer().(Function).getThisBinder()
}
override string getAPrimaryQlClass() { result = "ArrowFunctionExpr" }
}
@@ -850,20 +852,20 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function {
*/
class SeqExpr extends @seq_expr, Expr {
/** Gets the `i`th expression in this sequence. */
Expr getOperand(int i) { result = getChildExpr(i) }
Expr getOperand(int i) { result = this.getChildExpr(i) }
/** Gets an expression in this sequence. */
Expr getAnOperand() { result = getOperand(_) }
Expr getAnOperand() { result = this.getOperand(_) }
/** Gets the number of expressions in this sequence. */
int getNumOperands() { result = count(getOperand(_)) }
int getNumOperands() { result = count(this.getOperand(_)) }
/** Gets the last expression in this sequence. */
Expr getLastOperand() { result = getOperand(getNumOperands() - 1) }
Expr getLastOperand() { result = this.getOperand(this.getNumOperands() - 1) }
override predicate isImpure() { getAnOperand().isImpure() }
override predicate isImpure() { this.getAnOperand().isImpure() }
override Expr getUnderlyingValue() { result = getLastOperand().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getLastOperand().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "SeqExpr" }
}
@@ -879,20 +881,20 @@ class SeqExpr extends @seq_expr, Expr {
*/
class ConditionalExpr extends @conditional_expr, Expr {
/** Gets the condition expression of this conditional. */
Expr getCondition() { result = getChildExpr(0) }
Expr getCondition() { result = this.getChildExpr(0) }
/** Gets the 'then' expression of this conditional. */
Expr getConsequent() { result = getChildExpr(1) }
Expr getConsequent() { result = this.getChildExpr(1) }
/** Gets the 'else' expression of this conditional. */
Expr getAlternate() { result = getChildExpr(2) }
Expr getAlternate() { result = this.getChildExpr(2) }
/** Gets either the 'then' or the 'else' expression of this conditional. */
Expr getABranch() { result = getConsequent() or result = getAlternate() }
Expr getABranch() { result = this.getConsequent() or result = this.getAlternate() }
override predicate isImpure() {
getCondition().isImpure() or
getABranch().isImpure()
this.getCondition().isImpure() or
this.getABranch().isImpure()
}
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
@@ -917,7 +919,7 @@ class InvokeExpr extends @invokeexpr, Expr {
/** Gets the name of the function or method being invoked, if it can be determined. */
string getCalleeName() {
exists(Expr callee | callee = getCallee().getUnderlyingValue() |
exists(Expr callee | callee = this.getCallee().getUnderlyingValue() |
result = callee.(Identifier).getName() or
result = callee.(PropAccess).getPropertyName()
)
@@ -927,25 +929,25 @@ class InvokeExpr extends @invokeexpr, Expr {
Expr getArgument(int i) { i >= 0 and result = this.getChildExpr(i) }
/** Gets an argument of this invocation. */
Expr getAnArgument() { result = getArgument(_) }
Expr getAnArgument() { result = this.getArgument(_) }
/** Gets the last argument of this invocation, if any. */
Expr getLastArgument() { result = getArgument(getNumArgument() - 1) }
Expr getLastArgument() { result = this.getArgument(this.getNumArgument() - 1) }
/** Gets the number of arguments of this invocation. */
int getNumArgument() { result = count(getAnArgument()) }
int getNumArgument() { result = count(this.getAnArgument()) }
/** Gets the `i`th type argument of this invocation. */
TypeExpr getTypeArgument(int i) { i >= 0 and result = this.getChildTypeExpr(-i - 2) }
/** Gets a type argument of this invocation. */
TypeExpr getATypeArgument() { result = getTypeArgument(_) }
TypeExpr getATypeArgument() { result = this.getTypeArgument(_) }
/** Gets the number of type arguments of this invocation. */
int getNumTypeArgument() { result = count(getATypeArgument()) }
int getNumTypeArgument() { result = count(this.getATypeArgument()) }
override ControlFlowNode getFirstControlFlowNode() {
result = getCallee().getFirstControlFlowNode()
result = this.getCallee().getFirstControlFlowNode()
}
/** Holds if the argument list of this function has a trailing comma. */
@@ -953,7 +955,7 @@ class InvokeExpr extends @invokeexpr, Expr {
// check whether the last token of this invocation is a closing
// parenthesis, which itself is preceded by a comma
exists(PunctuatorToken rparen | rparen.getValue() = ")" |
rparen = getLastToken() and
rparen = this.getLastToken() and
rparen.getPreviousToken().getValue() = ","
)
}
@@ -961,7 +963,7 @@ class InvokeExpr extends @invokeexpr, Expr {
/**
* Holds if the `i`th argument of this invocation is a spread element.
*/
predicate isSpreadArgument(int i) { getArgument(i).stripParens() instanceof SpreadElement }
predicate isSpreadArgument(int i) { this.getArgument(i).stripParens() instanceof SpreadElement }
/**
* Holds if the `i`th argument of this invocation is an object literal whose property
@@ -970,7 +972,7 @@ class InvokeExpr extends @invokeexpr, Expr {
* This predicate is an approximation, computed using only local data flow.
*/
predicate hasOptionArgument(int i, string name, Expr value) {
value = flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr()
value = this.flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr()
}
/**
@@ -1004,7 +1006,7 @@ class InvokeExpr extends @invokeexpr, Expr {
* Note that the resolved function may be overridden in a subclass and thus is not
* necessarily the actual target of this invocation at runtime.
*/
Function getResolvedCallee() { result = getResolvedCalleeName().getImplementation() }
Function getResolvedCallee() { result = this.getResolvedCalleeName().getImplementation() }
}
/**
@@ -1036,7 +1038,7 @@ class CallExpr extends @call_expr, InvokeExpr {
* Gets the expression specifying the receiver on which the function
* is invoked, if any.
*/
Expr getReceiver() { result = getCallee().(PropAccess).getBase() }
Expr getReceiver() { result = this.getCallee().(PropAccess).getBase() }
override string getAPrimaryQlClass() { result = "CallExpr" }
}
@@ -1052,25 +1054,25 @@ class CallExpr extends @call_expr, InvokeExpr {
* ```
*/
class MethodCallExpr extends CallExpr {
MethodCallExpr() { getCallee().stripParens() instanceof PropAccess }
MethodCallExpr() { this.getCallee().stripParens() instanceof PropAccess }
/**
* Gets the property access referencing the method to be invoked.
*/
private PropAccess getMethodRef() { result = getCallee().stripParens() }
private PropAccess getMethodRef() { result = this.getCallee().stripParens() }
/**
* Gets the receiver expression of this method call.
*/
override Expr getReceiver() { result = getMethodRef().getBase() }
override Expr getReceiver() { result = this.getMethodRef().getBase() }
/**
* Gets the name of the invoked method, if it can be determined.
*/
string getMethodName() { result = getMethodRef().getPropertyName() }
string getMethodName() { result = this.getMethodRef().getPropertyName() }
/** Holds if this invocation calls method `m` on expression `base`. */
predicate calls(Expr base, string m) { getMethodRef().accesses(base, m) }
predicate calls(Expr base, string m) { this.getMethodRef().accesses(base, m) }
override string getAPrimaryQlClass() { result = "MethodCallExpr" }
}
@@ -1088,14 +1090,14 @@ class MethodCallExpr extends CallExpr {
*/
class PropAccess extends @propaccess, Expr {
/** Gets the base expression on which the property is accessed. */
Expr getBase() { result = getChildExpr(0) }
Expr getBase() { result = this.getChildExpr(0) }
/**
* Gets the expression specifying the name of the property being
* read or written. For dot expressions, this is an identifier; for
* index expressions it can be an arbitrary expression.
*/
Expr getPropertyNameExpr() { result = getChildExpr(1) }
Expr getPropertyNameExpr() { result = this.getChildExpr(1) }
/** Gets the name of the accessed property, if it can be determined. */
string getPropertyName() { none() }
@@ -1103,21 +1105,21 @@ class PropAccess extends @propaccess, Expr {
/** Gets the qualified name of the accessed property, if it can be determined. */
string getQualifiedName() {
exists(string basename |
basename = getBase().(Identifier).getName() or
basename = getBase().(PropAccess).getQualifiedName()
basename = this.getBase().(Identifier).getName() or
basename = this.getBase().(PropAccess).getQualifiedName()
|
result = basename + "." + getPropertyName()
result = basename + "." + this.getPropertyName()
)
}
/** Holds if this property name accesses property `p` on expression `base`. */
predicate accesses(Expr base, string p) {
base = getBase() and
p = getPropertyName()
base = this.getBase() and
p = this.getPropertyName()
}
override ControlFlowNode getFirstControlFlowNode() {
result = getBase().getFirstControlFlowNode()
result = this.getBase().getFirstControlFlowNode()
}
override Expr getUnderlyingReference() { result = this }
@@ -1133,12 +1135,12 @@ class PropAccess extends @propaccess, Expr {
* ```
*/
class DotExpr extends @dot_expr, PropAccess {
override string getPropertyName() { result = getProperty().getName() }
override string getPropertyName() { result = this.getProperty().getName() }
/** Gets the identifier specifying the name of the accessed property. */
Identifier getProperty() { result = getChildExpr(1) }
Identifier getProperty() { result = this.getChildExpr(1) }
override predicate isImpure() { getBase().isImpure() }
override predicate isImpure() { this.getBase().isImpure() }
override string getAPrimaryQlClass() { result = "DotExpr" }
}
@@ -1154,13 +1156,13 @@ class DotExpr extends @dot_expr, PropAccess {
*/
class IndexExpr extends @index_expr, PropAccess {
/** Gets the expression specifying the name of the accessed property. */
Expr getIndex() { result = getChildExpr(1) }
Expr getIndex() { result = this.getChildExpr(1) }
override string getPropertyName() { result = getIndex().(Literal).getValue() }
override string getPropertyName() { result = this.getIndex().(Literal).getValue() }
override predicate isImpure() {
getBase().isImpure() or
getIndex().isImpure()
this.getBase().isImpure() or
this.getIndex().isImpure()
}
override string getAPrimaryQlClass() { result = "IndexExpr" }
@@ -1178,15 +1180,15 @@ class IndexExpr extends @index_expr, PropAccess {
*/
class UnaryExpr extends @unaryexpr, Expr {
/** Gets the operand of this unary operator. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Gets the operator of this expression. */
string getOperator() { none() }
override predicate isImpure() { getOperand().isImpure() }
override predicate isImpure() { this.getOperand().isImpure() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UnaryExpr" }
@@ -1204,7 +1206,7 @@ class UnaryExpr extends @unaryexpr, Expr {
class NegExpr extends @neg_expr, UnaryExpr {
override string getOperator() { result = "-" }
override int getIntValue() { result = -getOperand().getIntValue() }
override int getIntValue() { result = -this.getOperand().getIntValue() }
}
/**
@@ -1316,28 +1318,28 @@ class SpreadElement extends @spread_element, UnaryExpr {
*/
class BinaryExpr extends @binaryexpr, Expr {
/** Gets the left operand of this binary operator. */
Expr getLeftOperand() { result = getChildExpr(0) }
Expr getLeftOperand() { result = this.getChildExpr(0) }
/** Gets the right operand of this binary operator. */
Expr getRightOperand() { result = getChildExpr(1) }
Expr getRightOperand() { result = this.getChildExpr(1) }
/** Gets an operand of this binary operator. */
Expr getAnOperand() { result = getAChildExpr() }
Expr getAnOperand() { result = this.getAChildExpr() }
/** Holds if `e` and `f` (in either order) are the two operands of this expression. */
predicate hasOperands(Expr e, Expr f) {
e = getAnOperand() and
f = getAnOperand() and
e = this.getAnOperand() and
f = this.getAnOperand() and
e != f
}
/** Gets the operator of this expression. */
string getOperator() { none() }
override predicate isImpure() { getAnOperand().isImpure() }
override predicate isImpure() { this.getAnOperand().isImpure() }
override ControlFlowNode getFirstControlFlowNode() {
result = getLeftOperand().getFirstControlFlowNode()
result = this.getLeftOperand().getFirstControlFlowNode()
}
/**
@@ -1348,7 +1350,7 @@ class BinaryExpr extends @binaryexpr, Expr {
*/
int getWhitespaceAroundOperator() {
exists(Token lastLeft, Token operator, Token firstRight, int l, int c1, int c2, int c3, int c4 |
lastLeft = getLeftOperand().getLastToken() and
lastLeft = this.getLeftOperand().getLastToken() and
operator = lastLeft.getNextToken() and
firstRight = operator.getNextToken() and
lastLeft.getLocation().hasLocationInfo(_, _, _, l, c1) and
@@ -1889,15 +1891,17 @@ class ShiftExpr extends BinaryExpr {
*/
class Assignment extends @assignment, Expr {
/** Gets the left hand side of this assignment. */
Expr getLhs() { result = getChildExpr(0) }
Expr getLhs() { result = this.getChildExpr(0) }
/** Gets the right hand side of this assignment. */
Expr getRhs() { result = getChildExpr(1) }
Expr getRhs() { result = this.getChildExpr(1) }
/** Gets the variable or property this assignment writes to, if any. */
Expr getTarget() { result = getLhs().stripParens() }
Expr getTarget() { result = this.getLhs().stripParens() }
override ControlFlowNode getFirstControlFlowNode() { result = getLhs().getFirstControlFlowNode() }
override ControlFlowNode getFirstControlFlowNode() {
result = this.getLhs().getFirstControlFlowNode()
}
}
/**
@@ -1910,7 +1914,7 @@ class Assignment extends @assignment, Expr {
* ```
*/
class AssignExpr extends @assign_expr, Assignment {
override Expr getUnderlyingValue() { result = getRhs().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getRhs().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "AssignExpr" }
}
@@ -2126,7 +2130,7 @@ class AssignNullishCoalescingExpr extends @assignnullishcoalescingexpr, Compound
*/
class UpdateExpr extends @updateexpr, Expr {
/** Gets the operand of this update. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Holds if this is a prefix increment or prefix decrement expression. */
predicate isPrefix() { none() }
@@ -2135,7 +2139,7 @@ class UpdateExpr extends @updateexpr, Expr {
string getOperator() { none() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UpdateExpr" }
@@ -2208,7 +2212,7 @@ class PostDecExpr extends @postdec_expr, UpdateExpr {
*/
class YieldExpr extends @yield_expr, Expr {
/** Gets the operand of this `yield` expression. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Holds if this is a `yield*` expression. */
predicate isDelegating() { is_delegating(this) }
@@ -2216,9 +2220,9 @@ class YieldExpr extends @yield_expr, Expr {
override predicate isImpure() { any() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
or
not exists(getOperand()) and result = this
not exists(this.getOperand()) and result = this
}
override string getAPrimaryQlClass() { result = "YieldExpr" }
@@ -2239,45 +2243,47 @@ class ComprehensionExpr extends @comprehension_expr, Expr {
/** Gets the `n`th comprehension block in this comprehension. */
ComprehensionBlock getBlock(int n) {
exists(int idx |
result = getChildExpr(idx) and
result = this.getChildExpr(idx) and
idx > 0 and
n = idx - 1
)
}
/** Gets a comprehension block in this comprehension. */
ComprehensionBlock getABlock() { result = getBlock(_) }
ComprehensionBlock getABlock() { result = this.getBlock(_) }
/** Gets the number of comprehension blocks in this comprehension. */
int getNumBlock() { result = count(getABlock()) }
int getNumBlock() { result = count(this.getABlock()) }
/** Gets the `n`th filter expression in this comprehension. */
Expr getFilter(int n) {
exists(int idx |
result = getChildExpr(idx) and
result = this.getChildExpr(idx) and
idx < 0 and
n = -idx - 1
)
}
/** Gets a filter expression in this comprehension. */
Expr getAFilter() { result = getFilter(_) }
Expr getAFilter() { result = this.getFilter(_) }
/** Gets the number of filter expressions in this comprehension. */
int getNumFilter() { result = count(getAFilter()) }
int getNumFilter() { result = count(this.getAFilter()) }
/** Gets the body expression of this comprehension. */
Expr getBody() { result = getChildExpr(0) }
Expr getBody() { result = this.getChildExpr(0) }
override predicate isImpure() {
getABlock().isImpure() or
getAFilter().isImpure() or
getBody().isImpure()
this.getABlock().isImpure() or
this.getAFilter().isImpure() or
this.getBody().isImpure()
}
/** Holds if this is a legacy postfix comprehension expression. */
predicate isPostfix() {
exists(Token tk | tk = getFirstToken().getNextToken() | not tk.getValue().regexpMatch("if|for"))
exists(Token tk | tk = this.getFirstToken().getNextToken() |
not tk.getValue().regexpMatch("if|for")
)
}
override string getAPrimaryQlClass() { result = "ComprehensionExpr" }
@@ -2324,14 +2330,14 @@ class GeneratorExpr extends @generator_expr, ComprehensionExpr { }
*/
class ComprehensionBlock extends @comprehension_block, Expr {
/** Gets the iterating variable or pattern of this comprehension block. */
BindingPattern getIterator() { result = getChildExpr(0) }
BindingPattern getIterator() { result = this.getChildExpr(0) }
/** Gets the domain over which this comprehension block iterates. */
Expr getDomain() { result = getChildExpr(1) }
Expr getDomain() { result = this.getChildExpr(1) }
override predicate isImpure() {
getIterator().isImpure() or
getDomain().isImpure()
this.getIterator().isImpure() or
this.getDomain().isImpure()
}
override string getAPrimaryQlClass() { result = "ComprehensionBlock" }
@@ -2490,17 +2496,17 @@ class RelationalComparison extends Comparison {
*/
Expr getLesserOperand() {
(this instanceof LTExpr or this instanceof LEExpr) and
result = getLeftOperand()
result = this.getLeftOperand()
or
(this instanceof GTExpr or this instanceof GEExpr) and
result = getRightOperand()
result = this.getRightOperand()
}
/**
* Gets the greater operand of this comparison, that is, the right operand for
* a `<` or `<=` comparison, and the left operand for `>=` or `>`.
*/
Expr getGreaterOperand() { result = getAnOperand() and result != getLesserOperand() }
Expr getGreaterOperand() { result = this.getAnOperand() and result != this.getLesserOperand() }
/**
* Holds if this is a comparison with `<=` or `>=`.
@@ -2550,13 +2556,13 @@ class DecExpr extends UpdateExpr {
*/
class LegacyLetExpr extends Expr, @legacy_letexpr {
/** Gets the `i`th declarator in this `let` expression. */
VariableDeclarator getDecl(int i) { result = getChildExpr(i) and i >= 0 }
VariableDeclarator getDecl(int i) { result = this.getChildExpr(i) and i >= 0 }
/** Gets a declarator in this declaration expression. */
VariableDeclarator getADecl() { result = getDecl(_) }
VariableDeclarator getADecl() { result = this.getDecl(_) }
/** Gets the expression this `let` expression scopes over. */
Expr getBody() { result = getChildExpr(-1) }
Expr getBody() { result = this.getChildExpr(-1) }
override string getAPrimaryQlClass() { result = "LegacyLetExpr" }
}
@@ -2633,11 +2639,11 @@ class ImmediatelyInvokedFunctionExpr extends Function {
*/
predicate argumentPassing(Parameter p, Expr arg) {
exists(int parmIdx, int argIdx |
p = getParameter(parmIdx) and
p = this.getParameter(parmIdx) and
not p.isRestParameter() and
argIdx = parmIdx + getArgumentOffset() and
arg = getArgument(argIdx) and
not isSpreadArgument([0 .. argIdx])
argIdx = parmIdx + this.getArgumentOffset() and
arg = this.getArgument(argIdx) and
not this.isSpreadArgument([0 .. argIdx])
)
}
}
@@ -2653,12 +2659,12 @@ class ImmediatelyInvokedFunctionExpr extends Function {
*/
class AwaitExpr extends @await_expr, Expr {
/** Gets the operand of this `await` expression. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
override predicate isImpure() { any() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "AwaitExpr" }
@@ -2711,10 +2717,10 @@ class Decorator extends @decorator, Expr {
* For example, the decorator `@A` has expression `A`,
* and `@testable(true)` has expression `testable(true)`.
*/
Expr getExpression() { result = getChildExpr(0) }
Expr getExpression() { result = this.getChildExpr(0) }
override ControlFlowNode getFirstControlFlowNode() {
result = getExpression().getFirstControlFlowNode()
result = this.getExpression().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "Decorator" }
@@ -2774,15 +2780,15 @@ class FunctionBindExpr extends @bind_expr, Expr {
* Gets the object of this function bind expression; undefined for
* expressions of the form `::b.f`.
*/
Expr getObject() { result = getChildExpr(0) }
Expr getObject() { result = this.getChildExpr(0) }
/** Gets the callee of this function bind expression. */
Expr getCallee() { result = getChildExpr(1) }
Expr getCallee() { result = this.getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() {
result = getObject().getFirstControlFlowNode()
result = this.getObject().getFirstControlFlowNode()
or
not exists(getObject()) and result = getCallee().getFirstControlFlowNode()
not exists(this.getObject()) and result = this.getCallee().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "FunctionBindExpr" }
@@ -2799,15 +2805,15 @@ class FunctionBindExpr extends @bind_expr, Expr {
*/
class DynamicImportExpr extends @dynamic_import, Expr, Import {
/** Gets the expression specifying the path of the imported module. */
Expr getSource() { result = getChildExpr(0) }
Expr getSource() { result = this.getChildExpr(0) }
override ControlFlowNode getFirstControlFlowNode() {
result = getSource().getFirstControlFlowNode()
result = this.getSource().getFirstControlFlowNode()
}
override PathExpr getImportedPath() { result = getSource() }
override PathExpr getImportedPath() { result = this.getSource() }
override Module getEnclosingModule() { result = getTopLevel() }
override Module getEnclosingModule() { result = this.getTopLevel() }
override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) }
@@ -2820,7 +2826,7 @@ private class LiteralDynamicImportPath extends PathExpr, ConstantString {
exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource())
}
override string getValue() { result = getStringValue() }
override string getValue() { result = this.getStringValue() }
}
/**
@@ -2858,7 +2864,7 @@ class OptionalChainRoot extends ChainElem {
OptionalUse optionalUse;
OptionalChainRoot() {
getChainBase*() = optionalUse and
this.getChainBase*() = optionalUse and
not exists(ChainElem other | this = other.getChainBase())
}

View File

@@ -80,14 +80,14 @@ private predicate hasTypedefAnnotation(Stmt s) {
/** A typedef declaration in an externs file. */
class ExternalTypedef extends ExternalDecl, VariableDeclarator {
ExternalTypedef() {
getBindingPattern() instanceof Identifier and
inExternsFile() and
hasTypedefAnnotation(getDeclStmt())
this.getBindingPattern() instanceof Identifier and
this.inExternsFile() and
hasTypedefAnnotation(this.getDeclStmt())
}
override string getName() { result = getBindingPattern().(Identifier).getName() }
override string getName() { result = this.getBindingPattern().(Identifier).getName() }
override string getQualifiedName() { result = getName() }
override string getQualifiedName() { result = this.getName() }
}
/**
@@ -135,7 +135,7 @@ abstract class ExternalVarDecl extends ExternalDecl {
/**
* Gets the `@type` tag associated with this declaration, if any.
*/
ExternalTypeTag getTypeTag() { result = getATag() }
ExternalTypeTag getTypeTag() { result = this.getATag() }
}
/**
@@ -157,7 +157,7 @@ abstract class ExternalVarDecl extends ExternalDecl {
* </pre>
*/
abstract class ExternalGlobalDecl extends ExternalVarDecl {
override string getQualifiedName() { result = getName() }
override string getQualifiedName() { result = this.getName() }
}
/**
@@ -174,7 +174,7 @@ abstract class ExternalGlobalDecl extends ExternalVarDecl {
* </pre>
*/
class ExternalGlobalFunctionDecl extends ExternalGlobalDecl, FunctionDeclStmt {
ExternalGlobalFunctionDecl() { inExternsFile() }
ExternalGlobalFunctionDecl() { this.inExternsFile() }
/** Gets the name of this declaration. */
override string getName() { result = FunctionDeclStmt.super.getName() }
@@ -196,13 +196,13 @@ class ExternalGlobalFunctionDecl extends ExternalGlobalDecl, FunctionDeclStmt {
*/
class ExternalGlobalVarDecl extends ExternalGlobalDecl, VariableDeclarator {
ExternalGlobalVarDecl() {
getBindingPattern() instanceof Identifier and
inExternsFile() and
this.getBindingPattern() instanceof Identifier and
this.inExternsFile() and
// exclude type aliases
not hasTypedefAnnotation(getDeclStmt())
not hasTypedefAnnotation(this.getDeclStmt())
}
override string getName() { result = getBindingPattern().(Identifier).getName() }
override string getName() { result = this.getBindingPattern().(Identifier).getName() }
/** Gets the initializer associated with this declaration, if any. */
override Expr getInit() { result = VariableDeclarator.super.getInit() }
@@ -226,10 +226,10 @@ class ExternalGlobalVarDecl extends ExternalGlobalDecl, VariableDeclarator {
*/
class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
ExternalMemberDecl() {
getParent() instanceof Externs and
this.getParent() instanceof Externs and
(
getExpr() instanceof PropAccess or
getExpr().(AssignExpr).getLhs() instanceof PropAccess
this.getExpr() instanceof PropAccess or
this.getExpr().(AssignExpr).getLhs() instanceof PropAccess
)
}
@@ -237,20 +237,22 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
* Gets the property access describing the declared member.
*/
PropAccess getProperty() {
result = getExpr() or
result = getExpr().(AssignExpr).getLhs()
result = this.getExpr() or
result = this.getExpr().(AssignExpr).getLhs()
}
override Expr getInit() { result = getExpr().(AssignExpr).getRhs() }
override Expr getInit() { result = this.getExpr().(AssignExpr).getRhs() }
override string getQualifiedName() { result = getBaseName() + "." + getName() }
override string getQualifiedName() { result = this.getBaseName() + "." + this.getName() }
/**
* Holds if this member belongs to type `base` and has name `name`.
*/
predicate hasQualifiedName(string base, string name) { base = getBaseName() and name = getName() }
predicate hasQualifiedName(string base, string name) {
base = this.getBaseName() and name = this.getName()
}
override string getName() { result = getProperty().getPropertyName() }
override string getName() { result = this.getProperty().getPropertyName() }
/**
* Gets the name of the base type to which the member declared by this declaration belongs.
@@ -260,7 +262,7 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
/**
* Gets the base type to which the member declared by this declaration belongs.
*/
ExternalType getDeclaringType() { result.getQualifiedName() = getBaseName() }
ExternalType getDeclaringType() { result.getQualifiedName() = this.getBaseName() }
}
/**
@@ -282,9 +284,9 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
* </pre>
*/
class ExternalStaticMemberDecl extends ExternalMemberDecl {
ExternalStaticMemberDecl() { getProperty().getBase() instanceof Identifier }
ExternalStaticMemberDecl() { this.getProperty().getBase() instanceof Identifier }
override string getBaseName() { result = getProperty().getBase().(Identifier).getName() }
override string getBaseName() { result = this.getProperty().getBase().(Identifier).getName() }
}
/**
@@ -307,14 +309,16 @@ class ExternalStaticMemberDecl extends ExternalMemberDecl {
*/
class ExternalInstanceMemberDecl extends ExternalMemberDecl {
ExternalInstanceMemberDecl() {
exists(PropAccess outer, PropAccess inner | outer = getProperty() and inner = outer.getBase() |
exists(PropAccess outer, PropAccess inner |
outer = this.getProperty() and inner = outer.getBase()
|
inner.getBase() instanceof Identifier and
inner.getPropertyName() = "prototype"
)
}
override string getBaseName() {
result = getProperty().getBase().(PropAccess).getBase().(Identifier).getName()
result = this.getProperty().getBase().(PropAccess).getBase().(Identifier).getName()
}
}
@@ -360,7 +364,7 @@ class ExternalFunction extends ExternalEntity, Function {
predicate isVarArgs() {
exists(SimpleParameter lastParm, JSDocParamTag pt |
lastParm = this.getParameter(this.getNumParameter() - 1) and
pt = getDecl().getATag() and
pt = this.getDecl().getATag() and
pt.getName() = lastParm.getName() and
pt.getType() instanceof JSDocRestParameterTypeExpr
)
@@ -380,7 +384,7 @@ class ExternalFunction extends ExternalEntity, Function {
* </pre>
*/
class ConstructorTag extends JSDocTag {
ConstructorTag() { getTitle() = "constructor" }
ConstructorTag() { this.getTitle() = "constructor" }
}
/**
@@ -396,8 +400,8 @@ class ConstructorTag extends JSDocTag {
abstract private class NamedTypeReferent extends JSDocTag {
/** Gets the name of the type to which this tag refers. */
string getTarget() {
result = getType().(JSDocNamedTypeExpr).getName() or
result = getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName()
result = this.getType().(JSDocNamedTypeExpr).getName() or
result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName()
}
/**
@@ -412,7 +416,7 @@ abstract private class NamedTypeReferent extends JSDocTag {
* type `Array`, which is also the source declaration of `!Array=`. Primitive types,
* union types, and other complex kinds of types do not have a source declaration.
*/
ExternalType getTypeDeclaration() { result = sourceDecl(getType()) }
ExternalType getTypeDeclaration() { result = sourceDecl(this.getType()) }
}
/**
@@ -437,7 +441,7 @@ private ExternalType sourceDecl(JSDocTypeExpr tp) {
* </pre>
*/
class ImplementsTag extends NamedTypeReferent {
ImplementsTag() { getTitle() = "implements" }
ImplementsTag() { this.getTitle() = "implements" }
}
/**
@@ -451,7 +455,7 @@ class ImplementsTag extends NamedTypeReferent {
* </pre>
*/
class ExtendsTag extends NamedTypeReferent {
ExtendsTag() { getTitle() = "extends" }
ExtendsTag() { this.getTitle() = "extends" }
}
/**
@@ -465,7 +469,7 @@ class ExtendsTag extends NamedTypeReferent {
* </pre>
*/
class ExternalTypeTag extends NamedTypeReferent {
ExternalTypeTag() { getTitle() = "type" }
ExternalTypeTag() { this.getTitle() = "type" }
}
/**
@@ -489,16 +493,18 @@ class ExternalTypeTag extends NamedTypeReferent {
abstract class ExternalType extends ExternalGlobalFunctionDecl {
/** Gets a type which this type extends. */
ExternalType getAnExtendedType() {
getDocumentation().getATag().(ExtendsTag).getTarget() = result.getQualifiedName()
this.getDocumentation().getATag().(ExtendsTag).getTarget() = result.getQualifiedName()
}
/** Gets a type which this type implements. */
ExternalType getAnImplementedType() {
getDocumentation().getATag().(ImplementsTag).getTarget() = result.getQualifiedName()
this.getDocumentation().getATag().(ImplementsTag).getTarget() = result.getQualifiedName()
}
/** Gets a supertype of this type. */
ExternalType getASupertype() { result = getAnExtendedType() or result = getAnImplementedType() }
ExternalType getASupertype() {
result = this.getAnExtendedType() or result = this.getAnImplementedType()
}
/** Gets a declaration of a member of this type. */
ExternalMemberDecl getAMember() { result.getDeclaringType() = this }
@@ -518,7 +524,7 @@ abstract class ExternalType extends ExternalGlobalFunctionDecl {
* </pre>
*/
class ExternalConstructor extends ExternalType {
ExternalConstructor() { getDocumentation().getATag() instanceof ConstructorTag }
ExternalConstructor() { this.getDocumentation().getATag() instanceof ConstructorTag }
}
/**
@@ -534,7 +540,7 @@ class ExternalConstructor extends ExternalType {
* </pre>
*/
class ExternalInterface extends ExternalType {
ExternalInterface() { getDocumentation().getATag().getTitle() = "interface" }
ExternalInterface() { this.getDocumentation().getATag().getTitle() = "interface" }
}
/**
@@ -551,7 +557,7 @@ class ExternalInterface extends ExternalType {
* </pre>
*/
class FunctionExternal extends ExternalConstructor {
FunctionExternal() { getName() = "Function" }
FunctionExternal() { this.getName() = "Function" }
}
/**
@@ -568,7 +574,7 @@ class FunctionExternal extends ExternalConstructor {
* </pre>
*/
class ObjectExternal extends ExternalConstructor {
ObjectExternal() { getName() = "Object" }
ObjectExternal() { this.getName() = "Object" }
}
/**
@@ -586,5 +592,5 @@ class ObjectExternal extends ExternalConstructor {
* </pre>
*/
class ArrayExternal extends ExternalConstructor {
ArrayExternal() { getName() = "Array" }
ArrayExternal() { this.getName() = "Array" }
}

View File

@@ -48,7 +48,7 @@ abstract class Container extends @container {
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
@@ -74,7 +74,9 @@ abstract class Container extends @container {
* <tr><td>"//FileServer/"</td><td>""</td></tr>
* </table>
*/
string getBaseName() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1) }
string getBaseName() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1)
}
/**
* Gets the extension of this container, that is, the suffix of its base name
@@ -100,7 +102,7 @@ abstract class Container extends @container {
* </table>
*/
string getExtension() {
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4)
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4)
}
/**
@@ -120,7 +122,9 @@ abstract class Container extends @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 2) }
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 2)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() { containerparent(result, this) }
@@ -129,20 +133,20 @@ abstract class Container extends @container {
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = getAChildContainer() }
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = getAFile() and
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = getAChildContainer() }
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = getAFolder() and
result = this.getAFolder() and
result.getBaseName() = baseName
}
@@ -151,7 +155,7 @@ abstract class Container extends @container {
*
* This is the absolute path of the container.
*/
string toString() { result = getAbsolutePath() }
string toString() { result = this.getAbsolutePath() }
}
/** A folder. */
@@ -160,13 +164,13 @@ class Folder extends Container, @folder {
/** Gets the file or subfolder in this folder that has the given `name`, if any. */
Container getChildContainer(string name) {
result = getAChildContainer() and
result = this.getAChildContainer() and
result.getBaseName() = name
}
/** Gets the file in this folder that has the given `stem` and `extension`, if any. */
File getFile(string stem, string extension) {
result = getAChildContainer() and
result = this.getAChildContainer() and
result.getStem() = stem and
result.getExtension() = extension
}
@@ -184,14 +188,14 @@ class Folder extends Container, @folder {
*/
File getJavaScriptFile(string stem) {
result =
min(int p, string ext | p = getFileExtensionPriority(ext) | getFile(stem, ext) order by p)
min(int p, string ext | p = getFileExtensionPriority(ext) | this.getFile(stem, ext) order by p)
}
/** Gets a subfolder contained in this folder. */
Folder getASubFolder() { result = getAChildContainer() }
Folder getASubFolder() { result = this.getAChildContainer() }
/** Gets the URL of this folder. */
override string getURL() { result = "folder://" + getAbsolutePath() }
override string getURL() { result = "folder://" + this.getAbsolutePath() }
}
/** A file. */

View File

@@ -39,14 +39,14 @@ import javascript
class Function extends @function, Parameterized, TypeParameterized, StmtContainer, Documentable,
AST::ValueNode {
/** Gets the `i`th parameter of this function. */
Parameter getParameter(int i) { result = getChildExpr(i) }
Parameter getParameter(int i) { result = this.getChildExpr(i) }
/** Gets a parameter of this function. */
override Parameter getAParameter() { exists(int idx | result = getParameter(idx)) }
override Parameter getAParameter() { exists(int idx | result = this.getParameter(idx)) }
/** Gets the parameter named `name` of this function, if any. */
SimpleParameter getParameterByName(string name) {
result = getAParameter() and
result = this.getAParameter() and
result.getName() = name
}
@@ -72,9 +72,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* `this` parameter types are specific to TypeScript.
*/
TypeAnnotation getThisTypeAnnotation() {
result = getChildTypeExpr(-4)
result = this.getChildTypeExpr(-4)
or
result = getDocumentation().getATagByTitle("this").getType()
result = this.getDocumentation().getATagByTitle("this").getType()
}
/**
@@ -82,10 +82,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* Gets the identifier specifying the name of this function, if any.
*/
deprecated VarDecl getId() { result = getIdentifier() }
deprecated VarDecl getId() { result = this.getIdentifier() }
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getIdentifier() { result = getChildExpr(-1) }
VarDecl getIdentifier() { result = this.getChildExpr(-1) }
/**
* Gets the name of this function if it has one, or a name inferred from its context.
@@ -96,9 +96,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, there is no result.
*/
string getName() {
result = getIdentifier().getName()
result = this.getIdentifier().getName()
or
not exists(getIdentifier()) and
not exists(this.getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@@ -118,17 +118,17 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
}
/** Gets the variable holding this function. */
Variable getVariable() { result = getIdentifier().getVariable() }
Variable getVariable() { result = this.getIdentifier().getVariable() }
/** Gets the `arguments` variable of this function, if any. */
ArgumentsVariable getArgumentsVariable() { result.getFunction() = this }
/** Holds if the body of this function refers to the function's `arguments` variable. */
predicate usesArgumentsObject() {
exists(getArgumentsVariable().getAnAccess())
exists(this.getArgumentsVariable().getAnAccess())
or
exists(PropAccess read |
read.getBase() = getVariable().getAnAccess() and
read.getBase() = this.getVariable().getAnAccess() and
read.getPropertyName() = "arguments"
)
}
@@ -136,29 +136,31 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/**
* Holds if this function declares a parameter or local variable named `arguments`.
*/
predicate declaresArguments() { exists(getScope().getVariable("arguments").getADeclaration()) }
predicate declaresArguments() {
exists(this.getScope().getVariable("arguments").getADeclaration())
}
/** Gets the statement enclosing this function, if any. */
Stmt getEnclosingStmt() { none() }
/** Gets the body of this function. */
override ExprOrStmt getBody() { result = getChild(-2) }
override ExprOrStmt getBody() { result = this.getChild(-2) }
/** Gets the `i`th statement in the body of this function. */
Stmt getBodyStmt(int i) { result = getBody().(BlockStmt).getStmt(i) }
Stmt getBodyStmt(int i) { result = this.getBody().(BlockStmt).getStmt(i) }
/** Gets a statement in the body of this function. */
Stmt getABodyStmt() { result = getBodyStmt(_) }
Stmt getABodyStmt() { result = this.getBodyStmt(_) }
/** Gets the number of statements in the body of this function. */
int getNumBodyStmt() { result = count(getABodyStmt()) }
int getNumBodyStmt() { result = count(this.getABodyStmt()) }
/** Gets the return type annotation on this function, if any. */
TypeAnnotation getReturnTypeAnnotation() {
typeexprs(result, _, this, -3, _)
or
exists(string title | title = "return" or title = "returns" |
result = getDocumentation().getATagByTitle(title).getType()
result = this.getDocumentation().getATagByTitle(title).getType()
)
}
@@ -179,7 +181,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private Token lastTokenOfParameterList() {
// if there are any parameters, it's the last token of the last parameter
exists(Parameter lastParam | lastParam = getParameter(getNumParameter() - 1) |
exists(Parameter lastParam | lastParam = this.getParameter(this.getNumParameter() - 1) |
result = lastParam.getDefault().getLastToken()
or
not exists(lastParam.getDefault()) and result = lastParam.getLastToken()
@@ -187,32 +189,34 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
or
// otherwise we have an empty parameter list `()`, and
// we want to return the opening parenthesis
not exists(getAParameter()) and
not exists(this.getAParameter()) and
(
// if the function has a name, the opening parenthesis comes right after it
result = getIdentifier().getLastToken().getNextToken()
result = this.getIdentifier().getLastToken().getNextToken()
or
// otherwise this must be an arrow function with no parameters, so the opening
// parenthesis is the very first token of the function
not exists(getIdentifier()) and result = getFirstToken()
not exists(this.getIdentifier()) and result = this.getFirstToken()
)
}
/** Holds if the parameter list of this function has a trailing comma. */
predicate hasTrailingComma() { lastTokenOfParameterList().getNextToken().getValue() = "," }
predicate hasTrailingComma() { this.lastTokenOfParameterList().getNextToken().getValue() = "," }
/** Holds if this function is an asynchronous function. */
predicate isAsync() { is_async(this) }
/** Holds if this function is asynchronous or a generator. */
predicate isAsyncOrGenerator() { isAsync() or isGenerator() }
predicate isAsyncOrGenerator() { this.isAsync() or this.isGenerator() }
/** Gets the enclosing function or toplevel of this function. */
override StmtContainer getEnclosingContainer() { result = getEnclosingStmt().getContainer() }
override StmtContainer getEnclosingContainer() { result = this.getEnclosingStmt().getContainer() }
/** Gets the number of lines in this function. */
int getNumberOfLines() {
exists(int sl, int el | getLocation().hasLocationInfo(_, sl, _, el, _) | result = el - sl + 1)
exists(int sl, int el | this.getLocation().hasLocationInfo(_, sl, _, el, _) |
result = el - sl + 1
)
}
/** Gets the number of lines containing code in this function. */
@@ -247,8 +251,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/** Gets an expression that could be returned by this function, if any. */
Expr getAReturnedExpr() {
result = getBody() or
result = getAReturnStmt().getExpr()
result = this.getBody() or
result = this.getAReturnStmt().getExpr()
}
/**
@@ -262,10 +266,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* which is the nearest enclosing non-arrow function or top-level.
*/
StmtContainer getThisBindingContainer() {
result = getThisBinder()
result = this.getThisBinder()
or
not exists(getThisBinder()) and
result = getTopLevel()
not exists(this.getThisBinder()) and
result = this.getTopLevel()
}
/**
@@ -276,12 +280,12 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* parameter, no parameter default values, and no destructuring parameters.
*/
predicate hasMappedArgumentsVariable() {
exists(getArgumentsVariable()) and
not isStrict() and
forall(Parameter p | p = getAParameter() |
exists(this.getArgumentsVariable()) and
not this.isStrict() and
forall(Parameter p | p = this.getAParameter() |
p instanceof SimpleParameter and not exists(p.getDefault())
) and
not hasRestParameter()
not this.hasRestParameter()
}
/**
@@ -293,23 +297,23 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, the result is "anonymous function".
*/
override string describe() {
if exists(inferNameFromVarDef())
then result = inferNameFromVarDef()
if exists(this.inferNameFromVarDef())
then result = this.inferNameFromVarDef()
else
if exists(inferNameFromProp())
then result = inferNameFromProp()
if exists(this.inferNameFromProp())
then result = this.inferNameFromProp()
else
if exists(inferNameFromMemberDef())
then result = inferNameFromMemberDef()
if exists(this.inferNameFromMemberDef())
then result = this.inferNameFromMemberDef()
else
if exists(inferNameFromCallSig())
then result = inferNameFromCallSig()
if exists(this.inferNameFromCallSig())
then result = this.inferNameFromCallSig()
else
if exists(inferNameFromIndexSig())
then result = inferNameFromIndexSig()
if exists(this.inferNameFromIndexSig())
then result = this.inferNameFromIndexSig()
else
if exists(inferNameFromFunctionType())
then result = inferNameFromFunctionType()
if exists(this.inferNameFromFunctionType())
then result = this.inferNameFromFunctionType()
else result = "anonymous function"
}
@@ -319,8 +323,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `var f = function g() {}`, prefer `g` to `f`
if exists(getIdentifier())
then result = "function " + getIdentifier().getName()
if exists(this.getIdentifier())
then result = "function " + this.getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "function " + vd.getTarget().(VarRef).getName()
@@ -400,7 +404,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* A JavaScript function always has a body.
*/
predicate hasBody() { exists(getBody()) }
predicate hasBody() { exists(this.getBody()) }
/**
* Holds if this function is part of an abstract class member.
@@ -419,10 +423,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
this instanceof ArrowFunctionExpr and
kind = "an arrow function"
or
isGenerator() and
this.isGenerator() and
kind = "a generator function"
or
isAsync() and
this.isAsync() and
kind = "an async function"
}

View File

@@ -80,7 +80,7 @@ module AccessPath {
SsaExplicitDefinition getSsaDefinition() { result.getSourceVariable() = this }
/** Gets the data flow node representing the value of this variable, if one exists. */
DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() }
DataFlow::Node getValue() { result = this.getSsaDefinition().getRhsNode() }
}
/**

View File

@@ -94,13 +94,13 @@ module InclusionTest {
*/
private class Includes_Native extends Range, DataFlow::MethodCallNode {
Includes_Native() {
getMethodName() = "includes" and
getNumArgument() = 1
this.getMethodName() = "includes" and
this.getNumArgument() = 1
}
override DataFlow::Node getContainerNode() { result = getReceiver() }
override DataFlow::Node getContainerNode() { result = this.getReceiver() }
override DataFlow::Node getContainedNode() { result = getArgument(0) }
override DataFlow::Node getContainedNode() { result = this.getArgument(0) }
}
/**
@@ -117,9 +117,9 @@ module InclusionTest {
)
}
override DataFlow::Node getContainerNode() { result = getArgument(0) }
override DataFlow::Node getContainerNode() { result = this.getArgument(0) }
override DataFlow::Node getContainedNode() { result = getArgument(1) }
override DataFlow::Node getContainedNode() { result = this.getArgument(1) }
}
/**

View File

@@ -38,7 +38,7 @@ private class PlainJsonParserCall extends JsonParserCall {
)
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = this }
}
@@ -61,7 +61,7 @@ private class JsonParserCallWithWrapper extends JsonParserCall {
)
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = this.getAPropertyRead(outputPropName) }
}
@@ -74,9 +74,9 @@ private class JsonParserCallWithCallback extends JsonParserCall {
this = DataFlow::moduleImport("safe-json-parse/callback").getACall()
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = getCallback(1).getParameter(1) }
override DataFlow::SourceNode getOutput() { result = this.getCallback(1).getParameter(1) }
}
/**

View File

@@ -25,7 +25,7 @@ module JsonSchema {
* Gets a value that indicates whether the validation was successful.
*/
DataFlow::Node getAValidationResultAccess(boolean polarity) {
result = this and polarity = getPolarity()
result = this and polarity = this.getPolarity()
}
}
@@ -35,7 +35,7 @@ module JsonSchema {
/** An object literal with a `$schema` property indicating it is the root of a JSON schema. */
private class SchemaNodeByTag extends SchemaRoot, DataFlow::ObjectLiteralNode {
SchemaNodeByTag() {
getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%")
this.getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%")
}
}
@@ -67,13 +67,13 @@ module JsonSchema {
Instance() { this = API::moduleImport("ajv").getAnInstantiation() }
/** Gets the data flow node holding the options passed to this `Ajv` instance. */
DataFlow::Node getOptionsArg() { result = getArgument(0) }
DataFlow::Node getOptionsArg() { result = this.getArgument(0) }
/** Gets an API node that refers to this object. */
API::Node ref() {
result = getReturn()
result = this.getReturn()
or
result = ref().getMember(chainedMethod()).getReturn()
result = this.ref().getMember(chainedMethod()).getReturn()
}
/**
@@ -83,16 +83,16 @@ module JsonSchema {
* signature is different.
*/
API::Node getAValidationFunction() {
result = ref().getMember(["compile", "getSchema"]).getReturn()
result = this.ref().getMember(["compile", "getSchema"]).getReturn()
or
result = ref().getMember("compileAsync").getPromised()
result = this.ref().getMember("compileAsync").getPromised()
}
/**
* Gets an API node that refers to an error produced by this Ajv instance.
*/
API::Node getAValidationError() {
exists(API::Node base | base = [ref(), getAValidationFunction()] |
exists(API::Node base | base = [this.ref(), this.getAValidationFunction()] |
result = base.getMember("errors")
or
result = base.getMember("errorsText").getReturn()
@@ -111,14 +111,14 @@ module JsonSchema {
this = instance.getAValidationFunction().getACall() and argIndex = 0
}
override DataFlow::Node getInput() { result = getArgument(argIndex) }
override DataFlow::Node getInput() { result = this.getArgument(argIndex) }
/** Gets the argument holding additional options to the call. */
DataFlow::Node getOwnOptionsArg() { result = getArgument(argIndex + 1) }
DataFlow::Node getOwnOptionsArg() { result = this.getArgument(argIndex + 1) }
/** Gets a data flow passed as the extra options to this validation call or to the underlying `Ajv` instance. */
DataFlow::Node getAnOptionsArg() {
result = getOwnOptionsArg()
result = this.getOwnOptionsArg()
or
result = instance.getOptionsArg()
}

View File

@@ -25,7 +25,7 @@ class Location extends @location {
int getEndColumn() { locations_default(this, _, _, _, _, result) }
/** Gets the number of lines covered by this location. */
int getNumLines() { result = getEndLine() - getStartLine() + 1 }
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
/** Holds if this location starts before location `that`. */
pragma[inline]
@@ -85,7 +85,7 @@ class Location extends @location {
/** A program element with a location. */
class Locatable extends @locatable {
/** Gets the file this program element comes from. */
File getFile() { result = getLocation().getFile() }
File getFile() { result = this.getLocation().getFile() }
/** Gets this element's location. */
Location getLocation() {
@@ -124,7 +124,7 @@ class Locatable extends @locatable {
}
/** Gets the number of lines covered by this element. */
int getNumLines() { result = getLocation().getNumLines() }
int getNumLines() { result = this.getLocation().getNumLines() }
/** Gets a textual representation of this element. */
string toString() {
@@ -135,7 +135,7 @@ class Locatable extends @locatable {
/**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/
final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
/**
* Gets the primary QL class for the Locatable.

View File

@@ -13,19 +13,19 @@ private import semmle.javascript.internal.CachedStages
*/
abstract class Module extends TopLevel {
/** Gets the full path of the file containing this module. */
string getPath() { result = getFile().getAbsolutePath() }
string getPath() { result = this.getFile().getAbsolutePath() }
/** Gets the short name of this module without file extension. */
string getName() { result = getFile().getStem() }
string getName() { result = this.getFile().getStem() }
/** Gets an import appearing in this module. */
Import getAnImport() { result.getTopLevel() = this }
/** Gets a module from which this module imports. */
Module getAnImportedModule() { result = getAnImport().getImportedModule() }
Module getAnImportedModule() { result = this.getAnImport().getImportedModule() }
/** Gets a symbol exported by this module. */
string getAnExportedSymbol() { exists(getAnExportedValue(result)) }
string getAnExportedSymbol() { exists(this.getAnExportedValue(result)) }
/**
* DEPRECATED. Use `getAnExportedValue` instead.
@@ -86,7 +86,7 @@ abstract class Module extends TopLevel {
exists(PropAccess pacc | export = pacc |
pacc.getBase() = this.(NodeModule).getAModuleExportsNode().asExpr() and
name = pacc.getPropertyName() and
isExterns() and
this.isExterns() and
exists(pacc.getDocumentation())
)
)
@@ -125,7 +125,7 @@ abstract class Module extends TopLevel {
* as the interaction between different module types is not standardized.
*/
DataFlow::Node getDefaultOrBulkExport() {
result = [getAnExportedValue("default"), getABulkExportedNode()]
result = [this.getAnExportedValue("default"), this.getABulkExportedNode()]
}
/**
@@ -144,7 +144,7 @@ abstract class Module extends TopLevel {
exists(string v | v = path.getValue() |
// paths starting with a dot are resolved relative to the module's directory
if v.matches(".%")
then searchRoot = getFile().getParentContainer()
then searchRoot = this.getFile().getParentContainer()
else
// all other paths are resolved relative to the file system root
searchRoot.getBaseName() = ""
@@ -202,14 +202,14 @@ abstract class Import extends ASTNode {
* path is assumed to be a possible target of the import.
*/
Module resolveExternsImport() {
result.isExterns() and result.getName() = getImportedPath().getValue()
result.isExterns() and result.getName() = this.getImportedPath().getValue()
}
/**
* Gets the module the path of this import resolves to.
*/
Module resolveImportedPath() {
result.getFile() = getEnclosingModule().resolve(getImportedPath())
result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath())
}
/**
@@ -220,7 +220,7 @@ abstract class Import extends ASTNode {
exists(JSDocTag tag |
tag.getTitle() = "providesModule" and
tag.getParent().getComment().getTopLevel() = result and
tag.getDescription().trim() = getImportedPath().getValue()
tag.getDescription().trim() = this.getImportedPath().getValue()
)
}
@@ -231,9 +231,9 @@ abstract class Import extends ASTNode {
result.getFile() =
min(TypeRootFolder typeRoot |
|
typeRoot.getModuleFile(getImportedPath().getValue())
typeRoot.getModuleFile(this.getImportedPath().getValue())
order by
typeRoot.getSearchPriority(getFile().getParentContainer())
typeRoot.getSearchPriority(this.getFile().getParentContainer())
)
}
@@ -258,13 +258,13 @@ abstract class Import extends ASTNode {
cached
Module getImportedModule() {
Stages::Imports::ref() and
if exists(resolveExternsImport())
then result = resolveExternsImport()
if exists(this.resolveExternsImport())
then result = this.resolveExternsImport()
else (
result = resolveAsProvidedModule() or
result = resolveImportedPath() or
result = resolveFromTypeRoot() or
result = resolveFromTypeScriptSymbol() or
result = this.resolveAsProvidedModule() or
result = this.resolveImportedPath() or
result = this.resolveFromTypeRoot() or
result = this.resolveFromTypeScriptSymbol() or
result = resolveNeighbourPackage(this.getImportedPath().getValue())
)
}

View File

@@ -8,91 +8,95 @@ private import NodeModuleResolutionImpl
/** A `package.json` configuration object. */
class PackageJSON extends JSONObject {
PackageJSON() {
getJsonFile().getBaseName() = "package.json" and
isTopLevel()
this.getJsonFile().getBaseName() = "package.json" and
this.isTopLevel()
}
/** Gets the name of this package. */
string getPackageName() { result = getPropStringValue("name") }
string getPackageName() { result = this.getPropStringValue("name") }
/** Gets the version of this package. */
string getVersion() { result = getPropStringValue("version") }
string getVersion() { result = this.getPropStringValue("version") }
/** Gets the description of this package. */
string getDescription() { result = getPropStringValue("description") }
string getDescription() { result = this.getPropStringValue("description") }
/** Gets the array of keywords for this package. */
JSONArray getKeywords() { result = getPropValue("keywords") }
JSONArray getKeywords() { result = this.getPropValue("keywords") }
/** Gets a keyword for this package. */
string getAKeyword() { result = getKeywords().getElementStringValue(_) }
string getAKeyword() { result = this.getKeywords().getElementStringValue(_) }
/** Gets the homepage URL of this package. */
string getHomepage() { result = getPropStringValue("homepage") }
string getHomepage() { result = this.getPropStringValue("homepage") }
/** Gets the bug tracker information of this package. */
BugTrackerInfo getBugs() { result = getPropValue("bugs") }
BugTrackerInfo getBugs() { result = this.getPropValue("bugs") }
/** Gets the license information of this package. */
string getLicense() { result = getPropStringValue("license") }
string getLicense() { result = this.getPropStringValue("license") }
/** Gets the author information of this package. */
ContributorInfo getAuthor() { result = getPropValue("author") }
ContributorInfo getAuthor() { result = this.getPropValue("author") }
/** Gets information for a contributor to this package. */
ContributorInfo getAContributor() { result = getPropValue("contributors").getElementValue(_) }
ContributorInfo getAContributor() {
result = this.getPropValue("contributors").getElementValue(_)
}
/** Gets the array of files for this package. */
JSONArray getFiles() { result = getPropValue("files") }
JSONArray getFiles() { result = this.getPropValue("files") }
/** Gets a file for this package. */
string getAFile() { result = getFiles().getElementStringValue(_) }
string getAFile() { result = this.getFiles().getElementStringValue(_) }
/** Gets the main module of this package. */
string getMain() { result = MainModulePath::of(this).getValue() }
/** Gets the path of a command defined for this package. */
string getBin(string cmd) {
cmd = getPackageName() and result = getPropStringValue("bin")
cmd = this.getPackageName() and result = this.getPropStringValue("bin")
or
result = getPropValue("bin").getPropValue(cmd).getStringValue()
result = this.getPropValue("bin").getPropValue(cmd).getStringValue()
}
/** Gets a manual page for this package. */
string getAManFile() {
result = getPropStringValue("man") or
result = getPropValue("man").getElementValue(_).getStringValue()
result = this.getPropStringValue("man") or
result = this.getPropValue("man").getElementValue(_).getStringValue()
}
/** Gets information about the directories of this package. */
JSONObject getDirectories() { result = getPropValue("directories") }
JSONObject getDirectories() { result = this.getPropValue("directories") }
/** Gets repository information for this package. */
RepositoryInfo getRepository() { result = getPropValue("repository") }
RepositoryInfo getRepository() { result = this.getPropValue("repository") }
/** Gets information about the scripts of this package. */
JSONObject getScripts() { result = getPropValue("scripts") }
JSONObject getScripts() { result = this.getPropValue("scripts") }
/** Gets configuration information for this package. */
JSONObject getConfig() { result = getPropValue("config") }
JSONObject getConfig() { result = this.getPropValue("config") }
/** Gets the dependencies of this package. */
PackageDependencies getDependencies() { result = getPropValue("dependencies") }
PackageDependencies getDependencies() { result = this.getPropValue("dependencies") }
/** Gets the development dependencies of this package. */
PackageDependencies getDevDependencies() { result = getPropValue("devDependencies") }
PackageDependencies getDevDependencies() { result = this.getPropValue("devDependencies") }
/** Gets the peer dependencies of this package. */
PackageDependencies getPeerDependencies() { result = getPropValue("peerDependencies") }
PackageDependencies getPeerDependencies() { result = this.getPropValue("peerDependencies") }
/** Gets the bundled dependencies of this package. */
PackageDependencies getBundledDependencies() {
result = getPropValue("bundledDependencies") or
result = getPropValue("bundleDependencies")
result = this.getPropValue("bundledDependencies") or
result = this.getPropValue("bundleDependencies")
}
/** Gets the optional dependencies of this package. */
PackageDependencies getOptionalDependencies() { result = getPropValue("optionalDependencies") }
PackageDependencies getOptionalDependencies() {
result = this.getPropValue("optionalDependencies")
}
/**
* Gets a JSON object describing a group of dependencies of
@@ -102,13 +106,13 @@ class PackageJSON extends JSONObject {
* `optionalDependencies`.
*/
PackageDependencies getADependenciesObject(string depkind) {
result = getDependencies() and depkind = ""
result = this.getDependencies() and depkind = ""
or
result = getDevDependencies() and depkind = "dev"
result = this.getDevDependencies() and depkind = "dev"
or
result = getBundledDependencies() and depkind = "bundled"
result = this.getBundledDependencies() and depkind = "bundled"
or
result = getOptionalDependencies() and depkind = "opt"
result = this.getOptionalDependencies() and depkind = "opt"
}
/**
@@ -120,55 +124,55 @@ class PackageJSON extends JSONObject {
* different from the other dependency types.
*/
predicate declaresDependency(string pkg, string version) {
getADependenciesObject(_).getADependency(pkg, version)
this.getADependenciesObject(_).getADependency(pkg, version)
}
/** Gets the engine dependencies of this package. */
PackageDependencies getEngines() { result = getPropValue("engines") }
PackageDependencies getEngines() { result = this.getPropValue("engines") }
/** Holds if this package has strict engine requirements. */
predicate isEngineStrict() { getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
predicate isEngineStrict() { this.getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
/** Gets information about operating systems supported by this package. */
JSONArray getOSs() { result = getPropValue("os") }
JSONArray getOSs() { result = this.getPropValue("os") }
/** Gets an operating system supported by this package. */
string getWhitelistedOS() {
result = getOSs().getElementStringValue(_) and
result = this.getOSs().getElementStringValue(_) and
not result.matches("!%")
}
/** Gets an operating system not supported by this package. */
string getBlacklistedOS() {
exists(string str | str = getOSs().getElementStringValue(_) |
exists(string str | str = this.getOSs().getElementStringValue(_) |
result = str.regexpCapture("!(.*)", 1)
)
}
/** Gets information about platforms supported by this package. */
JSONArray getCPUs() { result = getPropValue("cpu") }
JSONArray getCPUs() { result = this.getPropValue("cpu") }
/** Gets a platform supported by this package. */
string getWhitelistedCPU() {
result = getCPUs().getElementStringValue(_) and
result = this.getCPUs().getElementStringValue(_) and
not result.matches("!%")
}
/** Gets a platform not supported by this package. */
string getBlacklistedCPU() {
exists(string str | str = getCPUs().getElementStringValue(_) |
exists(string str | str = this.getCPUs().getElementStringValue(_) |
result = str.regexpCapture("!(.*)", 1)
)
}
/** Holds if this package prefers to be installed globally. */
predicate isPreferGlobal() { getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
/** Holds if this is a private package. */
predicate isPrivate() { getPropValue("private").(JSONBoolean).getValue() = "true" }
predicate isPrivate() { this.getPropValue("private").(JSONBoolean).getValue() = "true" }
/** Gets publishing configuration information about this package. */
JSONValue getPublishConfig() { result = getPropValue("publishConfig") }
JSONValue getPublishConfig() { result = this.getPropValue("publishConfig") }
/**
* Gets the main module of this package.
@@ -221,19 +225,19 @@ class ContributorInfo extends JSONValue {
/** Gets the contributor's name. */
string getName() {
result = this.getPropValue("name").getStringValue() or
result = parseInfo(1)
result = this.parseInfo(1)
}
/** Gets the contributor's email address. */
string getEmail() {
result = this.getPropValue("email").getStringValue() or
result = parseInfo(2)
result = this.parseInfo(2)
}
/** Gets the contributor's homepage URL. */
string getUrl() {
result = this.getPropValue("url").getStringValue() or
result = parseInfo(3)
result = this.parseInfo(3)
}
}
@@ -244,10 +248,10 @@ class RepositoryInfo extends JSONObject {
RepositoryInfo() { exists(PackageJSON pkg | this = pkg.getPropValue("repository")) }
/** Gets the repository type. */
string getType() { result = getPropStringValue("type") }
string getType() { result = this.getPropStringValue("type") }
/** Gets the repository URL. */
string getUrl() { result = getPropStringValue("url") }
string getUrl() { result = this.getPropStringValue("url") }
}
/**
@@ -262,7 +266,7 @@ class PackageDependencies extends JSONObject {
}
/** Holds if this package depends on version 'version' of package 'pkg'. */
predicate getADependency(string pkg, string version) { version = getPropStringValue(pkg) }
predicate getADependency(string pkg, string version) { version = this.getPropStringValue(pkg) }
}
/**
@@ -284,7 +288,7 @@ class NPMPackage extends @folder {
PackageJSON getPackageJSON() { result = pkg }
/** Gets the name of this package. */
string getPackageName() { result = getPackageJSON().getPackageName() }
string getPackageName() { result = this.getPackageJSON().getPackageName() }
/** Gets the `node_modules` folder of this package. */
Folder getNodeModulesFolder() {
@@ -308,7 +312,7 @@ class NPMPackage extends @folder {
* and modules inside the `node_modules` folder of a package are not
* considered to belong to that package.
*/
Module getAModule() { result.getFile() = getAFile() }
Module getAModule() { result.getFile() = this.getAFile() }
/**
* Gets the main module of this package.

View File

@@ -21,10 +21,10 @@ class NodeModule extends Module {
}
/** Gets the `module` variable of this module. */
Variable getModuleVariable() { result = getScope().getVariable("module") }
Variable getModuleVariable() { result = this.getScope().getVariable("module") }
/** Gets the `exports` variable of this module. */
Variable getExportsVariable() { result = getScope().getVariable("exports") }
Variable getExportsVariable() { result = this.getScope().getVariable("exports") }
/** Gets the scope induced by this module. */
override ModuleScope getScope() { result.getScopeElement() = this }
@@ -35,7 +35,7 @@ class NodeModule extends Module {
*/
pragma[noinline]
DefiniteAbstractValue getAModuleExportsValue() {
result = getAModuleExportsProperty().getAValue()
result = this.getAModuleExportsProperty().getAValue()
}
pragma[noinline]
@@ -51,14 +51,14 @@ class NodeModule extends Module {
*/
DataFlow::AnalyzedNode getAModuleExportsNode() {
result = getAModuleExportsCandidate() and
result.getAValue() = getAModuleExportsValue()
result.getAValue() = this.getAModuleExportsValue()
}
/** Gets a symbol exported by this module. */
override string getAnExportedSymbol() {
result = super.getAnExportedSymbol()
or
result = getAnImplicitlyExportedSymbol()
result = this.getAnImplicitlyExportedSymbol()
or
// getters and the like.
exists(DataFlow::PropWrite pwn |
@@ -70,12 +70,12 @@ class NodeModule extends Module {
override DataFlow::Node getAnExportedValue(string name) {
// a property write whose base is `exports` or `module.exports`
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
pwn.getBase() = getAModuleExportsNode() and
pwn.getBase() = this.getAModuleExportsNode() and
name = pwn.getPropertyName()
)
or
// a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};`
exists(ObjectExpr obj | obj = getAModuleExportsNode().asExpr() |
exists(ObjectExpr obj | obj = this.getAModuleExportsNode().asExpr() |
result =
obj.getAProperty()
.(SpreadProperty)
@@ -92,16 +92,16 @@ class NodeModule extends Module {
or
// an externs definition (where appropriate)
exists(PropAccess pacc | result = DataFlow::valueNode(pacc) |
pacc.getBase() = getAModuleExportsNode().asExpr() and
pacc.getBase() = this.getAModuleExportsNode().asExpr() and
name = pacc.getPropertyName() and
isExterns() and
this.isExterns() and
exists(pacc.getDocumentation())
)
}
override DataFlow::Node getABulkExportedNode() {
exists(DataFlow::PropWrite write |
write.getBase().asExpr() = getModuleVariable().getAnAccess() and
write.getBase().asExpr() = this.getModuleVariable().getAnAccess() and
write.getPropertyName() = "exports" and
result = write.getRhs()
)
@@ -109,7 +109,7 @@ class NodeModule extends Module {
/** Gets a symbol that the module object inherits from its prototypes. */
private string getAnImplicitlyExportedSymbol() {
exists(ExternalConstructor ec | ec = getPrototypeOfExportedExpr() |
exists(ExternalConstructor ec | ec = this.getPrototypeOfExportedExpr() |
result = ec.getAMember().getName()
or
ec instanceof FunctionExternal and result = "prototype"
@@ -121,7 +121,7 @@ class NodeModule extends Module {
/** Gets an externs declaration of the prototype object of a value exported by this module. */
private ExternalConstructor getPrototypeOfExportedExpr() {
exists(AbstractValue exported | exported = getAModuleExportsValue() |
exists(AbstractValue exported | exported = this.getAModuleExportsValue() |
result instanceof ObjectExternal
or
exported instanceof AbstractFunction and result instanceof FunctionExternal
@@ -136,7 +136,7 @@ class NodeModule extends Module {
// paths starting with `./` or `../` are resolved relative to the importing
// module's folder
pathval.regexpMatch("\\.\\.?(/.*)?") and
(searchRoot = getFile().getParentContainer() and priority = 0)
(searchRoot = this.getFile().getParentContainer() and priority = 0)
or
// paths starting with `/` are resolved relative to the file system root
pathval.matches("/%") and
@@ -145,7 +145,7 @@ class NodeModule extends Module {
// paths that do not start with `./`, `../` or `/` are resolved relative
// to `node_modules` folders
not pathval.regexpMatch("\\.\\.?(/.*)?|/.*") and
findNodeModulesFolder(getFile().getParentContainer(), searchRoot, priority)
findNodeModulesFolder(this.getFile().getParentContainer(), searchRoot, priority)
)
}
}
@@ -277,16 +277,16 @@ private predicate isRequire(DataFlow::Node nd) {
* ```
*/
class Require extends CallExpr, Import {
Require() { isRequire(getCallee().flow()) }
Require() { isRequire(this.getCallee().flow()) }
override PathExpr getImportedPath() { result = getArgument(0) }
override PathExpr getImportedPath() { result = this.getArgument(0) }
override Module getEnclosingModule() { this = result.getAnImport() }
override Module resolveImportedPath() {
moduleInFile(result, load(min(int prio | moduleInFile(_, load(prio)))))
moduleInFile(result, this.load(min(int prio | moduleInFile(_, this.load(prio)))))
or
not exists(Module mod | moduleInFile(mod, load(_))) and
not exists(Module mod | moduleInFile(mod, this.load(_))) and
result = Import.super.resolveImportedPath()
}
@@ -296,7 +296,7 @@ class Require extends CallExpr, Import {
* The result can be a JavaScript file, a JSON file or a `.node` file.
* Externs files are not treated differently from other files by this predicate.
*/
File getImportedFile() { result = load(min(int prio | exists(load(prio)))) }
File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) }
/**
* Gets the file that this `require` refers to (which may not be a JavaScript file),
@@ -354,7 +354,7 @@ class Require extends CallExpr, Import {
* `.js`, `.json` and `.node`.
*/
private File load(int priority) {
exists(int r | getEnclosingModule().searchRoot(getImportedPath(), _, r) |
exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPath(), _, r) |
result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or
result =
loadAsDirectory(this, r,
@@ -382,27 +382,27 @@ private class RequirePath extends PathExprCandidate {
private class ConstantRequirePathElement extends PathExpr, ConstantString {
ConstantRequirePathElement() { this = any(RequirePath rp).getAPart() }
override string getValue() { result = getStringValue() }
override string getValue() { result = this.getStringValue() }
}
/** A `__dirname` path expression. */
private class DirNamePath extends PathExpr, VarAccess {
DirNamePath() {
getName() = "__dirname" and
getVariable().getScope() instanceof ModuleScope
this.getName() = "__dirname" and
this.getVariable().getScope() instanceof ModuleScope
}
override string getValue() { result = getFile().getParentContainer().getAbsolutePath() }
override string getValue() { result = this.getFile().getParentContainer().getAbsolutePath() }
}
/** A `__filename` path expression. */
private class FileNamePath extends PathExpr, VarAccess {
FileNamePath() {
getName() = "__filename" and
getVariable().getScope() instanceof ModuleScope
this.getName() = "__filename" and
this.getVariable().getScope() instanceof ModuleScope
}
override string getValue() { result = getFile().getAbsolutePath() }
override string getValue() { result = this.getFile().getAbsolutePath() }
}
/**

View File

@@ -113,7 +113,7 @@ abstract class PathString extends string {
string getComponent(int i) { result = this.splitAt("/", i) }
/** Gets the number of components of this path. */
int getNumComponent() { result = count(int i | exists(getComponent(i))) }
int getNumComponent() { result = count(int i | exists(this.getComponent(i))) }
/** Gets the base name of the folder or file this path refers to. */
string getBaseName() { result = this.regexpCapture(pathRegex(), 2) }
@@ -147,7 +147,7 @@ abstract class PathString extends string {
* Gets the absolute path that this path refers to when resolved relative to
* `root`.
*/
Path resolve(Folder root) { result = resolveUpTo(getNumComponent(), root) }
Path resolve(Folder root) { result = this.resolveUpTo(this.getNumComponent(), root) }
}
/**
@@ -306,9 +306,9 @@ abstract class PathExpr extends Locatable {
/** Gets the root folder of priority `priority` associated with this path expression. */
Folder getSearchRoot(int priority) {
// We default to the enclosing module's search root, though this may be overridden.
getEnclosingModule().searchRoot(this, result, priority)
this.getEnclosingModule().searchRoot(this, result, priority)
or
result = getAdditionalSearchRoot(priority)
result = this.getAdditionalSearchRoot(priority)
}
/**
@@ -320,16 +320,16 @@ abstract class PathExpr extends Locatable {
Folder getAdditionalSearchRoot(int priority) { none() }
/** Gets the `i`th component of this path. */
string getComponent(int i) { result = getValue().(PathString).getComponent(i) }
string getComponent(int i) { result = this.getValue().(PathString).getComponent(i) }
/** Gets the number of components of this path. */
int getNumComponent() { result = getValue().(PathString).getNumComponent() }
int getNumComponent() { result = this.getValue().(PathString).getNumComponent() }
/** Gets the base name of the folder or file this path refers to. */
string getBaseName() { result = getValue().(PathString).getBaseName() }
string getBaseName() { result = this.getValue().(PathString).getBaseName() }
/** Gets the stem, that is, base name without extension, of the folder or file this path refers to. */
string getStem() { result = getValue().(PathString).getStem() }
string getStem() { result = this.getValue().(PathString).getStem() }
/**
* Gets the extension of the folder or file this path refers to, that is, the suffix of the base name
@@ -337,7 +337,7 @@ abstract class PathExpr extends Locatable {
*
* Has no result if the base name does not contain a dot.
*/
string getExtension() { result = getValue().(PathString).getExtension() }
string getExtension() { result = this.getValue().(PathString).getExtension() }
/**
* Gets the file or folder that the first `n` components of this path refer to
@@ -345,22 +345,25 @@ abstract class PathExpr extends Locatable {
*/
pragma[nomagic]
Container resolveUpTo(int n, int priority) {
result = getValue().(PathString).resolveUpTo(n, getSearchRoot(priority)).getContainer()
result =
this.getValue().(PathString).resolveUpTo(n, this.getSearchRoot(priority)).getContainer()
}
/**
* Gets the file or folder that this path refers to when resolved relative to
* the root folder of the given `priority`.
*/
Container resolve(int priority) { result = resolveUpTo(getNumComponent(), priority) }
Container resolve(int priority) { result = this.resolveUpTo(this.getNumComponent(), priority) }
/**
* Gets the file or folder that the first `n` components of this path refer to.
*/
Container resolveUpTo(int n) { result = resolveUpTo(n, min(int p | exists(resolveUpTo(n, p)))) }
Container resolveUpTo(int n) {
result = this.resolveUpTo(n, min(int p | exists(this.resolveUpTo(n, p))))
}
/** Gets the file or folder that this path refers to. */
Container resolve() { result = resolveUpTo(getNumComponent()) }
Container resolve() { result = this.resolveUpTo(this.getNumComponent()) }
/** Gets the module containing this path expression, if any. */
Module getEnclosingModule() {
@@ -418,5 +421,5 @@ abstract class PathExprCandidate extends Expr {
* `ConstantString`s).
*/
pragma[nomagic]
Expr getAPart() { result = this or result = getAPart().getAChildExpr() }
Expr getAPart() { result = this or result = this.getAPart().getAChildExpr() }
}

View File

@@ -98,7 +98,7 @@ class PrintAstNode extends TPrintAstNode {
/**
* Gets a child of this node.
*/
final PrintAstNode getAChild() { result = getChild(_) }
final PrintAstNode getAChild() { result = this.getChild(_) }
/**
* Gets the parent of this node, if any.
@@ -116,7 +116,7 @@ class PrintAstNode extends TPrintAstNode {
*/
string getProperty(string key) {
key = "semmle.label" and
result = toString()
result = this.toString()
}
/**
@@ -125,7 +125,7 @@ class PrintAstNode extends TPrintAstNode {
* this.
*/
string getChildEdgeLabel(int childIndex) {
exists(getChild(childIndex)) and
exists(this.getChild(childIndex)) and
result = childIndex.toString()
}
}

View File

@@ -13,14 +13,14 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
abstract DataFlow::FunctionNode getExecutor();
/** Gets the `resolve` parameter of the executor function. */
DataFlow::ParameterNode getResolveParameter() { result = getExecutor().getParameter(0) }
DataFlow::ParameterNode getResolveParameter() { result = this.getExecutor().getParameter(0) }
/** Gets the `reject` parameter of the executor function. */
DataFlow::ParameterNode getRejectParameter() { result = getExecutor().getParameter(1) }
DataFlow::ParameterNode getRejectParameter() { result = this.getExecutor().getParameter(1) }
/** Gets the `i`th callback handler installed by method `m`. */
private DataFlow::FunctionNode getAHandler(string m, int i) {
result = getAMethodCall(m).getCallback(i)
result = this.getAMethodCall(m).getCallback(i)
}
/**
@@ -28,8 +28,8 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
* `then` handlers and `finally` handlers.
*/
DataFlow::FunctionNode getAResolveHandler() {
result = getAHandler("then", 0) or
result = getAFinallyHandler()
result = this.getAHandler("then", 0) or
result = this.getAFinallyHandler()
}
/**
@@ -37,20 +37,20 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
* `then` handlers, `catch` handlers and `finally` handlers.
*/
DataFlow::FunctionNode getARejectHandler() {
result = getAHandler("then", 1) or
result = getACatchHandler() or
result = getAFinallyHandler()
result = this.getAHandler("then", 1) or
result = this.getACatchHandler() or
result = this.getAFinallyHandler()
}
/**
* Gets a `catch` handler of this promise.
*/
DataFlow::FunctionNode getACatchHandler() { result = getAHandler("catch", 0) }
DataFlow::FunctionNode getACatchHandler() { result = this.getAHandler("catch", 0) }
/**
* Gets a `finally` handler of this promise.
*/
DataFlow::FunctionNode getAFinallyHandler() { result = getAHandler("finally", 0) }
DataFlow::FunctionNode getAFinallyHandler() { result = this.getAHandler("finally", 0) }
}
/** Holds if the `i`th callback handler is installed by method `m`. */
@@ -115,7 +115,7 @@ class PromiseCandidate extends DataFlow::InvokeNode {
private class ES2015PromiseDefinition extends PromiseDefinition, DataFlow::InvokeNode {
ES2015PromiseDefinition() { this = getAPromiseObject().getAnInvocation() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -149,7 +149,7 @@ abstract class PromiseAllCreation extends PromiseCreationCall {
class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
ResolvedES2015PromiseDefinition() { this = getAPromiseObject().getAMemberCall("resolve") }
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**
@@ -165,7 +165,7 @@ class AggregateES2015PromiseDefinition extends PromiseCreationCall {
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
@@ -175,7 +175,7 @@ class AggregateES2015PromiseDefinition extends PromiseCreationCall {
class ES2015PromiseAllDefinition extends AggregateES2015PromiseDefinition, PromiseAllCreation {
ES2015PromiseAllDefinition() { this.getCalleeName() = "all" }
override DataFlow::Node getArrayNode() { result = getArgument(0) }
override DataFlow::Node getArrayNode() { result = this.getArgument(0) }
}
/**
@@ -185,12 +185,12 @@ module Promises {
/**
* Gets the pseudo-field used to describe resolved values in a promise.
*/
string valueProp() { result = "$PromiseResolveField$" }
string valueProp() { none() }
/**
* Gets the pseudo-field used to describe rejected values in a promise.
*/
string errorProp() { result = "$PromiseRejectField$" }
string errorProp() { none() }
}
/**
@@ -556,7 +556,7 @@ module Bluebird {
private class BluebirdPromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
BluebirdPromiseDefinition() { this = bluebird().getAnInstantiation() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -565,7 +565,7 @@ module Bluebird {
class ResolvedBluebidPromiseDefinition extends ResolvedPromiseDefinition {
ResolvedBluebidPromiseDefinition() { this = bluebird().getAMemberCall("resolve") }
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**
@@ -577,7 +577,7 @@ module Bluebird {
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
@@ -587,7 +587,7 @@ module Bluebird {
class BluebirdPromiseAllDefinition extends AggregateBluebirdPromiseDefinition, PromiseAllCreation {
BluebirdPromiseAllDefinition() { this.getCalleeName() = "all" }
override DataFlow::Node getArrayNode() { result = getArgument(0) }
override DataFlow::Node getArrayNode() { result = this.getArgument(0) }
}
/**
@@ -601,7 +601,7 @@ module Bluebird {
BluebirdCoroutineDefinition {
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
boundArgs = 0 and
callback = getArgument(0) and
callback = this.getArgument(0) and
result = this
}
}
@@ -617,7 +617,7 @@ module Q {
private class QPromiseDefinition extends PromiseDefinition, DataFlow::CallNode {
QPromiseDefinition() { this = DataFlow::moduleMember(["q", "kew"], "Promise").getACall() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
}
@@ -628,7 +628,7 @@ private module ClosurePromise {
private class ClosurePromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
ClosurePromiseDefinition() { this = Closure::moduleImport("goog.Promise").getACall() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -640,7 +640,7 @@ private module ClosurePromise {
this = Closure::moduleImport("goog.Promise.resolve").getACall()
}
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**

View File

@@ -49,13 +49,13 @@ class RegExpTerm extends Locatable, @regexpterm {
RegExpTerm getChild(int i) { regexpterm(result, _, this, i, _) }
/** Gets a child term of this term. */
RegExpTerm getAChild() { result = getChild(_) }
RegExpTerm getAChild() { result = this.getChild(_) }
/** Gets the number of child terms of this term. */
int getNumChild() { result = count(getAChild()) }
int getNumChild() { result = count(this.getAChild()) }
/** Gets the last child term of this term. */
RegExpTerm getLastChild() { result = getChild(getNumChild() - 1) }
RegExpTerm getLastChild() { result = this.getChild(this.getNumChild() - 1) }
/**
* Gets the parent term of this regular expression term, or the
@@ -64,7 +64,7 @@ class RegExpTerm extends Locatable, @regexpterm {
RegExpParent getParent() { regexpterm(this, _, result, _, _) }
/** Gets the regular expression literal this term belongs to, if any. */
RegExpLiteral getLiteral() { result = getRootTerm().getParent() }
RegExpLiteral getLiteral() { result = this.getRootTerm().getParent() }
override string toString() { regexpterm(this, _, _, _, result) }
@@ -76,7 +76,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/** Gets the regular expression term that is matched (textually) before this one, if any. */
RegExpTerm getPredecessor() {
exists(RegExpTerm parent | parent = getParent() |
exists(RegExpTerm parent | parent = this.getParent() |
result = parent.(RegExpSequence).previousElement(this)
or
not exists(parent.(RegExpSequence).previousElement(this)) and
@@ -87,7 +87,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/** Gets the regular expression term that is matched (textually) after this one, if any. */
RegExpTerm getSuccessor() {
exists(RegExpTerm parent | parent = getParent() |
exists(RegExpTerm parent | parent = this.getParent() |
result = parent.(RegExpSequence).nextElement(this)
or
not exists(parent.(RegExpSequence).nextElement(this)) and
@@ -100,7 +100,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* Holds if this regular term is in a forward-matching context, that is,
* it has no enclosing lookbehind assertions.
*/
predicate isInForwardMatchingContext() { not isInBackwardMatchingContext() }
predicate isInForwardMatchingContext() { not this.isInBackwardMatchingContext() }
/**
* Holds if this regular term is in a backward-matching context, that is,
@@ -111,22 +111,22 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Holds if this is the root term of a regular expression.
*/
predicate isRootTerm() { not getParent() instanceof RegExpTerm }
predicate isRootTerm() { not this.getParent() instanceof RegExpTerm }
/**
* Gets the outermost term of this regular expression.
*/
RegExpTerm getRootTerm() {
isRootTerm() and
this.isRootTerm() and
result = this
or
result = getParent().(RegExpTerm).getRootTerm()
result = this.getParent().(RegExpTerm).getRootTerm()
}
/**
* Holds if this term occurs as part of a regular expression literal.
*/
predicate isPartOfRegExpLiteral() { exists(getLiteral()) }
predicate isPartOfRegExpLiteral() { exists(this.getLiteral()) }
/**
* Holds if this term occurs as part of a string literal.
@@ -134,7 +134,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* This predicate holds regardless of whether the string literal is actually
* used as a regular expression. See `isUsedAsRegExp`.
*/
predicate isPartOfStringLiteral() { getRootTerm().getParent() instanceof StringLiteral }
predicate isPartOfStringLiteral() { this.getRootTerm().getParent() instanceof StringLiteral }
/**
* Holds if this term is part of a regular expression literal, or a string literal
@@ -153,7 +153,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* ```
*/
predicate isUsedAsRegExp() {
exists(RegExpParent parent | parent = getRootTerm().getParent() |
exists(RegExpParent parent | parent = this.getRootTerm().getParent() |
parent instanceof RegExpLiteral
or
parent.(Expr).flow() instanceof RegExpPatternSource
@@ -175,7 +175,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Gets a string that is matched by this regular-expression term.
*/
string getAMatchedString() { result = getConstantValue() }
string getAMatchedString() { result = this.getConstantValue() }
}
/**
@@ -242,7 +242,7 @@ class RegExpConstant extends RegExpTerm, @regexp_constant {
override predicate isNullable() { none() }
override string getConstantValue() { result = getValue() }
override string getConstantValue() { result = this.getValue() }
override string getAPrimaryQlClass() { result = "RegExpConstant" }
}
@@ -260,8 +260,8 @@ class RegExpCharEscape extends RegExpEscape, RegExpConstant, @regexp_char_escape
override predicate isCharacter() {
not (
// unencodable characters are represented as '?' or \uFFFD in the database
getValue() = ["?", 65533.toUnicode()] and
exists(string s | s = toString().toLowerCase() |
this.getValue() = ["?", 65533.toUnicode()] and
exists(string s | s = this.toString().toLowerCase() |
// only Unicode escapes give rise to unencodable characters
s.matches("\\\\u%") and
// but '\u003f' actually is the '?' character itself
@@ -284,14 +284,14 @@ class RegExpCharEscape extends RegExpEscape, RegExpConstant, @regexp_char_escape
*/
class RegExpAlt extends RegExpTerm, @regexp_alt {
/** Gets an alternative of this term. */
RegExpTerm getAlternative() { result = getAChild() }
RegExpTerm getAlternative() { result = this.getAChild() }
/** Gets the number of alternatives of this term. */
int getNumAlternative() { result = getNumChild() }
int getNumAlternative() { result = this.getNumChild() }
override predicate isNullable() { getAlternative().isNullable() }
override predicate isNullable() { this.getAlternative().isNullable() }
override string getAMatchedString() { result = getAlternative().getAMatchedString() }
override string getAMatchedString() { result = this.getAlternative().getAMatchedString() }
override string getAPrimaryQlClass() { result = "RegExpAlt" }
}
@@ -309,30 +309,30 @@ class RegExpAlt extends RegExpTerm, @regexp_alt {
*/
class RegExpSequence extends RegExpTerm, @regexp_seq {
/** Gets an element of this sequence. */
RegExpTerm getElement() { result = getAChild() }
RegExpTerm getElement() { result = this.getAChild() }
/** Gets the number of elements in this sequence. */
int getNumElement() { result = getNumChild() }
int getNumElement() { result = this.getNumChild() }
override predicate isNullable() {
forall(RegExpTerm child | child = getAChild() | child.isNullable())
forall(RegExpTerm child | child = this.getAChild() | child.isNullable())
}
override string getConstantValue() { result = getConstantValue(0) }
override string getConstantValue() { result = this.getConstantValue(0) }
/**
* Gets the single string matched by the `i`th child and all following children of
* this sequence, if any.
*/
private string getConstantValue(int i) {
i = getNumChild() and
i = this.getNumChild() and
result = ""
or
result = getChild(i).getConstantValue() + getConstantValue(i + 1)
result = this.getChild(i).getConstantValue() + this.getConstantValue(i + 1)
}
/** Gets the element preceding `element` in this sequence. */
RegExpTerm previousElement(RegExpTerm element) { element = nextElement(result) }
RegExpTerm previousElement(RegExpTerm element) { element = this.nextElement(result) }
/** Gets the element following `element` in this sequence. */
RegExpTerm nextElement(RegExpTerm element) {
@@ -431,7 +431,7 @@ class RegExpNonWordBoundary extends RegExpTerm, @regexp_nonwordboundary {
*/
class RegExpSubPattern extends RegExpTerm, @regexp_subpattern {
/** Gets the lookahead term. */
RegExpTerm getOperand() { result = getAChild() }
RegExpTerm getOperand() { result = this.getAChild() }
override predicate isNullable() { any() }
}
@@ -541,7 +541,7 @@ class RegExpStar extends RegExpQuantifier, @regexp_star {
* ```
*/
class RegExpPlus extends RegExpQuantifier, @regexp_plus {
override predicate isNullable() { getAChild().isNullable() }
override predicate isNullable() { this.getAChild().isNullable() }
override string getAPrimaryQlClass() { result = "RegExpPlus" }
}
@@ -586,8 +586,8 @@ class RegExpRange extends RegExpQuantifier, @regexp_range {
int getUpperBound() { range_quantifier_upper_bound(this, result) }
override predicate isNullable() {
getAChild().isNullable() or
getLowerBound() = 0
this.getAChild().isNullable() or
this.getLowerBound() = 0
}
override string getAPrimaryQlClass() { result = "RegExpRange" }
@@ -640,11 +640,11 @@ class RegExpGroup extends RegExpTerm, @regexp_group {
/** Gets the name of this capture group, if any. */
string getName() { is_named_capture(this, result) }
override predicate isNullable() { getAChild().isNullable() }
override predicate isNullable() { this.getAChild().isNullable() }
override string getConstantValue() { result = getAChild().getConstantValue() }
override string getConstantValue() { result = this.getAChild().getConstantValue() }
override string getAMatchedString() { result = getAChild().getAMatchedString() }
override string getAMatchedString() { result = this.getAChild().getAMatchedString() }
override string getAPrimaryQlClass() { result = "RegExpGroup" }
}
@@ -832,7 +832,7 @@ class RegExpBackRef extends RegExpTerm, @regexp_backref {
)
}
override predicate isNullable() { getGroup().isNullable() }
override predicate isNullable() { this.getGroup().isNullable() }
override string getAPrimaryQlClass() { result = "RegExpBackRef" }
}
@@ -854,7 +854,7 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
override predicate isNullable() { none() }
override string getAMatchedString() {
not isInverted() and result = getAChild().getAMatchedString()
not this.isInverted() and result = this.getAChild().getAMatchedString()
}
/**
@@ -862,13 +862,13 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
*/
predicate isUniversalClass() {
// [^]
isInverted() and not exists(getAChild())
this.isInverted() and not exists(this.getAChild())
or
// [\w\W] and similar
not isInverted() and
not this.isInverted() and
exists(string cce1, string cce2 |
cce1 = getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = getAChild().(RegExpCharacterClassEscape).getValue()
cce1 = this.getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = this.getAChild().(RegExpCharacterClassEscape).getValue()
|
cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase()
)
@@ -891,8 +891,8 @@ class RegExpCharacterRange extends RegExpTerm, @regexp_char_range {
/** Holds if `lo` is the lower bound of this character range and `hi` the upper bound. */
predicate isRange(string lo, string hi) {
lo = getChild(0).(RegExpConstant).getValue() and
hi = getChild(1).(RegExpConstant).getValue()
lo = this.getChild(0).(RegExpConstant).getValue() and
hi = this.getChild(1).(RegExpConstant).getValue()
}
override string getAPrimaryQlClass() { result = "RegExpCharacterRange" }
@@ -904,11 +904,11 @@ class RegExpParseError extends Error, @regexp_parse_error {
RegExpTerm getTerm() { regexp_parse_errors(this, result, _) }
/** Gets the regular expression literal in which the parse error occurred. */
RegExpLiteral getLiteral() { result = getTerm().getLiteral() }
RegExpLiteral getLiteral() { result = this.getTerm().getLiteral() }
override string getMessage() { regexp_parse_errors(this, _, result) }
override string toString() { result = getMessage() }
override string toString() { result = this.getMessage() }
override predicate isFatal() { none() }
}
@@ -1102,9 +1102,9 @@ private class StringRegExpPatternSource extends RegExpPatternSource {
)
}
override string getPattern() { result = getStringValue() }
override string getPattern() { result = this.getStringValue() }
override RegExpTerm getRegExpTerm() { result = asExpr().(StringLiteral).asRegExp() }
override RegExpTerm getRegExpTerm() { result = this.asExpr().(StringLiteral).asRegExp() }
}
/**
@@ -1126,9 +1126,9 @@ private class StringConcatRegExpPatternSource extends RegExpPatternSource {
)
}
override string getPattern() { result = getStringValue() }
override string getPattern() { result = this.getStringValue() }
override RegExpTerm getRegExpTerm() { result = asExpr().(AddExpr).asRegExp() }
override RegExpTerm getRegExpTerm() { result = this.asExpr().(AddExpr).asRegExp() }
}
module RegExp {

View File

@@ -9,18 +9,18 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
CallToObjectDefineProperty() {
exists(GlobalVariable obj |
obj.getName() = "Object" and
calls(DataFlow::valueNode(obj.getAnAccess()), "defineProperty")
this.calls(DataFlow::valueNode(obj.getAnAccess()), "defineProperty")
)
}
/** Gets the data flow node denoting the object on which the property is defined. */
DataFlow::Node getBaseObject() { result = getArgument(0) }
DataFlow::Node getBaseObject() { result = this.getArgument(0) }
/** Gets the name of the property being defined, if it can be determined. */
string getPropertyName() { result = getArgument(1).getStringValue() }
string getPropertyName() { result = this.getArgument(1).getStringValue() }
/** Gets the data flow node denoting the descriptor of the property being defined. */
DataFlow::Node getPropertyDescriptor() { result = getArgument(2) }
DataFlow::Node getPropertyDescriptor() { result = this.getArgument(2) }
/**
* Holds if there is an assignment to property `name` to the
@@ -29,7 +29,7 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
*/
predicate hasPropertyAttributeWrite(string name, DataFlow::Node rhs) {
exists(DataFlow::SourceNode descriptor |
descriptor.flowsTo(getPropertyDescriptor()) and
descriptor.flowsTo(this.getPropertyDescriptor()) and
descriptor.hasPropertyWrite(name, rhs)
)
}
@@ -39,10 +39,10 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
* A direct call to `eval`.
*/
class DirectEval extends CallExpr {
DirectEval() { getCallee().(GlobalVarAccess).getName() = "eval" }
DirectEval() { this.getCallee().(GlobalVarAccess).getName() = "eval" }
/** Holds if this call could affect the value of `lv`. */
predicate mayAffect(LocalVariable lv) { getParent+() = lv.getScope().getScopeElement() }
predicate mayAffect(LocalVariable lv) { this.getParent+() = lv.getScope().getScopeElement() }
}
/**
@@ -52,15 +52,15 @@ class DirectEval extends CallExpr {
private class ArrayIterationCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode::Range,
DataFlow::MethodCallNode {
ArrayIterationCallbackAsPartialInvoke() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
// Filter out library methods named 'forEach' etc
not DataFlow::moduleImport(_).flowsTo(getReceiver()) and
getMethodName() = ["filter", "forEach", "map", "some", "every"]
not DataFlow::moduleImport(_).flowsTo(this.getReceiver()) and
this.getMethodName() = ["filter", "forEach", "map", "some", "every"]
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(0) and
result = getArgument(1)
callback = this.getArgument(0) and
result = this.getArgument(1)
}
}
@@ -86,48 +86,48 @@ private class IteratorExceptionStep extends DataFlow::SharedFlowStep {
*/
class StringReplaceCall extends DataFlow::MethodCallNode {
StringReplaceCall() {
getMethodName() = ["replace", "replaceAll"] and
(getNumArgument() = 2 or getReceiver().mayHaveStringValue(_))
this.getMethodName() = ["replace", "replaceAll"] and
(this.getNumArgument() = 2 or this.getReceiver().mayHaveStringValue(_))
}
/** Gets the regular expression passed as the first argument to `replace`, if any. */
DataFlow::RegExpCreationNode getRegExp() { result.flowsTo(getArgument(0)) }
DataFlow::RegExpCreationNode getRegExp() { result.flowsTo(this.getArgument(0)) }
/** Gets a string that is being replaced by this call. */
string getAReplacedString() {
result = getRegExp().getRoot().getAMatchedString() or
getArgument(0).mayHaveStringValue(result)
result = this.getRegExp().getRoot().getAMatchedString() or
this.getArgument(0).mayHaveStringValue(result)
}
/**
* Gets the second argument of this call to `replace`, which is either a string
* or a callback.
*/
DataFlow::Node getRawReplacement() { result = getArgument(1) }
DataFlow::Node getRawReplacement() { result = this.getArgument(1) }
/**
* Gets a function flowing into the second argument of this call to `replace`.
*/
DataFlow::FunctionNode getReplacementCallback() { result = getCallback(1) }
DataFlow::FunctionNode getReplacementCallback() { result = this.getCallback(1) }
/**
* Holds if this is a global replacement, that is, the first argument is a regular expression
* with the `g` flag, or this is a call to `.replaceAll()`.
*/
predicate isGlobal() { getRegExp().isGlobal() or getMethodName() = "replaceAll" }
predicate isGlobal() { this.getRegExp().isGlobal() or this.getMethodName() = "replaceAll" }
/**
* Holds if this call to `replace` replaces `old` with `new`.
*/
predicate replaces(string old, string new) {
exists(string rawNew |
old = getAReplacedString() and
getRawReplacement().mayHaveStringValue(rawNew) and
old = this.getAReplacedString() and
this.getRawReplacement().mayHaveStringValue(rawNew) and
new = rawNew.replaceAll("$&", old)
)
or
exists(DataFlow::FunctionNode replacer, DataFlow::PropRead pr, DataFlow::ObjectLiteralNode map |
replacer = getCallback(1) and
replacer = this.getCallback(1) and
replacer.getParameter(0).flowsToExpr(pr.getPropertyNameExpr()) and
pr = map.getAPropertyRead() and
pr.flowsTo(replacer.getAReturn()) and
@@ -143,7 +143,7 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
DataFlow::FunctionNode replacer, ConditionGuardNode guard, EqualityTest test,
DataFlow::Node ret
|
replacer = getCallback(1) and
replacer = this.getCallback(1) and
guard.getOutcome() = test.getPolarity() and
guard.getTest() = test and
replacer.getParameter(0).flowsToExpr(test.getAnOperand()) and
@@ -164,27 +164,31 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
class StringSplitCall extends DataFlow::MethodCallNode {
StringSplitCall() {
this.getMethodName() = "split" and
(getNumArgument() = [1, 2] or getReceiver().mayHaveStringValue(_))
(this.getNumArgument() = [1, 2] or this.getReceiver().mayHaveStringValue(_))
}
/**
* Gets a string that determines where the string is split.
*/
string getSeparator() {
getArgument(0).mayHaveStringValue(result)
this.getArgument(0).mayHaveStringValue(result)
or
result =
getArgument(0).getALocalSource().(DataFlow::RegExpCreationNode).getRoot().getAMatchedString()
this.getArgument(0)
.getALocalSource()
.(DataFlow::RegExpCreationNode)
.getRoot()
.getAMatchedString()
}
/**
* Gets the DataFlow::Node for the base string that is split.
*/
DataFlow::Node getBaseString() { result = getReceiver() }
DataFlow::Node getBaseString() { result = this.getReceiver() }
/**
* Gets a read of the `i`th element from the split string.
*/
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = getAPropertyRead(i.toString()) }
DataFlow::Node getASubstringRead(int i) { result = this.getAPropertyRead(i.toString()) }
}

View File

@@ -20,8 +20,8 @@ import javascript
class Stmt extends @stmt, ExprOrStmt, Documentable {
/** Holds if this statement has an implicitly inserted semicolon. */
predicate hasSemicolonInserted() {
isSubjectToSemicolonInsertion() and
getLastToken().getValue() != ";"
this.isSubjectToSemicolonInsertion() and
this.getLastToken().getValue() != ";"
}
/** Holds if automatic semicolon insertion applies to this statement. */
@@ -47,8 +47,8 @@ class Stmt extends @stmt, ExprOrStmt, Documentable {
* Holds if this statement is lexically nested inside statement `outer`.
*/
predicate nestedIn(Stmt outer) {
outer = getParentStmt+() or
getContainer().(Expr).getEnclosingStmt().nestedIn(outer)
outer = this.getParentStmt+() or
this.getContainer().(Expr).getEnclosingStmt().nestedIn(outer)
}
/**
@@ -56,10 +56,10 @@ class Stmt extends @stmt, ExprOrStmt, Documentable {
* crossing function boundaries or other `try ` statements with catch blocks.
*/
TryStmt getEnclosingTryCatchStmt() {
getParentStmt+() = result.getBody() and
this.getParentStmt+() = result.getBody() and
exists(result.getACatchClause()) and
not exists(TryStmt mid | exists(mid.getACatchClause()) |
getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result.getBody()
this.getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result.getBody()
)
}
}
@@ -116,7 +116,7 @@ class LoopStmt extends TLoopStmt, ControlStmt {
/** Gets the loop test of this loop. */
abstract Expr getTest();
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
}
/**
@@ -145,13 +145,13 @@ class EmptyStmt extends @empty_stmt, Stmt {
*/
class BlockStmt extends @block_stmt, Stmt {
/** Gets the `i`th statement in this block. */
Stmt getStmt(int i) { result = getChildStmt(i) }
Stmt getStmt(int i) { result = this.getChildStmt(i) }
/** Gets a statement in this block. */
Stmt getAStmt() { result = getStmt(_) }
Stmt getAStmt() { result = this.getStmt(_) }
/** Gets the number of statements in this block. */
int getNumStmt() { result = count(getAStmt()) }
int getNumStmt() { result = count(this.getAStmt()) }
/** Holds if this block is a function body. */
predicate isFunctionBody() { this.getParent() instanceof Function }
@@ -171,9 +171,9 @@ class BlockStmt extends @block_stmt, Stmt {
*/
class ExprStmt extends @expr_stmt, Stmt {
/** Gets the expression of this expression statement. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
override predicate isSubjectToSemicolonInsertion() { not isDoubleColonMethod(_, _, _) }
override predicate isSubjectToSemicolonInsertion() { not this.isDoubleColonMethod(_, _, _) }
/**
* Holds if this expression statement is a JScript-style double colon method declaration.
@@ -182,7 +182,7 @@ class ExprStmt extends @expr_stmt, Stmt {
// the parser converts double colon method declarations into assignments, but we
// can consult token-level information to identify them
exists(Assignment assgn, DotExpr dot, Token tk |
assgn = getExpr() and
assgn = this.getExpr() and
dot = assgn.getLhs() and
interface = dot.getBase() and
// check if the interface name is followed by two colons
@@ -205,7 +205,7 @@ class ExprStmt extends @expr_stmt, Stmt {
* be a directive).
*/
private class MaybeDirective extends ExprStmt {
MaybeDirective() { getExpr() instanceof StringLiteral }
MaybeDirective() { this.getExpr() instanceof StringLiteral }
/**
* Gets the raw text of the string literal wrapped by this statement.
@@ -228,7 +228,7 @@ private class MaybeDirective extends ExprStmt {
* string literal is the same as in the former case.)
*/
string getDirectiveText() {
exists(string text | text = getExpr().(StringLiteral).getRawValue() |
exists(string text | text = this.getExpr().(StringLiteral).getRawValue() |
result = text.substring(1, text.length() - 1)
)
}
@@ -279,7 +279,7 @@ abstract class KnownDirective extends Directive { }
* ```
*/
class StrictModeDecl extends KnownDirective {
StrictModeDecl() { getDirectiveText() = "use strict" }
StrictModeDecl() { this.getDirectiveText() = "use strict" }
}
/**
@@ -292,7 +292,7 @@ class StrictModeDecl extends KnownDirective {
* ```
*/
class ASMJSDirective extends KnownDirective {
ASMJSDirective() { getDirectiveText() = "use asm" }
ASMJSDirective() { this.getDirectiveText() = "use asm" }
}
/**
@@ -305,7 +305,7 @@ class ASMJSDirective extends KnownDirective {
* ```
*/
class BabelDirective extends KnownDirective {
BabelDirective() { getDirectiveText() = "use babel" }
BabelDirective() { this.getDirectiveText() = "use babel" }
}
/**
@@ -318,7 +318,7 @@ class BabelDirective extends KnownDirective {
* ```
*/
class SixToFiveDirective extends KnownDirective {
SixToFiveDirective() { getDirectiveText() = "use 6to5" }
SixToFiveDirective() { this.getDirectiveText() = "use 6to5" }
}
/**
@@ -331,7 +331,9 @@ class SixToFiveDirective extends KnownDirective {
* ```
*/
class SystemJSFormatDirective extends KnownDirective {
SystemJSFormatDirective() { getDirectiveText().regexpMatch("format (cjs|esm|global|register)") }
SystemJSFormatDirective() {
this.getDirectiveText().regexpMatch("format (cjs|esm|global|register)")
}
}
/**
@@ -344,7 +346,7 @@ class SystemJSFormatDirective extends KnownDirective {
* ```
*/
class FormatRegisterDirective extends SystemJSFormatDirective {
FormatRegisterDirective() { getDirectiveText() = "format register" }
FormatRegisterDirective() { this.getDirectiveText() = "format register" }
}
/**
@@ -357,7 +359,7 @@ class FormatRegisterDirective extends SystemJSFormatDirective {
* ```
*/
class NgInjectDirective extends KnownDirective {
NgInjectDirective() { getDirectiveText().regexpMatch("ng(No)?Inject") }
NgInjectDirective() { this.getDirectiveText().regexpMatch("ng(No)?Inject") }
}
/**
@@ -370,7 +372,9 @@ class NgInjectDirective extends KnownDirective {
* ```
*/
class YuiDirective extends KnownDirective {
YuiDirective() { getDirectiveText().regexpMatch("([a-z0-9_]+:nomunge, ?)*([a-z0-9_]+:nomunge)") }
YuiDirective() {
this.getDirectiveText().regexpMatch("([a-z0-9_]+:nomunge, ?)*([a-z0-9_]+:nomunge)")
}
}
/**
@@ -383,7 +387,7 @@ class YuiDirective extends KnownDirective {
* ```
*/
class SystemJSDepsDirective extends KnownDirective {
SystemJSDepsDirective() { getDirectiveText().regexpMatch("deps [^ ]+") }
SystemJSDepsDirective() { this.getDirectiveText().regexpMatch("deps [^ ]+") }
}
/**
@@ -396,7 +400,7 @@ class SystemJSDepsDirective extends KnownDirective {
* ```
*/
class BundleDirective extends KnownDirective {
BundleDirective() { getDirectiveText() = "bundle" }
BundleDirective() { this.getDirectiveText() = "bundle" }
}
/**
@@ -414,26 +418,26 @@ class BundleDirective extends KnownDirective {
*/
class IfStmt extends @if_stmt, ControlStmt {
/** Gets the condition of this `if` statement. */
Expr getCondition() { result = getChildExpr(0) }
Expr getCondition() { result = this.getChildExpr(0) }
/** Gets the "then" branch of this `if` statement. */
Stmt getThen() { result = getChildStmt(1) }
Stmt getThen() { result = this.getChildStmt(1) }
/** Gets the "else" branch of this `if` statement, if any. */
Stmt getElse() { result = getChildStmt(2) }
Stmt getElse() { result = this.getChildStmt(2) }
/** Gets the `if` token of this `if` statement. */
KeywordToken getIfToken() { result = getFirstToken() }
KeywordToken getIfToken() { result = this.getFirstToken() }
/** Gets the `else` token of this `if` statement, if any. */
KeywordToken getElseToken() {
result = getThen().getLastToken().getNextToken() and
result.getIndex() < getLastToken().getIndex()
result = this.getThen().getLastToken().getNextToken() and
result.getIndex() < this.getLastToken().getIndex()
}
override Stmt getAControlledStmt() {
result = getThen() or
result = getElse()
result = this.getThen() or
result = this.getElse()
}
/** Holds if this `if` statement is an `else if` of an outer `if` statement. */
@@ -459,10 +463,10 @@ class IfStmt extends @if_stmt, ControlStmt {
*/
class LabeledStmt extends @labeled_stmt, Stmt {
/** Gets the label of this statement. */
string getLabel() { result = getChildExpr(0).(Identifier).getName() }
string getLabel() { result = this.getChildExpr(0).(Identifier).getName() }
/** Gets the labeled statement of this statement. */
Stmt getStmt() { result = getChildStmt(1) }
Stmt getStmt() { result = this.getChildStmt(1) }
override string getAPrimaryQlClass() { result = "LabeledStmt" }
}
@@ -513,10 +517,10 @@ class JumpStmt extends TJumpStmt, Stmt {
*/
class BreakOrContinueStmt extends TBreakOrContinueStmt, JumpStmt {
/** Gets the label this statement refers to, if any. */
string getTargetLabel() { result = getChildExpr(0).(Identifier).getName() }
string getTargetLabel() { result = this.getChildExpr(0).(Identifier).getName() }
/** Holds if this statement has an explicit target label. */
predicate hasTargetLabel() { exists(getTargetLabel()) }
predicate hasTargetLabel() { exists(this.getTargetLabel()) }
/** Gets the statement this statement breaks out of or continues with. */
override Stmt getTarget() { jump_targets(this, result) }
@@ -565,25 +569,27 @@ class ContinueStmt extends @continue_stmt, BreakOrContinueStmt {
*/
class WithStmt extends @with_stmt, ControlStmt {
/** Gets the controlling expression of this `with` statement. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/** Gets the body of this `with` statement. */
Stmt getBody() { result = getChildStmt(1) }
Stmt getBody() { result = this.getChildStmt(1) }
/**
* Holds if `acc` could refer to a property of the scope object
* introduced by this `with` statement.
*/
predicate mayAffect(VarAccess acc) {
acc.getEnclosingStmt().nestedIn(getBody()) and
acc.getEnclosingStmt().nestedIn(this.getBody()) and
exists(Variable v | v = acc.getVariable() |
v instanceof GlobalVariable
or
exists(ASTNode scopeElt | scopeElt = v.getScope().getScopeElement() | scopeElt = getParent+())
exists(ASTNode scopeElt | scopeElt = v.getScope().getScopeElement() |
scopeElt = this.getParent+()
)
)
}
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
override string getAPrimaryQlClass() { result = "WithStmt" }
}
@@ -608,18 +614,18 @@ class WithStmt extends @with_stmt, ControlStmt {
*/
class SwitchStmt extends @switch_stmt, ControlStmt {
/** Gets the controlling expression of this `switch` statement. */
Expr getExpr() { result = getChildExpr(-1) }
Expr getExpr() { result = this.getChildExpr(-1) }
/** Gets the `i`th `case` clause of this `switch` statement. */
Case getCase(int i) { result = getChildStmt(i) }
Case getCase(int i) { result = this.getChildStmt(i) }
/** Gets a `case` clause of this `switch` statement. */
Case getACase() { result = getCase(_) }
Case getACase() { result = this.getCase(_) }
/** Gets the number of `case` clauses of this `switch` statement. */
int getNumCase() { result = count(getACase()) }
int getNumCase() { result = count(this.getACase()) }
override Case getAControlledStmt() { result = getACase() }
override Case getAControlledStmt() { result = this.getACase() }
override string getAPrimaryQlClass() { result = "SwitchStmt" }
}
@@ -636,13 +642,15 @@ class SwitchStmt extends @switch_stmt, ControlStmt {
*/
class ReturnStmt extends @return_stmt, JumpStmt {
/** Gets the expression specifying the returned value, if any. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/** Gets the target of this `return` statement, which is the enclosing statement container. */
override Function getTarget() { result = getContainer() }
override Function getTarget() { result = this.getContainer() }
override ControlFlowNode getFirstControlFlowNode() {
if exists(getExpr()) then result = getExpr().getFirstControlFlowNode() else result = this
if exists(this.getExpr())
then result = this.getExpr().getFirstControlFlowNode()
else result = this
}
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -661,7 +669,7 @@ class ReturnStmt extends @return_stmt, JumpStmt {
*/
class ThrowStmt extends @throw_stmt, JumpStmt {
/** Gets the expression specifying the value to throw. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/**
* Gets the target of this `throw` statement, which is the closest surrounding
@@ -669,15 +677,17 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
* `try` statement, the target defaults to the enclosing statement container.
*/
override ASTNode getTarget() {
if exists(TryStmt ts | getParentStmt+() = ts.getBody())
if exists(TryStmt ts | this.getParentStmt+() = ts.getBody())
then
getParentStmt+() = result.(TryStmt).getBody() and
not exists(TryStmt mid | getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result)
else result = getContainer()
this.getParentStmt+() = result.(TryStmt).getBody() and
not exists(TryStmt mid |
this.getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result
)
else result = this.getContainer()
}
override ControlFlowNode getFirstControlFlowNode() {
result = getExpr().getFirstControlFlowNode()
result = this.getExpr().getFirstControlFlowNode()
}
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -701,37 +711,37 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
*/
class TryStmt extends @try_stmt, ControlStmt {
/** Gets the body of this `try` statement. */
BlockStmt getBody() { result = getChildStmt(0) }
BlockStmt getBody() { result = this.getChildStmt(0) }
override Stmt getAControlledStmt() {
result = getBody() or
result = getACatchClause() or
result = getFinally()
result = this.getBody() or
result = this.getACatchClause() or
result = this.getFinally()
}
/** Gets the `i`th `catch` clause of this `try` statement, if any. */
CatchClause getCatchClause(int i) {
exists(int idx |
result = getChildStmt(idx) and
result = this.getChildStmt(idx) and
idx >= 1 and
i = idx - 1
)
}
/** Gets a `catch` clause of this `try` statement. */
CatchClause getACatchClause() { result = getCatchClause(_) }
CatchClause getACatchClause() { result = this.getCatchClause(_) }
/** Gets the (unique) unguarded `catch` clause of this `try` statement, if any. */
CatchClause getCatchClause() {
result = getACatchClause() and
result = this.getACatchClause() and
not exists(result.getGuard())
}
/** Gets the number of `catch` clauses of this `try` statement. */
int getNumCatchClause() { result = count(getACatchClause()) }
int getNumCatchClause() { result = count(this.getACatchClause()) }
/** Gets the `finally` block of this `try` statement, if any. */
BlockStmt getFinally() { result = getChildStmt(-1) }
BlockStmt getFinally() { result = this.getChildStmt(-1) }
override string getAPrimaryQlClass() { result = "TryStmt" }
}
@@ -749,11 +759,11 @@ class TryStmt extends @try_stmt, ControlStmt {
*/
class WhileStmt extends @while_stmt, LoopStmt {
/** Gets the loop condition of this `while` loop. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
override Expr getTest() { result = getExpr() }
override Expr getTest() { result = this.getExpr() }
override Stmt getBody() { result = getChildStmt(1) }
override Stmt getBody() { result = this.getChildStmt(1) }
override string getAPrimaryQlClass() { result = "WhileStmt" }
}
@@ -771,11 +781,11 @@ class WhileStmt extends @while_stmt, LoopStmt {
*/
class DoWhileStmt extends @do_while_stmt, LoopStmt {
/** Gets the loop condition of this `do`-`while` loop. */
Expr getExpr() { result = getChildExpr(1) }
Expr getExpr() { result = this.getChildExpr(1) }
override Expr getTest() { result = getExpr() }
override Expr getTest() { result = this.getExpr() }
override Stmt getBody() { result = getChildStmt(0) }
override Stmt getBody() { result = this.getChildStmt(0) }
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -813,16 +823,16 @@ class ExprOrVarDecl extends ASTNode {
class ForStmt extends @for_stmt, LoopStmt {
/** Gets the init part of this `for` loop. */
ExprOrVarDecl getInit() {
result = getChildExpr(0) or
result = getChildStmt(0)
result = this.getChildExpr(0) or
result = this.getChildStmt(0)
}
override Expr getTest() { result = getChildExpr(1) }
override Expr getTest() { result = this.getChildExpr(1) }
/** Gets the update part of this `for` loop. */
Expr getUpdate() { result = getChildExpr(2) }
Expr getUpdate() { result = this.getChildExpr(2) }
override Stmt getBody() { result = getChildStmt(3) }
override Stmt getBody() { result = this.getChildStmt(3) }
override string getAPrimaryQlClass() { result = "ForStmt" }
}
@@ -848,22 +858,22 @@ class EnhancedForLoop extends TEnhancedForLoop, LoopStmt {
* pattern, a property reference, or a variable declaration statement.
*/
ExprOrVarDecl getIterator() {
result = getChildExpr(0) or
result = getChildStmt(0)
result = this.getChildExpr(0) or
result = this.getChildStmt(0)
}
/**
* Gets the default value of the loop's iterator, if any.
*/
Expr getDefault() { result = getChildExpr(-1) }
Expr getDefault() { result = this.getChildExpr(-1) }
/**
* Gets the iterator expression of this `for`-`in` or `for`-`of` loop; this can be
* either a variable access or a variable declarator.
*/
Expr getIteratorExpr() {
result = getIterator() or
result = getIterator().(DeclStmt).getADecl()
result = this.getIterator() or
result = this.getIterator().(DeclStmt).getADecl()
}
/**
@@ -871,29 +881,29 @@ class EnhancedForLoop extends TEnhancedForLoop, LoopStmt {
* expression in this `for`-`in` or `for`-`of` loop.
*/
Expr getLValue() {
result = getIterator() and
result = this.getIterator() and
(result instanceof BindingPattern or result instanceof PropAccess)
or
result = getIterator().(DeclStmt).getADecl().getBindingPattern()
result = this.getIterator().(DeclStmt).getADecl().getBindingPattern()
}
/**
* Gets an iterator variable of this `for`-`in` or `for`-`of` loop.
*/
Variable getAnIterationVariable() {
result = getIterator().(DeclStmt).getADecl().getBindingPattern().getAVariable() or
result = getIterator().(BindingPattern).getAVariable()
result = this.getIterator().(DeclStmt).getADecl().getBindingPattern().getAVariable() or
result = this.getIterator().(BindingPattern).getAVariable()
}
override Expr getTest() { none() }
/** Gets the expression this `for`-`in` or `for`-`of` loop iterates over. */
Expr getIterationDomain() { result = getChildExpr(1) }
Expr getIterationDomain() { result = this.getChildExpr(1) }
override Stmt getBody() { result = getChildStmt(2) }
override Stmt getBody() { result = this.getChildStmt(2) }
override ControlFlowNode getFirstControlFlowNode() {
result = getIteratorExpr().getFirstControlFlowNode()
result = this.getIteratorExpr().getFirstControlFlowNode()
}
}
@@ -993,10 +1003,10 @@ class FunctionDeclStmt extends @function_decl_stmt, Stmt, Function {
*/
class DeclStmt extends @decl_stmt, Stmt {
/** Gets the `i`th declarator in this declaration statement. */
VariableDeclarator getDecl(int i) { result = getChildExpr(i) and i >= 0 }
VariableDeclarator getDecl(int i) { result = this.getChildExpr(i) and i >= 0 }
/** Gets a declarator in this declaration statement. */
VariableDeclarator getADecl() { result = getDecl(_) }
VariableDeclarator getADecl() { result = this.getDecl(_) }
override predicate isSubjectToSemicolonInsertion() {
// exclude variable declarations in the init part of for/for-in/for-of loops
@@ -1052,7 +1062,7 @@ class LetStmt extends @let_stmt, DeclStmt { }
*/
class LegacyLetStmt extends @legacy_let_stmt, DeclStmt {
/** Gets the statement this let statement scopes over. */
Stmt getBody() { result = getChildStmt(-1) }
Stmt getBody() { result = this.getChildStmt(-1) }
override predicate isSubjectToSemicolonInsertion() { none() }
}
@@ -1069,22 +1079,22 @@ class LegacyLetStmt extends @legacy_let_stmt, DeclStmt {
*/
class Case extends @case, Stmt {
/** Gets the test expression of this `case` clause. */
Expr getExpr() { result = getChildExpr(-1) }
Expr getExpr() { result = this.getChildExpr(-1) }
/** Holds if this is a `default` clause. */
predicate isDefault() { not exists(getExpr()) }
predicate isDefault() { not exists(this.getExpr()) }
/** Gets the `i`th statement in this `case` clause. */
Stmt getBodyStmt(int i) { result = getChildStmt(i) }
Stmt getBodyStmt(int i) { result = this.getChildStmt(i) }
/** Gets a statement in this `case` clause. */
Stmt getABodyStmt() { result = getChildStmt(_) }
Stmt getABodyStmt() { result = this.getChildStmt(_) }
/** Gets the number of statements in this `case` clause. */
int getNumBodyStmt() { result = count(getABodyStmt()) }
int getNumBodyStmt() { result = count(this.getABodyStmt()) }
/** Gets the `switch` statement to which this clause belongs. */
SwitchStmt getSwitch() { result = getParent() }
SwitchStmt getSwitch() { result = this.getParent() }
override string getAPrimaryQlClass() { result = "Case" }
}
@@ -1102,12 +1112,12 @@ class Case extends @case, Stmt {
*/
class CatchClause extends @catch_clause, ControlStmt, Parameterized {
/** Gets the body of this `catch` clause. */
BlockStmt getBody() { result = getChildStmt(1) }
BlockStmt getBody() { result = this.getChildStmt(1) }
/** Gets the guard expression of this `catch` clause, if any. */
Expr getGuard() { result = getChildExpr(2) }
Expr getGuard() { result = this.getChildExpr(2) }
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
/** Gets the scope induced by this `catch` clause. */
CatchScope getScope() { result.getCatchClause() = this }

View File

@@ -89,13 +89,13 @@ module StringOps {
*/
private class StartsWith_Native extends Range, DataFlow::MethodCallNode {
StartsWith_Native() {
getMethodName() = "startsWith" and
getNumArgument() = 1
this.getMethodName() = "startsWith" and
this.getNumArgument() = 1
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
}
/**
@@ -126,14 +126,14 @@ module StringOps {
*/
private class StartsWith_IndexOfCoercion extends Range, DataFlow::MethodCallNode {
StartsWith_IndexOfCoercion() {
getMethodName() = "indexOf" and
getNumArgument() = 1 and
this.getMethodName() = "indexOf" and
this.getNumArgument() = 1 and
this.flowsToExpr(any(ConditionGuardNode guard).getTest()) // check for boolean coercion
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
override boolean getPolarity() { result = false }
}
@@ -143,7 +143,7 @@ module StringOps {
*/
private class StartsWith_Library extends Range, DataFlow::CallNode {
StartsWith_Library() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
exists(DataFlow::SourceNode callee | this = callee.getACall() |
callee = LodashUnderscore::member("startsWith")
or
@@ -156,9 +156,9 @@ module StringOps {
)
}
override DataFlow::Node getBaseString() { result = getArgument(0) }
override DataFlow::Node getBaseString() { result = this.getArgument(0) }
override DataFlow::Node getSubstring() { result = getArgument(1) }
override DataFlow::Node getSubstring() { result = this.getArgument(1) }
}
/**
@@ -224,10 +224,10 @@ module StringOps {
*/
class Includes extends InclusionTest {
/** Gets the `A` in `A.includes(B)`. */
DataFlow::Node getBaseString() { result = getContainerNode() }
DataFlow::Node getBaseString() { result = this.getContainerNode() }
/** Gets the `B` in `A.includes(B)`. */
DataFlow::Node getSubstring() { result = getContainedNode() }
DataFlow::Node getSubstring() { result = this.getContainedNode() }
}
/**
@@ -314,13 +314,13 @@ module StringOps {
*/
private class EndsWith_Native extends Range, DataFlow::MethodCallNode {
EndsWith_Native() {
getMethodName() = "endsWith" and
getNumArgument() = 1
this.getMethodName() = "endsWith" and
this.getNumArgument() = 1
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
}
/**
@@ -328,7 +328,7 @@ module StringOps {
*/
private class EndsWith_Library extends Range, DataFlow::CallNode {
EndsWith_Library() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
exists(DataFlow::SourceNode callee | this = callee.getACall() |
callee = LodashUnderscore::member("endsWith")
or
@@ -341,9 +341,9 @@ module StringOps {
)
}
override DataFlow::Node getBaseString() { result = getArgument(0) }
override DataFlow::Node getBaseString() { result = this.getArgument(0) }
override DataFlow::Node getSubstring() { result = getArgument(1) }
override DataFlow::Node getSubstring() { result = this.getArgument(1) }
}
}
@@ -542,7 +542,7 @@ module StringOps {
*/
class ConcatenationRoot extends Concatenation {
pragma[inline]
ConcatenationRoot() { isRoot() }
ConcatenationRoot() { this.isRoot() }
/**
* Gets a leaf in this concatenation tree that this node is the root of.
@@ -561,9 +561,9 @@ module StringOps {
* the result is `"Hello , how are you?"`
*/
string getConstantStringParts() {
result = getStringValue()
result = this.getStringValue()
or
not exists(getStringValue()) and
not exists(this.getStringValue()) and
result =
strictconcat(StringLiteralLike leaf |
leaf = this.(SmallConcatenationRoot).getALeaf().asExpr()
@@ -581,7 +581,7 @@ module StringOps {
*/
private class SmallConcatenationRoot extends ConcatenationRoot {
SmallConcatenationRoot() {
sum(StringLiteralLike leaf | leaf = getALeaf().asExpr() | leaf.getStringValue().length()) <
sum(StringLiteralLike leaf | leaf = this.getALeaf().asExpr() | leaf.getStringValue().length()) <
1000 * 1000
}
}
@@ -607,7 +607,7 @@ module StringOps {
*/
class ConcatenationLeaf extends ConcatenationOperand {
pragma[inline]
ConcatenationLeaf() { isLeaf() }
ConcatenationLeaf() { this.isLeaf() }
}
/**
@@ -616,7 +616,7 @@ module StringOps {
class HtmlConcatenationRoot extends ConcatenationRoot {
pragma[noinline]
HtmlConcatenationRoot() {
getConstantStringParts().regexpMatch("(?s).*</?[a-zA-Z][^\\r\\n<>/]*/?>.*")
this.getConstantStringParts().regexpMatch("(?s).*</?[a-zA-Z][^\\r\\n<>/]*/?>.*")
}
}
@@ -624,7 +624,7 @@ module StringOps {
* A data flow node that is part of an HTML string concatenation.
*/
class HtmlConcatenationNode extends ConcatenationNode {
HtmlConcatenationNode() { getRoot() instanceof HtmlConcatenationRoot }
HtmlConcatenationNode() { this.getRoot() instanceof HtmlConcatenationRoot }
}
/**
@@ -632,7 +632,7 @@ module StringOps {
* and is not itself a concatenation operator.
*/
class HtmlConcatenationLeaf extends ConcatenationLeaf {
HtmlConcatenationLeaf() { getRoot() instanceof HtmlConcatenationRoot }
HtmlConcatenationLeaf() { this.getRoot() instanceof HtmlConcatenationRoot }
}
/**
@@ -659,7 +659,7 @@ module StringOps {
* Gets the AST of the regular expression used in the test, if it can be seen locally.
*/
RegExpTerm getRegExp() {
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
result = this.getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
or
result = super.getRegExpOperand(true).asExpr().(StringLiteral).asRegExp()
}
@@ -712,21 +712,21 @@ module StringOps {
}
private class TestCall extends Range, DataFlow::MethodCallNode {
TestCall() { getMethodName() = "test" }
TestCall() { this.getMethodName() = "test" }
override DataFlow::Node getRegExpOperand(boolean coerced) {
result = getReceiver() and coerced = false
result = this.getReceiver() and coerced = false
}
override DataFlow::Node getStringOperand() { result = getArgument(0) }
override DataFlow::Node getStringOperand() { result = this.getArgument(0) }
}
private class MatchCall extends DataFlow::MethodCallNode {
MatchCall() { getMethodName() = "match" }
MatchCall() { this.getMethodName() = "match" }
}
private class ExecCall extends DataFlow::MethodCallNode {
ExecCall() { getMethodName() = "exec" }
ExecCall() { this.getMethodName() = "exec" }
}
private predicate isCoercedToBoolean(Expr e) {

View File

@@ -37,7 +37,7 @@ class Token extends Locatable, @token {
/** Gets the token preceding this token inside the same toplevel structure, if any. */
Token getPreviousToken() { result.getNextToken() = this }
override string toString() { result = getValue() }
override string toString() { result = this.getValue() }
}
/** An end-of-file token. */

File diff suppressed because it is too large Load Diff

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